package gregtech.api.metatileentity; import static gregtech.GT_Mod.GT_FML_LOGGER; import static gregtech.api.enums.GT_Values.NW; import static gregtech.api.enums.GT_Values.V; import static gregtech.api.objects.XSTR.XSTR_INSTANCE; import appeng.api.networking.IGridNode; import appeng.api.networking.security.IActionHost; import appeng.api.util.AECableType; import appeng.api.util.DimensionalCoord; import appeng.me.helpers.AENetworkProxy; import appeng.me.helpers.IGridProxyable; import appeng.tile.TileEvent; import appeng.tile.events.TileEventType; import com.gtnewhorizon.structurelib.alignment.IAlignment; import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider; import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable; import com.gtnewhorizon.structurelib.alignment.constructable.IConstructableProvider; import cpw.mods.fml.common.Optional; import cpw.mods.fml.relauncher.ReflectionHelper; import gregtech.GT_Mod; import gregtech.api.GregTech_API; import gregtech.api.enums.GT_Values; import gregtech.api.enums.ItemList; import gregtech.api.enums.SoundResource; import gregtech.api.enums.Textures; import gregtech.api.graphs.GenerateNodeMap; import gregtech.api.graphs.GenerateNodeMapPower; import gregtech.api.graphs.Node; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; import gregtech.api.interfaces.tileentity.IDebugableTileEntity; import gregtech.api.interfaces.tileentity.IEnergyConnected; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.interfaces.tileentity.IGregtechWailaProvider; import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine; import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch; import gregtech.api.net.GT_Packet_TileEntity; import gregtech.api.objects.GT_ItemStack; import gregtech.api.util.*; import gregtech.common.GT_Pollution; import ic2.api.Direction; import java.lang.reflect.Field; import java.util.*; import javax.annotation.Nullable; import mcp.mobius.waila.api.IWailaConfigHandler; import mcp.mobius.waila.api.IWailaDataAccessor; import net.minecraft.block.Block; import net.minecraft.block.BlockFire; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.server.MinecraftServer; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.EnumChatFormatting; import net.minecraft.world.EnumSkyBlock; import net.minecraft.world.World; import net.minecraft.world.biome.BiomeGenBase; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTankInfo; /** * NEVER INCLUDE THIS FILE IN YOUR MOD!!! *

* This is the main TileEntity for EVERYTHING. */ @Optional.InterfaceList( value = { @Optional.Interface( iface = "appeng.api.networking.security.IActionHost", modid = "appliedenergistics2", striprefs = true), @Optional.Interface( iface = "appeng.me.helpers.IGridProxyable", modid = "appliedenergistics2", striprefs = true) }) public class BaseMetaTileEntity extends CommonMetaTileEntity implements IGregTechTileEntity, IActionHost, IGridProxyable, IAlignmentProvider, IConstructableProvider, IDebugableTileEntity, IGregtechWailaProvider { private static final Field ENTITY_ITEM_HEALTH_FIELD = ReflectionHelper.findField(EntityItem.class, "health", "field_70291_e"); private final boolean[] mActiveEUInputs = new boolean[] {false, false, false, false, false, false}; private final boolean[] mActiveEUOutputs = new boolean[] {false, false, false, false, false, false}; private final int[] mTimeStatistics = new int[GregTech_API.TICKS_FOR_LAG_AVERAGING]; public long mLastSoundTick = 0; public boolean mWasShutdown = false; protected MetaTileEntity mMetaTileEntity; protected long mStoredEnergy = 0, mStoredSteam = 0; protected int mAverageEUInputIndex = 0, mAverageEUOutputIndex = 0; protected boolean mReleaseEnergy = false; protected long[] mAverageEUInput = new long[] {0, 0, 0, 0, 0}, mAverageEUOutput = new long[] {0, 0, 0, 0, 0}; private boolean mHasEnoughEnergy = true, mRunningThroughTick = false, mInputDisabled = false, mOutputDisabled = false, mMuffler = false, mLockUpgrade = false; private boolean mActive = false, mWorkUpdate = false, mSteamConverter = false, mWorks = true; private boolean oRedstone = false; private byte mColor = 0, oColor = 0, oStrongRedstone = 0, oRedstoneData = 63, oTextureData = 0, oUpdateData = 0, oTexturePage = 0; private byte oLightValueClient = -1, oLightValue = -1, mLightValue = 0, mOtherUpgrades = 0, mFacing = 0, oFacing = 0, mWorkData = 0; private int mDisplayErrorCode = 0, oX = 0, oY = 0, oZ = 0, mTimeStatisticsIndex = 0, mLagWarningCount = 0; private long oOutput = 0, mAcceptedAmperes = Long.MAX_VALUE; private long mLastCheckTick = 0; private String mOwnerName = ""; private UUID mOwnerUuid = GT_Utility.defaultUuid; private NBTTagCompound mRecipeStuff = new NBTTagCompound(); private int cableUpdateDelay = 30; public BaseMetaTileEntity() {} @Override public void writeToNBT(NBTTagCompound aNBT) { try { super.writeToNBT(aNBT); } catch (Throwable e) { GT_FML_LOGGER.error("Encountered CRITICAL ERROR while saving MetaTileEntity.", e); } try { aNBT.setInteger("mID", mID); aNBT.setLong("mStoredSteam", mStoredSteam); aNBT.setLong("mStoredEnergy", mStoredEnergy); writeCoverNBT(aNBT, false); aNBT.setByte("mColor", mColor); aNBT.setByte("mLightValue", mLightValue); aNBT.setByte("mOtherUpgrades", mOtherUpgrades); aNBT.setByte("mWorkData", mWorkData); aNBT.setShort("mFacing", mFacing); aNBT.setString("mOwnerName", mOwnerName); aNBT.setString("mOwnerUuid", mOwnerUuid == null ? "" : mOwnerUuid.toString()); aNBT.setBoolean("mLockUpgrade", mLockUpgrade); aNBT.setBoolean("mMuffler", mMuffler); aNBT.setBoolean("mSteamConverter", mSteamConverter); aNBT.setBoolean("mActive", mActive); aNBT.setBoolean("mWorks", !mWorks); aNBT.setBoolean("mInputDisabled", mInputDisabled); aNBT.setBoolean("mOutputDisabled", mOutputDisabled); aNBT.setTag("GT.CraftingComponents", mRecipeStuff); aNBT.setInteger("nbtVersion", GT_Mod.TOTAL_VERSION); } catch (Throwable e) { GT_FML_LOGGER.error("Encountered CRITICAL ERROR while saving MetaTileEntity.", e); } saveMetaTileNBT(aNBT); } @Override public void readFromNBT(NBTTagCompound aNBT) { super.readFromNBT(aNBT); setInitialValuesAsNBT(aNBT, (short) 0); } @Override public void setInitialValuesAsNBT(NBTTagCompound aNBT, short aID) { if (aNBT == null) { if (aID > 0) mID = aID; else mID = mID > 0 ? mID : 0; if (mID != 0) createNewMetatileEntity(mID); mSidedRedstone = (hasValidMetaTileEntity() && mMetaTileEntity.hasSidedRedstoneOutputBehavior() ? new byte[] {0, 0, 0, 0, 0, 0} : new byte[] {15, 15, 15, 15, 15, 15}); } else { if (aID <= 0) mID = (short) aNBT.getInteger("mID"); else mID = aID; mStoredSteam = aNBT.getLong("mStoredSteam"); mStoredEnergy = aNBT.getLong("mStoredEnergy"); mColor = aNBT.getByte("mColor"); mLightValue = aNBT.getByte("mLightValue"); mWorkData = aNBT.getByte("mWorkData"); mFacing = oFacing = (byte) aNBT.getShort("mFacing"); mOwnerName = aNBT.getString("mOwnerName"); try { mOwnerUuid = UUID.fromString(aNBT.getString("mOwnerUuid")); } catch (IllegalArgumentException e) { mOwnerUuid = null; } mLockUpgrade = aNBT.getBoolean("mLockUpgrade"); mMuffler = aNBT.getBoolean("mMuffler"); mSteamConverter = aNBT.getBoolean("mSteamConverter"); mActive = aNBT.getBoolean("mActive"); mWorks = !aNBT.getBoolean("mWorks"); mInputDisabled = aNBT.getBoolean("mInputDisabled"); mOutputDisabled = aNBT.getBoolean("mOutputDisabled"); mOtherUpgrades = (byte) (aNBT.getByte("mOtherUpgrades") + aNBT.getByte("mBatteries") + aNBT.getByte("mLiBatteries")); mRecipeStuff = aNBT.getCompoundTag("GT.CraftingComponents"); final int nbtVersion = aNBT.getInteger("nbtVersion"); readCoverNBT(aNBT); loadMetaTileNBT(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) if (hasValidMetaTileEntity() && mMetaTileEntity.hasSidedRedstoneOutputBehavior()) mSidedRedstone = new byte[] {0, 0, 0, 0, 0, 0}; else mSidedRedstone = new byte[] {15, 15, 15, 15, 15, 15}; updateCoverBehavior(); } /** * Used for ticking special BaseMetaTileEntities, which need that for Energy Conversion * It's called right before onPostTick() */ public void updateStatus() { // } /** * Called when trying to charge Items */ public void chargeItem(ItemStack aStack) { decreaseStoredEU( GT_ModHandler.chargeElectricItem( aStack, (int) Math.min(Integer.MAX_VALUE, getStoredEU()), (int) Math.min(Integer.MAX_VALUE, mMetaTileEntity.getOutputTier()), false, false), true); } /** * Called when trying to discharge Items */ public void dischargeItem(ItemStack aStack) { increaseStoredEnergyUnits( GT_ModHandler.dischargeElectricItem( aStack, (int) Math.min(Integer.MAX_VALUE, getEUCapacity() - getStoredEU()), (int) Math.min(Integer.MAX_VALUE, mMetaTileEntity.getInputTier()), false, false, false), true); } protected boolean isRainPossible() { BiomeGenBase biome = getBiome(); // see net.minecraft.client.renderer.EntityRenderer.renderRainSnow return biome.rainfall > 0 && (biome.canSpawnLightningBolt() || biome.getEnableSnow()); } @Override public void updateEntity() { super.updateEntity(); if (!hasValidMetaTileEntity()) { if (mMetaTileEntity == null) return; mMetaTileEntity.setBaseMetaTileEntity(this); } mRunningThroughTick = true; long tTime = System.nanoTime(); final boolean aSideServer = isServerSide(); final boolean aSideClient = isClientSide(); try { if (hasValidMetaTileEntity()) { if (mTickTimer++ == 0) { oX = xCoord; oY = yCoord; oZ = zCoord; if (aSideServer) { checkDropCover(); } else { requestCoverDataIfNeeded(); } worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this); mMetaTileEntity.onFirstTick(this); if (!hasValidMetaTileEntity()) { mRunningThroughTick = false; return; } } if (aSideClient) { if (mColor != oColor) { mMetaTileEntity.onColorChangeClient(oColor = mColor); issueTextureUpdate(); } if (mLightValue != oLightValueClient) { worldObj.setLightValue(EnumSkyBlock.Block, xCoord, yCoord, zCoord, mLightValue); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord, yCoord, zCoord); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord + 1, yCoord, zCoord); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord - 1, yCoord, zCoord); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord, yCoord + 1, zCoord); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord, yCoord - 1, zCoord); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord, yCoord, zCoord + 1); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord, yCoord, zCoord - 1); oLightValueClient = mLightValue; issueTextureUpdate(); } if (mNeedsUpdate) { worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); // worldObj.func_147479_m(xCoord, yCoord, zCoord); mNeedsUpdate = false; } } if (aSideServer && mTickTimer > 10) { if (!doCoverThings()) { mRunningThroughTick = false; return; } } if (aSideServer) { if (++mAverageEUInputIndex >= mAverageEUInput.length) mAverageEUInputIndex = 0; if (++mAverageEUOutputIndex >= mAverageEUOutput.length) mAverageEUOutputIndex = 0; mAverageEUInput[mAverageEUInputIndex] = 0; mAverageEUOutput[mAverageEUOutputIndex] = 0; } mMetaTileEntity.onPreTick(this, mTickTimer); if (!hasValidMetaTileEntity()) { mRunningThroughTick = false; return; } if (aSideServer) { if (mRedstone != oRedstone || mTickTimer == 10) { updateCoverBehavior(); oRedstone = mRedstone; issueBlockUpdate(); } if (mTickTimer == 10) joinEnet(); if (xCoord != oX || yCoord != oY || zCoord != oZ) { oX = xCoord; oY = yCoord; oZ = zCoord; issueClientUpdate(); clearTileEntityBuffer(); } if (mFacing != oFacing) { oFacing = mFacing; checkDropCover(); issueBlockUpdate(); } if (mTickTimer > 20 && mMetaTileEntity.isElectric()) { mAcceptedAmperes = 0; if (getOutputVoltage() != oOutput) { oOutput = getOutputVoltage(); } if (mMetaTileEntity.isEnetOutput() || mMetaTileEntity.isEnetInput()) { for (byte i = 0; i < 6; i++) { boolean temp = isEnergyInputSide(i); if (temp != mActiveEUInputs[i]) { mActiveEUInputs[i] = temp; } temp = isEnergyOutputSide(i); if (temp != mActiveEUOutputs[i]) { mActiveEUOutputs[i] = temp; } } } if (mMetaTileEntity.isEnetOutput() && oOutput > 0) { final long tOutputVoltage = Math.max(oOutput, oOutput + (1L << Math.max(0, GT_Utility.getTier(oOutput) - 1))); final long tUsableAmperage = Math.min( getOutputAmperage(), (getStoredEU() - mMetaTileEntity.getMinimumStoredEU()) / tOutputVoltage); if (tUsableAmperage > 0) { final long tEU = tOutputVoltage * Util.emitEnergyToNetwork(oOutput, tUsableAmperage, this); mAverageEUOutput[mAverageEUOutputIndex] += tEU; decreaseStoredEU(tEU, true); } } if (getEUCapacity() > 0) { if (GregTech_API.sMachineFireExplosions && getRandomNumber(1000) == 0) { final Block tBlock = getBlockAtSide((byte) getRandomNumber(6)); if (tBlock instanceof BlockFire) doEnergyExplosion(); } if (!hasValidMetaTileEntity()) { mRunningThroughTick = false; return; } if (getRandomNumber(1000) == 0 && isRainPossible()) { final int precipitationHeightAtSide2 = worldObj.getPrecipitationHeight(xCoord, zCoord - 1); final int precipitationHeightAtSide3 = worldObj.getPrecipitationHeight(xCoord, zCoord + 1); final int precipitationHeightAtSide4 = worldObj.getPrecipitationHeight(xCoord - 1, zCoord); final int precipitationHeightAtSide5 = worldObj.getPrecipitationHeight(xCoord + 1, zCoord); if ((getCoverIDAtSide((byte) 1) == 0 && worldObj.getPrecipitationHeight(xCoord, zCoord) - 2 < yCoord) || (getCoverIDAtSide((byte) 2) == 0 && precipitationHeightAtSide2 - 1 < yCoord && precipitationHeightAtSide2 > -1) || (getCoverIDAtSide((byte) 3) == 0 && precipitationHeightAtSide3 - 1 < yCoord && precipitationHeightAtSide3 > -1) || (getCoverIDAtSide((byte) 4) == 0 && precipitationHeightAtSide4 - 1 < yCoord && precipitationHeightAtSide4 > -1) || (getCoverIDAtSide((byte) 5) == 0 && precipitationHeightAtSide5 - 1 < yCoord && precipitationHeightAtSide5 > -1)) { if (GregTech_API.sMachineRainExplosions && worldObj.isRaining()) { if (getRandomNumber(10) == 0) { try { GT_Mod.achievements.issueAchievement( this.getWorldObj().getPlayerEntityByName(mOwnerName), "badweather"); } catch (Exception ignored) { } GT_Log.exp.println("Machine at: " + this.getXCoord() + " | " + this.getYCoord() + " | " + this.getZCoord() + " DIMID: " + this.worldObj.provider.dimensionId + " explosion due to rain!"); doEnergyExplosion(); } else { GT_Log.exp.println("Machine at: " + this.getXCoord() + " | " + this.getYCoord() + " | " + this.getZCoord() + " DIMID: " + this.worldObj.provider.dimensionId + " set to Fire due to rain!"); setOnFire(); } } if (!hasValidMetaTileEntity()) { mRunningThroughTick = false; return; } if (GregTech_API.sMachineThunderExplosions && worldObj.isThundering() && getRandomNumber(3) == 0) { try { GT_Mod.achievements.issueAchievement( this.getWorldObj().getPlayerEntityByName(mOwnerName), "badweather"); } catch (Exception ignored) { } GT_Log.exp.println("Machine at: " + this.getXCoord() + " | " + this.getYCoord() + " | " + this.getZCoord() + " DIMID: " + this.worldObj.provider.dimensionId + " explosion due to Thunderstorm!"); doEnergyExplosion(); } } } } } if (!hasValidMetaTileEntity()) { mRunningThroughTick = false; return; } } if (aSideServer) { if (mMetaTileEntity.dechargerSlotCount() > 0 && getStoredEU() < getEUCapacity()) { for (int i = mMetaTileEntity.dechargerSlotStartIndex(), k = mMetaTileEntity.dechargerSlotCount() + i; i < k; i++) { if (mMetaTileEntity.mInventory[i] != null && getStoredEU() < getEUCapacity()) { dischargeItem(mMetaTileEntity.mInventory[i]); if (ic2.api.info.Info.itemEnergy.getEnergyValue(mMetaTileEntity.mInventory[i]) > 0) { if ((getStoredEU() + ic2.api.info.Info.itemEnergy.getEnergyValue( mMetaTileEntity.mInventory[i])) < getEUCapacity()) { increaseStoredEnergyUnits( (long) ic2.api.info.Info.itemEnergy.getEnergyValue( mMetaTileEntity.mInventory[i]), false); mMetaTileEntity.mInventory[i].stackSize--; mInventoryChanged = true; } } if (mMetaTileEntity.mInventory[i].stackSize <= 0) { mMetaTileEntity.mInventory[i] = null; mInventoryChanged = true; } } } } } if (aSideServer) { if (mMetaTileEntity.rechargerSlotCount() > 0 && getStoredEU() > 0) { for (int i = mMetaTileEntity.rechargerSlotStartIndex(), k = mMetaTileEntity.rechargerSlotCount() + i; i < k; i++) { if (getStoredEU() > 0 && mMetaTileEntity.mInventory[i] != null) { chargeItem(mMetaTileEntity.mInventory[i]); if (mMetaTileEntity.mInventory[i].stackSize <= 0) { mMetaTileEntity.mInventory[i] = null; mInventoryChanged = true; } } } } } updateStatus(); if (!hasValidMetaTileEntity()) { mRunningThroughTick = false; return; } mMetaTileEntity.onPostTick(this, mTickTimer); if (!hasValidMetaTileEntity()) { mRunningThroughTick = false; return; } if (aSideServer) { if (mTickTimer > 20 && cableUpdateDelay == 0) { generatePowerNodes(); } cableUpdateDelay--; if (mTickTimer % 10 == 0) { sendClientData(); } if (mTickTimer > 10) { byte tData = (byte) ((mFacing & 7) | (mActive ? 8 : 0) | (mRedstone ? 16 : 0) | (mLockUpgrade ? 32 : 0) | (mWorks ? 64 : 0)); if (tData != oTextureData) sendBlockEvent(GregTechTileClientEvents.CHANGE_COMMON_DATA, oTextureData = tData); tData = mMetaTileEntity.getUpdateData(); if (tData != oUpdateData) sendBlockEvent(GregTechTileClientEvents.CHANGE_CUSTOM_DATA, oUpdateData = tData); if (mMetaTileEntity instanceof GT_MetaTileEntity_Hatch) { tData = ((GT_MetaTileEntity_Hatch) mMetaTileEntity).getTexturePage(); if (tData != oTexturePage) sendBlockEvent(GregTechTileClientEvents.CHANGE_CUSTOM_DATA, (byte) ((oTexturePage = tData) | 0x80)); // set last bit as a flag for page } if (mColor != oColor) sendBlockEvent(GregTechTileClientEvents.CHANGE_COLOR, oColor = mColor); tData = (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 (tData != oRedstoneData) sendBlockEvent(GregTechTileClientEvents.CHANGE_REDSTONE_OUTPUT, oRedstoneData = tData); if (mLightValue != oLightValue) { worldObj.setLightValue(EnumSkyBlock.Block, xCoord, yCoord, zCoord, mLightValue); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord, yCoord, zCoord); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord + 1, yCoord, zCoord); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord - 1, yCoord, zCoord); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord, yCoord + 1, zCoord); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord, yCoord - 1, zCoord); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord, yCoord, zCoord + 1); worldObj.updateLightByType(EnumSkyBlock.Block, xCoord, yCoord, zCoord - 1); issueTextureUpdate(); sendBlockEvent(GregTechTileClientEvents.CHANGE_LIGHT, oLightValue = mLightValue); } } if (mNeedsBlockUpdate) { updateNeighbours(mStrongRedstone, oStrongRedstone); oStrongRedstone = mStrongRedstone; mNeedsBlockUpdate = false; } } } } catch (Throwable e) { e.printStackTrace(); e.printStackTrace(GT_Log.err); } if (aSideServer && hasValidMetaTileEntity()) { tTime = System.nanoTime() - tTime; if (mTimeStatistics.length > 0) mTimeStatistics[mTimeStatisticsIndex = (mTimeStatisticsIndex + 1) % mTimeStatistics.length] = (int) tTime; if (tTime > 0 && tTime > (GregTech_API.MILLISECOND_THRESHOLD_UNTIL_LAG_WARNING * 1000000L) && mTickTimer > 1000 && getMetaTileEntity().doTickProfilingMessageDuringThisTick() && mLagWarningCount++ < 10) GT_FML_LOGGER.warn("WARNING: Possible Lag Source at [" + xCoord + ", " + yCoord + ", " + zCoord + "] in Dimension " + worldObj.provider.dimensionId + " with " + tTime + "ns caused by an instance of " + getMetaTileEntity().getClass()); } mWorkUpdate = mInventoryChanged = mRunningThroughTick = false; } @Override public void getWailaBody( ItemStack itemStack, List currenttip, IWailaDataAccessor accessor, IWailaConfigHandler config) { if (hasValidMetaTileEntity() && getMetaTileEntity() != null) { getMetaTileEntity().getWailaBody(itemStack, currenttip, accessor, config); } super.getWailaBody(itemStack, currenttip, accessor, config); } @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); if (hasValidMetaTileEntity() && getMetaTileEntity() != null) { getMetaTileEntity().getWailaNBTData(player, tile, tag, world, x, y, z); } } private void sendClientData() { if (mSendClientData) { NW.sendPacketToAllPlayersInRange( worldObj, new GT_Packet_TileEntity( xCoord, (short) yCoord, zCoord, mID, mCoverSides[0], mCoverSides[1], mCoverSides[2], mCoverSides[3], mCoverSides[4], mCoverSides[5], oTextureData = (byte) ((mFacing & 7) | (mActive ? 8 : 0) | (mRedstone ? 16 : 0) | (mLockUpgrade ? 32 : 0) | (mWorks ? 64 : 0)), oTexturePage = (hasValidMetaTileEntity() && mMetaTileEntity instanceof GT_MetaTileEntity_Hatch) ? ((GT_MetaTileEntity_Hatch) mMetaTileEntity).getTexturePage() : 0, oUpdateData = hasValidMetaTileEntity() ? mMetaTileEntity.getUpdateData() : 0, oRedstoneData = (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)), oColor = mColor), xCoord, zCoord); mSendClientData = false; } sendCoverDataIfNeeded(); } public final void receiveMetaTileEntityData( short aID, int aCover0, int aCover1, int aCover2, int aCover3, int aCover4, int aCover5, byte aTextureData, byte aTexturePage, byte aUpdateData, byte aRedstoneData, byte aColorData) { issueTextureUpdate(); if (mID != aID && aID > 0) { mID = aID; createNewMetatileEntity(mID); } setCoverIDAtSide((byte) 0, aCover0); setCoverIDAtSide((byte) 1, aCover1); setCoverIDAtSide((byte) 2, aCover2); setCoverIDAtSide((byte) 3, aCover3); setCoverIDAtSide((byte) 4, aCover4); setCoverIDAtSide((byte) 5, aCover5); receiveClientEvent(GregTechTileClientEvents.CHANGE_COMMON_DATA, aTextureData); receiveClientEvent(GregTechTileClientEvents.CHANGE_CUSTOM_DATA, aUpdateData & 0x7F); receiveClientEvent(GregTechTileClientEvents.CHANGE_CUSTOM_DATA, aTexturePage | 0x80); receiveClientEvent(GregTechTileClientEvents.CHANGE_COLOR, aColorData); receiveClientEvent(GregTechTileClientEvents.CHANGE_REDSTONE_OUTPUT, aRedstoneData); } @Deprecated public final void receiveMetaTileEntityData( short aID, int aCover0, int aCover1, int aCover2, int aCover3, int aCover4, int aCover5, byte aTextureData, byte aUpdateData, byte aRedstoneData, byte aColorData) { receiveMetaTileEntityData( aID, aCover0, aCover1, aCover2, aCover3, aCover4, aCover5, aTextureData, (byte) 0, aUpdateData, aRedstoneData, aColorData); } @Override public boolean receiveClientEvent(int aEventID, int aValue) { super.receiveClientEvent(aEventID, aValue); if (hasValidMetaTileEntity()) { try { mMetaTileEntity.receiveClientEvent((byte) aEventID, (byte) aValue); } catch (Throwable e) { GT_Log.err.println( "Encountered Exception while receiving Data from the Server, the Client should've been crashed by now, but I prevented that. Please report immediately to GregTech Intergalactical!!!"); e.printStackTrace(GT_Log.err); } } 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 (hasValidMetaTileEntity()) { if ((aValue & 0x80) == 0) // Is texture index mMetaTileEntity.onValueUpdate((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 (hasValidMetaTileEntity() && mTickTimer > 20) mMetaTileEntity.doSound((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5); break; case GregTechTileClientEvents.START_SOUND_LOOP: if (hasValidMetaTileEntity() && mTickTimer > 20) mMetaTileEntity.startSoundLoop((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5); break; case GregTechTileClientEvents.STOP_SOUND_LOOP: if (hasValidMetaTileEntity() && mTickTimer > 20) mMetaTileEntity.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 ArrayList getDebugInfo(EntityPlayer aPlayer, int aLogLevel) { final ArrayList tList = new ArrayList<>(); if (aLogLevel > 2) { tList.add("Meta-ID: " + EnumChatFormatting.BLUE + mID + EnumChatFormatting.RESET + (canAccessData() ? EnumChatFormatting.GREEN + " valid" + EnumChatFormatting.RESET : EnumChatFormatting.RED + " invalid" + EnumChatFormatting.RESET) + (mMetaTileEntity == null ? EnumChatFormatting.RED + " MetaTileEntity == null!" + EnumChatFormatting.RESET : " ")); } if (aLogLevel > 1) { if (mTimeStatistics.length > 0) { double tAverageTime = 0; double tWorstTime = 0; for (int tTime : mTimeStatistics) { tAverageTime += tTime; if (tTime > tWorstTime) { tWorstTime = tTime; } // Uncomment this line to print out tick-by-tick times. // tList.add("tTime " + tTime); } tList.add("Average CPU load of ~" + GT_Utility.formatNumbers(tAverageTime / mTimeStatistics.length) + "ns over " + GT_Utility.formatNumbers(mTimeStatistics.length) + " ticks with worst time of " + GT_Utility.formatNumbers(tWorstTime) + "ns."); tList.add("Recorded " + GT_Utility.formatNumbers(mMetaTileEntity.mSoundRequests) + " sound requests in " + GT_Utility.formatNumbers(mTickTimer - mLastCheckTick) + " ticks."); mLastCheckTick = mTickTimer; mMetaTileEntity.mSoundRequests = 0; } if (mLagWarningCount > 0) { tList.add("Caused " + (mLagWarningCount >= 10 ? "more than 10" : mLagWarningCount) + " Lag Spike Warnings (anything taking longer than " + GregTech_API.MILLISECOND_THRESHOLD_UNTIL_LAG_WARNING + "ms) on the Server."); } tList.add("Is" + (mMetaTileEntity.isAccessAllowed(aPlayer) ? " " : EnumChatFormatting.RED + " not " + EnumChatFormatting.RESET) + "accessible for you"); } if (aLogLevel > 0) { if (getSteamCapacity() > 0 && hasSteamEngineUpgrade()) tList.add(GT_Utility.formatNumbers(getStoredSteam()) + " of " + GT_Utility.formatNumbers(getSteamCapacity()) + " Steam"); tList.add("Machine is " + (mActive ? EnumChatFormatting.GREEN + "active" + EnumChatFormatting.RESET : EnumChatFormatting.RED + "inactive" + EnumChatFormatting.RESET)); if (!mHasEnoughEnergy) tList.add( EnumChatFormatting.RED + "ATTENTION: This Device needs more power." + EnumChatFormatting.RESET); } if (joinedIc2Enet) tList.add("Joined IC2 ENet"); return mMetaTileEntity.getSpecialDebugInfo(this, aPlayer, aLogLevel, tList); } @Override public boolean isGivingInformation() { if (canAccessData()) return mMetaTileEntity.isGivingInformation(); return false; } @Override public byte getBackFacing() { return GT_Utility.getOppositeSide(mFacing); } @Override public byte getFrontFacing() { return mFacing; } @Override public void setFrontFacing(byte aFacing) { if (isValidFacing(aFacing)) { mFacing = aFacing; mMetaTileEntity.onFacingChange(); doEnetUpdate(); cableUpdateDelay = 10; if (mMetaTileEntity.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(); } } } @Override public int getSizeInventory() { if (canAccessData()) return mMetaTileEntity.getSizeInventory(); return 0; } @Override public ItemStack getStackInSlot(int aIndex) { if (canAccessData()) return mMetaTileEntity.getStackInSlot(aIndex); return null; } @Override public void setInventorySlotContents(int aIndex, ItemStack aStack) { mInventoryChanged = true; if (canAccessData()) { markDirty(); mMetaTileEntity.setInventorySlotContents( aIndex, worldObj.isRemote ? aStack : GT_OreDictUnificator.setStack(true, aStack)); } } @Override public String getInventoryName() { if (canAccessData()) return mMetaTileEntity.getInventoryName(); if (GregTech_API.METATILEENTITIES[mID] != null) return GregTech_API.METATILEENTITIES[mID].getInventoryName(); return ""; } @Override public int getInventoryStackLimit() { if (canAccessData()) return mMetaTileEntity.getInventoryStackLimit(); return 64; } @Override public void openInventory() { if (canAccessData()) mMetaTileEntity.onOpenGUI(); } @Override public void closeInventory() { if (canAccessData()) mMetaTileEntity.onCloseGUI(); } @Override public boolean isUseableByPlayer(EntityPlayer aPlayer) { return canAccessData() && playerOwnsThis(aPlayer, false) && mTickTimer > 40 && getTileEntityOffset(0, 0, 0) == this && aPlayer.getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) < 64 && mMetaTileEntity.isAccessAllowed(aPlayer); } @Override public void validate() { super.validate(); mTickTimer = 0; } @Override public void invalidate() { tileEntityInvalid = false; leaveEnet(); if (canAccessData()) { if (GregTech_API.mAE2) invalidateAE(); mMetaTileEntity.onRemoval(); mMetaTileEntity.setBaseMetaTileEntity(null); } super.invalidate(); } @Override public void onChunkUnload() { super.onChunkUnload(); if (GregTech_API.mAE2) onChunkUnloadAE(); } @Override public boolean hasCustomInventoryName() { return false; } @Override public ItemStack getStackInSlotOnClosing(int slot) { final ItemStack stack = getStackInSlot(slot); if (stack != null) setInventorySlotContents(slot, null); return stack; } /** * Checks validity of meta tile and delegates to it */ @Override public void onMachineBlockUpdate() { if (canAccessData()) mMetaTileEntity.onMachineBlockUpdate(); cableUpdateDelay = 10; } /** * Checks validity of meta tile and delegates to it */ @Override public boolean isMachineBlockUpdateRecursive() { return canAccessData() && mMetaTileEntity.isMachineBlockUpdateRecursive(); } @Override public int getProgress() { return canAccessData() ? mMetaTileEntity.getProgresstime() : 0; } @Override public int getMaxProgress() { return canAccessData() ? mMetaTileEntity.maxProgresstime() : 0; } @Override public boolean increaseProgress(int aProgressAmountInTicks) { return canAccessData() && mMetaTileEntity.increaseProgress(aProgressAmountInTicks) != aProgressAmountInTicks; } @Override public boolean hasThingsToDo() { return getMaxProgress() > 0; } @Override public void enableWorking() { if (!mWorks) mWorkUpdate = true; mWorks = true; mWasShutdown = false; } @Override public void disableWorking() { mWorks = false; } @Override public boolean isAllowedToWork() { return mWorks; } @Override public boolean hasWorkJustBeenEnabled() { return mWorkUpdate; } @Override public byte getWorkDataValue() { return mWorkData; } @Override public void setWorkDataValue(byte aValue) { mWorkData = aValue; } @Override public int getMetaTileID() { return mID; } @Override public int setMetaTileID(short aID) { return mID = aID; } @Override public boolean isActive() { return mActive; } @Override public void setActive(boolean aActive) { mActive = aActive; } @Override public long getTimer() { return mTickTimer; } @Override public boolean decreaseStoredEnergyUnits(long aEnergy, boolean aIgnoreTooLessEnergy) { if (!canAccessData()) return false; return mHasEnoughEnergy = decreaseStoredEU(aEnergy, aIgnoreTooLessEnergy) || decreaseStoredSteam(aEnergy, false) || (aIgnoreTooLessEnergy && (decreaseStoredSteam(aEnergy, true))); } @Override public boolean increaseStoredEnergyUnits(long aEnergy, boolean aIgnoreTooMuchEnergy) { if (!canAccessData()) return false; if (getStoredEU() < getEUCapacity() || aIgnoreTooMuchEnergy) { setStoredEU(mMetaTileEntity.getEUVar() + aEnergy); return true; } return false; } @Override public boolean inputEnergyFrom(byte aSide) { return inputEnergyFrom(aSide, true); } @Override public boolean inputEnergyFrom(byte aSide, boolean waitForActive) { if (aSide == 6) return true; if (isServerSide() && waitForActive) return ((aSide >= 0 && aSide < 6) && mActiveEUInputs[aSide]) && !mReleaseEnergy; return isEnergyInputSide(aSide); } @Override public boolean outputsEnergyTo(byte aSide) { return outputsEnergyTo(aSide, true); } @Override public boolean outputsEnergyTo(byte aSide, boolean waitForActive) { if (aSide == 6) return true; if (isServerSide() && waitForActive) return ((aSide >= 0 && aSide < 6) && mActiveEUOutputs[aSide]) || mReleaseEnergy; return isEnergyOutputSide(aSide); } @Override public boolean isEnetOutput() { return mMetaTileEntity != null && mMetaTileEntity.isEnetOutput(); } @Override public boolean isEnetInput() { return mMetaTileEntity != null && mMetaTileEntity.isEnetInput(); } public void generatePowerNodes() { if (isServerSide() && (isEnetInput() || isEnetOutput())) { final int time = MinecraftServer.getServer().getTickCounter(); for (byte i = 0; i < 6; i++) { if (outputsEnergyTo(i, false) || inputEnergyFrom(i, false)) { final IGregTechTileEntity TE = getIGregTechTileEntityAtSide(i); if (TE instanceof BaseMetaPipeEntity) { final Node node = ((BaseMetaPipeEntity) TE).getNode(); if (node == null) { new GenerateNodeMapPower((BaseMetaPipeEntity) TE); } else if (node.mCreationTime != time) { GenerateNodeMap.clearNodeMap(node, -1); new GenerateNodeMapPower((BaseMetaPipeEntity) TE); } } } } } } @Override public long getOutputAmperage() { if (canAccessData() && mMetaTileEntity.isElectric()) return mMetaTileEntity.maxAmperesOut(); return 0; } @Override public long getOutputVoltage() { if (canAccessData() && mMetaTileEntity.isElectric() && mMetaTileEntity.isEnetOutput()) return mMetaTileEntity.maxEUOutput(); return 0; } @Override public long getInputAmperage() { if (canAccessData() && mMetaTileEntity.isElectric()) return mMetaTileEntity.maxAmperesIn(); return 0; } @Override public long getInputVoltage() { if (canAccessData() && mMetaTileEntity.isElectric()) return mMetaTileEntity.maxEUInput(); return Integer.MAX_VALUE; } @Override public boolean increaseStoredSteam(long aEnergy, boolean aIgnoreTooMuchEnergy) { if (!canAccessData()) return false; if (mMetaTileEntity.getSteamVar() < getSteamCapacity() || aIgnoreTooMuchEnergy) { setStoredSteam(mMetaTileEntity.getSteamVar() + aEnergy); return true; } return false; } @Override public long getUniversalEnergyStored() { return Math.max(getStoredEU(), getStoredSteam()); } @Override public long getUniversalEnergyCapacity() { return Math.max(getEUCapacity(), getSteamCapacity()); } @Override public long getStoredEU() { if (canAccessData()) return Math.min(mMetaTileEntity.getEUVar(), getEUCapacity()); return 0; } @Override public long getEUCapacity() { if (canAccessData()) return mMetaTileEntity.maxEUStore(); return 0; } @Override public long getStoredSteam() { if (canAccessData()) return Math.min(mMetaTileEntity.getSteamVar(), getSteamCapacity()); return 0; } @Override public long getSteamCapacity() { if (canAccessData()) return mMetaTileEntity.maxSteamStore(); return 0; } @Override public ITexture[] getTexture(Block aBlock, byte aSide) { final ITexture coverTexture = getCoverTexture(aSide); final ITexture[] textureUncovered = hasValidMetaTileEntity() ? mMetaTileEntity.getTexture( this, aSide, mFacing, (byte) (mColor - 1), mActive, getOutputRedstoneSignal(aSide) > 0) : Textures.BlockIcons.ERROR_RENDERING; final ITexture[] textureCovered; if (coverTexture != null) { textureCovered = Arrays.copyOf(textureUncovered, textureUncovered.length + 1); textureCovered[textureUncovered.length] = coverTexture; return textureCovered; } else { return textureUncovered; } } private boolean isEnergyInputSide(byte aSide) { if (aSide >= 0 && aSide < 6) { if (!getCoverBehaviorAtSideNew(aSide) .letsEnergyIn(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this)) return false; if (isInvalid() || mReleaseEnergy) return false; if (canAccessData() && mMetaTileEntity.isElectric() && mMetaTileEntity.isEnetInput()) return mMetaTileEntity.isInputFacing(aSide); } return false; } private boolean isEnergyOutputSide(byte aSide) { if (aSide >= 0 && aSide < 6) { if (!getCoverBehaviorAtSideNew(aSide) .letsEnergyOut(aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this)) return false; if (isInvalid() || mReleaseEnergy) return mReleaseEnergy; if (canAccessData() && mMetaTileEntity.isElectric() && mMetaTileEntity.isEnetOutput()) return mMetaTileEntity.isOutputFacing(aSide); } return false; } @Override protected boolean hasValidMetaTileEntity() { return mMetaTileEntity != null && mMetaTileEntity.getBaseMetaTileEntity() == this; } @Override protected boolean canAccessData() { return !isDead && hasValidMetaTileEntity(); } public boolean setStoredEU(long aEnergy) { if (!canAccessData()) return false; if (aEnergy < 0) aEnergy = 0; mMetaTileEntity.setEUVar(aEnergy); return true; } public boolean setStoredSteam(long aEnergy) { if (!canAccessData()) return false; if (aEnergy < 0) aEnergy = 0; mMetaTileEntity.setSteamVar(aEnergy); return true; } public boolean decreaseStoredEU(long aEnergy, boolean aIgnoreTooLessEnergy) { if (!canAccessData()) { return false; } if (mMetaTileEntity.getEUVar() - aEnergy >= 0 || aIgnoreTooLessEnergy) { setStoredEU(mMetaTileEntity.getEUVar() - aEnergy); if (mMetaTileEntity.getEUVar() < 0) { setStoredEU(0); return false; } return true; } return false; } public boolean decreaseStoredSteam(long aEnergy, boolean aIgnoreTooLessEnergy) { if (!canAccessData()) return false; if (mMetaTileEntity.getSteamVar() - aEnergy >= 0 || aIgnoreTooLessEnergy) { setStoredSteam(mMetaTileEntity.getSteamVar() - aEnergy); if (mMetaTileEntity.getSteamVar() < 0) { setStoredSteam(0); return false; } return true; } return false; } public boolean playerOwnsThis(EntityPlayer aPlayer, boolean aCheckPrecicely) { if (!canAccessData()) return false; 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; } public boolean privateAccess() { if (!canAccessData()) return mLockUpgrade; return mLockUpgrade || mMetaTileEntity.ownerControl(); } public void doEnergyExplosion() { if (getUniversalEnergyCapacity() > 0 && getUniversalEnergyStored() >= getUniversalEnergyCapacity() / 5) { GT_Log.exp.println("Energy Explosion, injected " + getUniversalEnergyStored() + "EU >= " + getUniversalEnergyCapacity() / 5D + "Capacity of the Machine!"); doExplosion(oOutput * (getUniversalEnergyStored() >= getUniversalEnergyCapacity() ? 4 : getUniversalEnergyStored() >= getUniversalEnergyCapacity() / 2 ? 2 : 1)); GT_Mod.achievements.issueAchievement( this.getWorldObj().getPlayerEntityByName(mOwnerName), "electricproblems"); } } @Override public void doExplosion(long aAmount) { if (canAccessData()) { // This is only for Electric Machines if (GregTech_API.sMachineWireFire && mMetaTileEntity.isElectric()) { try { mReleaseEnergy = true; IEnergyConnected.Util.emitEnergyToNetwork(V[5], Math.max(1, getStoredEU() / V[5]), this); } catch (Exception ignored) { } } mReleaseEnergy = false; // Normal Explosion Code mMetaTileEntity.onExplosion(); if (GT_Mod.gregtechproxy.mExplosionItemDrop) { for (int i = 0; i < this.getSizeInventory(); i++) { final ItemStack tItem = this.getStackInSlot(i); if ((tItem != null) && (tItem.stackSize > 0) && (this.isValidSlot(i))) { dropItems(tItem); this.setInventorySlotContents(i, null); } } } if (mRecipeStuff != null) { for (int i = 0; i < 9; i++) { if (this.getRandomNumber(100) < 50) { dropItems(GT_Utility.loadItem(mRecipeStuff, "Ingredient." + i)); } } } GT_Pollution.addPollution(this, GT_Mod.gregtechproxy.mPollutionOnExplosion); mMetaTileEntity.doExplosion(aAmount); } } public void dropItems(ItemStack tItem) { if (tItem == null) return; final EntityItem tItemEntity = new EntityItem( this.worldObj, this.xCoord + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F, this.yCoord + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F, this.zCoord + XSTR_INSTANCE.nextFloat() * 0.8F + 0.1F, new ItemStack(tItem.getItem(), tItem.stackSize, tItem.getItemDamage())); if (tItem.hasTagCompound()) { tItemEntity.getEntityItem().setTagCompound((NBTTagCompound) tItem.getTagCompound().copy()); } tItemEntity.motionX = (XSTR_INSTANCE.nextGaussian() * 0.0500000007450581D); tItemEntity.motionY = (XSTR_INSTANCE.nextGaussian() * 0.0500000007450581D + 0.2000000029802322D); tItemEntity.motionZ = (XSTR_INSTANCE.nextGaussian() * 0.0500000007450581D); tItemEntity.hurtResistantTime = 999999; tItemEntity.lifespan = 60000; try { if (ENTITY_ITEM_HEALTH_FIELD != null) ENTITY_ITEM_HEALTH_FIELD.setInt(tItemEntity, 99999999); } catch (Exception ignored) { } this.worldObj.spawnEntityInWorld(tItemEntity); tItem.stackSize = 0; } @Override public ArrayList getDrops() { final ItemStack rStack = new ItemStack(GregTech_API.sBlockMachines, 1, mID); final NBTTagCompound tNBT = new NBTTagCompound(); if (mRecipeStuff != null && !mRecipeStuff.hasNoTags()) tNBT.setTag("GT.CraftingComponents", mRecipeStuff); if (mMuffler) tNBT.setBoolean("mMuffler", mMuffler); if (mLockUpgrade) tNBT.setBoolean("mLockUpgrade", mLockUpgrade); if (mSteamConverter) tNBT.setBoolean("mSteamConverter", mSteamConverter); if (mColor > 0) tNBT.setByte("mColor", mColor); if (mOtherUpgrades > 0) tNBT.setByte("mOtherUpgrades", mOtherUpgrades); writeCoverNBT(tNBT, true); if (hasValidMetaTileEntity()) mMetaTileEntity.setItemNBT(tNBT); if (!tNBT.hasNoTags()) rStack.setTagCompound(tNBT); onBaseTEDestroyed(); return new ArrayList<>(Collections.singletonList(rStack)); } @Override public boolean shouldDropItemAt(int index) { return this.mMetaTileEntity != null ? this.mMetaTileEntity.shouldDropItemAt(index) : true; } public int getUpgradeCount() { return (mMuffler ? 1 : 0) + (mLockUpgrade ? 1 : 0) + (mSteamConverter ? 1 : 0) + mOtherUpgrades; } @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(); if (tCurrentItem != null) { if (getColorization() >= 0 && GT_Utility.areStacksEqual(new ItemStack(Items.water_bucket, 1), tCurrentItem)) { tCurrentItem.func_150996_a(Items.bucket); setColorization((byte) (getColorization() >= 16 ? -2 : -1)); return true; } if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWrenchList)) { if (aPlayer.isSneaking() && mMetaTileEntity instanceof GT_MetaTileEntity_BasicMachine && ((GT_MetaTileEntity_BasicMachine) mMetaTileEntity) .setMainFacing(GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ))) { GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer); GT_Utility.sendSoundToPlayers( worldObj, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1, xCoord, yCoord, zCoord); cableUpdateDelay = 10; } else if (mMetaTileEntity.onWrenchRightClick( aSide, GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ), aPlayer, aX, aY, aZ)) { GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer); GT_Utility.sendSoundToPlayers( worldObj, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1, xCoord, yCoord, zCoord); cableUpdateDelay = 10; } return true; } if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sScrewdriverList)) { if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 200, aPlayer)) { setCoverDataAtSide( aSide, getCoverBehaviorAtSideNew(aSide) .onCoverScrewdriverClick( aSide, getCoverIDAtSide(aSide), getComplexCoverDataAtSide(aSide), this, aPlayer, aX, aY, aZ)); mMetaTileEntity.onScrewdriverRightClick(aSide, aPlayer, aX, aY, aZ); GT_Utility.sendSoundToPlayers( worldObj, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1, xCoord, yCoord, zCoord); } return true; } if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sHardHammerList)) { if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer)) { mInputDisabled = !mInputDisabled; if (mInputDisabled) mOutputDisabled = !mOutputDisabled; GT_Utility.sendChatToPlayer( aPlayer, GT_Utility.trans("086", "Auto-Input: ") + (mInputDisabled ? GT_Utility.trans("087", "Disabled") : GT_Utility.trans("088", "Enabled") + GT_Utility.trans("089", " Auto-Output: ") + (mOutputDisabled ? GT_Utility.trans("087", "Disabled") : GT_Utility.trans("088", "Enabled")))); GT_Utility.sendSoundToPlayers( worldObj, SoundResource.RANDOM_ANVIL_USE, 1.0F, -1, xCoord, yCoord, zCoord); } return true; } if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSoftHammerList)) { if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer)) { if (mWorks) disableWorking(); else enableWorking(); { String tChat = GT_Utility.trans("090", "Machine Processing: ") + (isAllowedToWork() ? GT_Utility.trans("088", "Enabled") : GT_Utility.trans("087", "Disabled")); if (getMetaTileEntity() != null && getMetaTileEntity().hasAlternativeModeText()) tChat = getMetaTileEntity().getAlternativeModeText(); GT_Utility.sendChatToPlayer(aPlayer, tChat); } GT_Utility.sendSoundToPlayers( worldObj, SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE, 1.0F, -1, xCoord, yCoord, zCoord); } return true; } if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSolderingToolList)) { final byte tSide = GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ); if (mMetaTileEntity.onSolderingToolRightClick(aSide, tSide, aPlayer, aX, aY, aZ)) { // logic handled internally GT_Utility.sendSoundToPlayers( worldObj, SoundResource.IC2_TOOLS_BATTERY_USE, 1.0F, -1, xCoord, yCoord, zCoord); } else if (GT_ModHandler.useSolderingIron(tCurrentItem, aPlayer)) { mStrongRedstone ^= (1 << tSide); GT_Utility.sendChatToPlayer( aPlayer, GT_Utility.trans("091", "Redstone Output at Side ") + tSide + GT_Utility.trans("092", " set to: ") + ((mStrongRedstone & (1 << tSide)) != 0 ? GT_Utility.trans("093", "Strong") : GT_Utility.trans("094", "Weak"))); GT_Utility.sendSoundToPlayers( worldObj, SoundResource.IC2_TOOLS_BATTERY_USE, 3.0F, -1, xCoord, yCoord, zCoord); issueBlockUpdate(); } doEnetUpdate(); cableUpdateDelay = 10; return true; } if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWireCutterList)) { final byte tSide = GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ); if (mMetaTileEntity.onWireCutterRightClick(aSide, tSide, aPlayer, aX, aY, aZ)) { // logic handled internally GT_Utility.sendSoundToPlayers( worldObj, SoundResource.IC2_TOOLS_WRENCH, 1.0F, -1, xCoord, yCoord, zCoord); } doEnetUpdate(); cableUpdateDelay = 10; return true; } byte coverSide = aSide; if (getCoverIDAtSide(aSide) == 0) coverSide = GT_Utility.determineWrenchingSide(aSide, aX, aY, aZ); if (getCoverIDAtSide(coverSide) == 0) { if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sCovers.keySet())) { if (GregTech_API.getCoverBehaviorNew(tCurrentItem) .isCoverPlaceable(coverSide, tCurrentItem, this) && mMetaTileEntity.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); } 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); } 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; if (isUpgradable() && tCurrentItem != null) { if (ItemList.Upgrade_Muffler.isStackEqual(aPlayer.inventory.getCurrentItem())) { if (addMufflerUpgrade()) { GT_Utility.sendSoundToPlayers( worldObj, SoundResource.RANDOM_CLICK, 1.0F, -1, xCoord, yCoord, zCoord); if (!aPlayer.capabilities.isCreativeMode) aPlayer.inventory.getCurrentItem().stackSize--; } return true; } if (ItemList.Upgrade_Lock.isStackEqual(aPlayer.inventory.getCurrentItem())) { if (isUpgradable() && !mLockUpgrade) { mLockUpgrade = true; setOwnerName(aPlayer.getDisplayName()); setOwnerUuid(aPlayer.getUniqueID()); GT_Utility.sendSoundToPlayers( worldObj, SoundResource.RANDOM_CLICK, 1.0F, -1, xCoord, yCoord, zCoord); if (!aPlayer.capabilities.isCreativeMode) aPlayer.inventory.getCurrentItem().stackSize--; } return true; } } } } try { if (!aPlayer.isSneaking() && hasValidMetaTileEntity()) return mMetaTileEntity.onRightclick(this, aPlayer, aSide, aX, aY, aZ); } catch (Throwable e) { GT_Log.err.println( "Encountered Exception while rightclicking TileEntity, the Game should've crashed now, but I prevented that. Please report immediately to GregTech Intergalactical!!!"); e.printStackTrace(GT_Log.err); e.printStackTrace(); } return false; } @Override public void onLeftclick(EntityPlayer aPlayer) { try { if (aPlayer != null && hasValidMetaTileEntity()) mMetaTileEntity.onLeftclick(this, aPlayer); } catch (Throwable e) { GT_Log.err.println( "Encountered Exception while leftclicking TileEntity, the Game should've crashed now, but I prevented that. Please report immediately to GregTech Intergalactical!!!"); e.printStackTrace(GT_Log.err); } } @Override public boolean isDigitalChest() { if (canAccessData()) return mMetaTileEntity.isDigitalChest(); return false; } @Override public ItemStack[] getStoredItemData() { if (canAccessData()) return mMetaTileEntity.getStoredItemData(); return null; } @Override public void setItemCount(int aCount) { if (canAccessData()) mMetaTileEntity.setItemCount(aCount); } @Override public int getMaxItemCount() { if (canAccessData()) return mMetaTileEntity.getMaxItemCount(); return 0; } /** * Can put aStack into Slot */ @Override public boolean isItemValidForSlot(int aIndex, ItemStack aStack) { return canAccessData() && mMetaTileEntity.isItemValidForSlot(aIndex, aStack); } /** * returns all valid Inventory Slots, no matter which Side (Unless it's covered). * The Side Stuff is done in the following two Functions. */ @Override public int[] getAccessibleSlotsFromSide(int aSide) { if (canAccessData() && (getCoverBehaviorAtSideNew((byte) aSide) .letsItemsOut( (byte) aSide, getCoverIDAtSide((byte) aSide), getComplexCoverDataAtSide((byte) aSide), -1, this) || getCoverBehaviorAtSideNew((byte) aSide) .letsItemsIn( (byte) aSide, getCoverIDAtSide((byte) aSide), getComplexCoverDataAtSide((byte) aSide), -1, this))) return mMetaTileEntity.getAccessibleSlotsFromSide(aSide); return GT_Values.emptyIntArray; } /** * Can put aStack into Slot at Side */ @Override public boolean canInsertItem(int aIndex, ItemStack aStack, int aSide) { return canAccessData() && (mRunningThroughTick || !mInputDisabled) && getCoverBehaviorAtSideNew((byte) aSide) .letsItemsIn( (byte) aSide, getCoverIDAtSide((byte) aSide), getComplexCoverDataAtSide((byte) aSide), aIndex, this) && mMetaTileEntity.canInsertItem(aIndex, aStack, aSide); } /** * Can pull aStack out of Slot from Side */ @Override public boolean canExtractItem(int aIndex, ItemStack aStack, int aSide) { return canAccessData() && (mRunningThroughTick || !mOutputDisabled) && getCoverBehaviorAtSideNew((byte) aSide) .letsItemsOut( (byte) aSide, getCoverIDAtSide((byte) aSide), getComplexCoverDataAtSide((byte) aSide), aIndex, this) && mMetaTileEntity.canExtractItem(aIndex, aStack, aSide); } @Override public boolean isUpgradable() { return canAccessData() && getUpgradeCount() < 8; } @Override public byte getGeneralRS(byte aSide) { if (mMetaTileEntity == null) return 0; return mMetaTileEntity.allowGeneralRedstoneOutput() ? mSidedRedstone[aSide] : 0; } @Override public boolean isSteamEngineUpgradable() { return isUpgradable() && !hasSteamEngineUpgrade() && getSteamCapacity() > 0; } @Override public boolean addSteamEngineUpgrade() { if (isSteamEngineUpgradable()) { issueBlockUpdate(); mSteamConverter = true; return true; } return false; } @Override public boolean hasSteamEngineUpgrade() { if (canAccessData() && mMetaTileEntity.isSteampowered()) return true; return mSteamConverter; } @Override public boolean hasMufflerUpgrade() { return mMuffler; } @Override public boolean isMufflerUpgradable() { return isUpgradable() && !hasMufflerUpgrade(); } @Override public boolean addMufflerUpgrade() { if (isMufflerUpgradable()) return mMuffler = true; return false; } @Override public void markInventoryBeenModified() { mInventoryChanged = true; } @Override public int getErrorDisplayID() { return mDisplayErrorCode; } @Override public void setErrorDisplayID(int aErrorID) { mDisplayErrorCode = aErrorID; } @Override public IMetaTileEntity getMetaTileEntity() { return hasValidMetaTileEntity() ? mMetaTileEntity : null; } @Override public void setMetaTileEntity(IMetaTileEntity aMetaTileEntity) { if (aMetaTileEntity instanceof MetaTileEntity || aMetaTileEntity == null) mMetaTileEntity = (MetaTileEntity) aMetaTileEntity; else { GT_FML_LOGGER.error( "Unknown meta tile entity set! Class {}, inventory name {}.", aMetaTileEntity.getClass(), aMetaTileEntity.getInventoryName()); } } public byte getLightValue() { return mLightValue; } @Override public void setLightValue(byte aLightValue) { mLightValue = (byte) (aLightValue & 15); } @Override public long getAverageElectricInput() { long rEU = 0; for (int i = 0; i < mAverageEUInput.length; ++i) if (i != mAverageEUInputIndex) rEU += mAverageEUInput[i]; return rEU / (mAverageEUInput.length - 1); } @Override public long getAverageElectricOutput() { long rEU = 0; for (int i = 0; i < mAverageEUOutput.length; ++i) if (i != mAverageEUOutputIndex) rEU += mAverageEUOutput[i]; return rEU / (mAverageEUOutput.length - 1); } @Override protected void updateOutputRedstoneSignal(byte aSide) { if (mMetaTileEntity.hasSidedRedstoneOutputBehavior()) { setOutputRedstoneSignal(aSide, (byte) 0); } else { setOutputRedstoneSignal(aSide, (byte) 15); } } @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 byte getComparatorValue(byte aSide) { return canAccessData() ? mMetaTileEntity.getComparatorValue(aSide) : 0; } @Override public ItemStack decrStackSize(int aIndex, int aAmount) { if (canAccessData()) { mInventoryChanged = true; return mMetaTileEntity.decrStackSize(aIndex, aAmount); } return null; } @Override public long injectEnergyUnits(byte aSide, long aVoltage, long aAmperage) { if (!canAccessData() || !mMetaTileEntity.isElectric() || !inputEnergyFrom(aSide) || aAmperage <= 0 || aVoltage <= 0 || getStoredEU() >= getEUCapacity() || mMetaTileEntity.maxAmperesIn() <= mAcceptedAmperes) return 0; if (aVoltage > getInputVoltage()) { GT_Log.exp.println( "Energy Explosion, injected " + aVoltage + "EU/t in a " + getInputVoltage() + "EU/t Machine!"); doExplosion(aVoltage); return 0; } if (increaseStoredEnergyUnits( aVoltage * (aAmperage = Math.min( aAmperage, Math.min( mMetaTileEntity.maxAmperesIn() - mAcceptedAmperes, 1 + ((getEUCapacity() - getStoredEU()) / aVoltage)))), true)) { mAverageEUInput[mAverageEUInputIndex] += aVoltage * aAmperage; mAcceptedAmperes += aAmperage; return aAmperage; } return 0; } @Override public boolean drainEnergyUnits(byte aSide, long aVoltage, long aAmperage) { if (!canAccessData() || !mMetaTileEntity.isElectric() || !outputsEnergyTo(aSide) || getStoredEU() - (aVoltage * aAmperage) < mMetaTileEntity.getMinimumStoredEU()) return false; if (decreaseStoredEU(aVoltage * aAmperage, false)) { mAverageEUOutput[mAverageEUOutputIndex] += aVoltage * aAmperage; return true; } return false; } @Override public boolean acceptsRotationalEnergy(byte aSide) { if (!canAccessData() || getCoverIDAtSide(aSide) != 0) return false; return mMetaTileEntity.acceptsRotationalEnergy(aSide); } @Override public boolean injectRotationalEnergy(byte aSide, long aSpeed, long aEnergy) { if (!canAccessData() || getCoverIDAtSide(aSide) != 0) return false; return mMetaTileEntity.injectRotationalEnergy(aSide, aSpeed, aEnergy); } @Override public int fill(ForgeDirection aSide, FluidStack aFluid, boolean doFill) { if (mTickTimer > 5 && canAccessData() && (mRunningThroughTick || !mInputDisabled) && (aSide == ForgeDirection.UNKNOWN || (mMetaTileEntity.isLiquidInput((byte) aSide.ordinal()) && getCoverBehaviorAtSideNew((byte) aSide.ordinal()) .letsFluidIn( (byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), aFluid == null ? null : aFluid.getFluid(), this)))) return mMetaTileEntity.fill(aSide, aFluid, doFill); return 0; } @Override public FluidStack drain(ForgeDirection aSide, int maxDrain, boolean doDrain) { if (mTickTimer > 5 && canAccessData() && (mRunningThroughTick || !mOutputDisabled) && (aSide == ForgeDirection.UNKNOWN || (mMetaTileEntity.isLiquidOutput((byte) aSide.ordinal()) && getCoverBehaviorAtSideNew((byte) aSide.ordinal()) .letsFluidOut( (byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), mMetaTileEntity.getFluid() == null ? null : mMetaTileEntity .getFluid() .getFluid(), this)))) return mMetaTileEntity.drain(aSide, maxDrain, doDrain); return null; } @Override public FluidStack drain(ForgeDirection aSide, FluidStack aFluid, boolean doDrain) { if (mTickTimer > 5 && canAccessData() && (mRunningThroughTick || !mOutputDisabled) && (aSide == ForgeDirection.UNKNOWN || (mMetaTileEntity.isLiquidOutput((byte) aSide.ordinal()) && getCoverBehaviorAtSideNew((byte) aSide.ordinal()) .letsFluidOut( (byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), aFluid == null ? null : aFluid.getFluid(), this)))) return mMetaTileEntity.drain(aSide, aFluid, doDrain); return null; } @Override public boolean canFill(ForgeDirection aSide, Fluid aFluid) { if (mTickTimer > 5 && canAccessData() && (mRunningThroughTick || !mInputDisabled) && (aSide == ForgeDirection.UNKNOWN || (mMetaTileEntity.isLiquidInput((byte) aSide.ordinal()) && getCoverBehaviorAtSideNew((byte) aSide.ordinal()) .letsFluidIn( (byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), aFluid, this)))) return mMetaTileEntity.canFill(aSide, aFluid); return false; } @Override public boolean canDrain(ForgeDirection aSide, Fluid aFluid) { if (mTickTimer > 5 && canAccessData() && (mRunningThroughTick || !mOutputDisabled) && (aSide == ForgeDirection.UNKNOWN || (mMetaTileEntity.isLiquidOutput((byte) aSide.ordinal()) && getCoverBehaviorAtSideNew((byte) aSide.ordinal()) .letsFluidOut( (byte) aSide.ordinal(), getCoverIDAtSide((byte) aSide.ordinal()), getComplexCoverDataAtSide((byte) aSide.ordinal()), aFluid, this)))) return mMetaTileEntity.canDrain(aSide, aFluid); return false; } @Override public FluidTankInfo[] getTankInfo(ForgeDirection aSide) { final byte tSide = (byte) aSide.ordinal(); if (canAccessData() && (aSide == ForgeDirection.UNKNOWN || (mMetaTileEntity.isLiquidInput(tSide) && getCoverBehaviorAtSideNew(tSide) .letsFluidIn( tSide, getCoverIDAtSide(tSide), getComplexCoverDataAtSide(tSide), null, this)) || (mMetaTileEntity.isLiquidOutput(tSide) && getCoverBehaviorAtSideNew(tSide) .letsFluidOut( tSide, getCoverIDAtSide(tSide), getComplexCoverDataAtSide(tSide), null, this)))) return mMetaTileEntity.getTankInfo(aSide); return new FluidTankInfo[] {}; } public double getOutputEnergyUnitsPerTick() { return oOutput; } public boolean isTeleporterCompatible(ForgeDirection aSide) { return canAccessData() && mMetaTileEntity.isTeleporterCompatible(); } public double demandedEnergyUnits() { if (mReleaseEnergy || !canAccessData() || !mMetaTileEntity.isEnetInput()) return 0; return getEUCapacity() - getStoredEU(); } public double injectEnergyUnits(ForgeDirection aDirection, double aAmount) { return injectEnergyUnits((byte) aDirection.ordinal(), (int) aAmount, 1) > 0 ? 0 : aAmount; } public boolean acceptsEnergyFrom(TileEntity aEmitter, ForgeDirection aDirection) { return inputEnergyFrom((byte) aDirection.ordinal()); } public boolean emitsEnergyTo(TileEntity aReceiver, ForgeDirection aDirection) { return outputsEnergyTo((byte) aDirection.ordinal()); } public double getOfferedEnergy() { return (canAccessData() && getStoredEU() - mMetaTileEntity.getMinimumStoredEU() >= oOutput) ? Math.max(0, oOutput) : 0; } public void drawEnergy(double amount) { mAverageEUOutput[mAverageEUOutputIndex] += amount; decreaseStoredEU((int) amount, true); } public int injectEnergy(ForgeDirection aForgeDirection, int aAmount) { return injectEnergyUnits((byte) aForgeDirection.ordinal(), aAmount, 1) > 0 ? 0 : aAmount; } public int addEnergy(int aEnergy) { if (!canAccessData()) return 0; if (aEnergy > 0) increaseStoredEnergyUnits(aEnergy, true); else decreaseStoredEU(-aEnergy, true); return (int) Math.min(Integer.MAX_VALUE, mMetaTileEntity.getEUVar()); } public boolean isAddedToEnergyNet() { return false; } public int demandsEnergy() { if (mReleaseEnergy || !canAccessData() || !mMetaTileEntity.isEnetInput()) return 0; return getCapacity() - getStored(); } public int getCapacity() { return (int) Math.min(Integer.MAX_VALUE, getEUCapacity()); } public int getStored() { return (int) Math.min(Integer.MAX_VALUE, Math.min(getStoredEU(), getCapacity())); } public void setStored(int aEU) { if (canAccessData()) setStoredEU(aEU); } public int getMaxSafeInput() { return (int) Math.min(Integer.MAX_VALUE, getInputVoltage()); } public int getMaxEnergyOutput() { if (mReleaseEnergy) return Integer.MAX_VALUE; return getOutput(); } public int getOutput() { return (int) Math.min(Integer.MAX_VALUE, oOutput); } public int injectEnergy(Direction aDirection, int aAmount) { return injectEnergyUnits((byte) aDirection.toSideValue(), aAmount, 1) > 0 ? 0 : aAmount; } public boolean isTeleporterCompatible(Direction aSide) { return canAccessData() && mMetaTileEntity.isTeleporterCompatible(); } public boolean acceptsEnergyFrom(TileEntity aReceiver, Direction aDirection) { return inputEnergyFrom((byte) aDirection.toSideValue()); } public boolean emitsEnergyTo(TileEntity aReceiver, Direction aDirection) { return outputsEnergyTo((byte) aDirection.toSideValue()); } @Override public boolean addStackToSlot(int aIndex, ItemStack aStack) { if (GT_Utility.isStackInvalid(aStack)) return true; if (aIndex < 0 || aIndex >= getSizeInventory()) return false; final ItemStack tStack = getStackInSlot(aIndex); if (GT_Utility.isStackInvalid(tStack)) { setInventorySlotContents(aIndex, aStack); return true; } aStack = GT_OreDictUnificator.get(aStack); if (GT_Utility.areStacksEqual(tStack, aStack) && tStack.stackSize + aStack.stackSize <= Math.min(aStack.getMaxStackSize(), getInventoryStackLimit())) { tStack.stackSize += aStack.stackSize; markDirty(); return true; } return false; } @Override public boolean addStackToSlot(int aIndex, ItemStack aStack, int aAmount) { return addStackToSlot(aIndex, GT_Utility.copyAmount(aAmount, aStack)); } @Override public byte getColorization() { return (byte) (mColor - 1); } @Override public byte setColorization(byte aColor) { if (aColor > 15 || aColor < -1) aColor = -1; mColor = (byte) (aColor + 1); if (canAccessData()) mMetaTileEntity.onColorChangeServer(aColor); return mColor; } @Override public float getBlastResistance(byte aSide) { return canAccessData() ? Math.max(0, getMetaTileEntity().getExplosionResistance(aSide)) : 10.0F; } @Override public boolean isUniversalEnergyStored(long aEnergyAmount) { if (getUniversalEnergyStored() >= aEnergyAmount) return true; mHasEnoughEnergy = false; return false; } @Override public String[] getInfoData() { { if (canAccessData()) return getMetaTileEntity().getInfoData(); return new String[] {}; } } @Override public int getLightOpacity() { return mMetaTileEntity == null ? getLightValue() > 0 ? 0 : 255 : mMetaTileEntity.getLightOpacity(); } @Override public void addCollisionBoxesToList( World aWorld, int aX, int aY, int aZ, AxisAlignedBB inputAABB, List outputAABB, Entity collider) { mMetaTileEntity.addCollisionBoxesToList(aWorld, aX, aY, aZ, inputAABB, outputAABB, collider); } @Override public AxisAlignedBB getCollisionBoundingBoxFromPool(World aWorld, int aX, int aY, int aZ) { return mMetaTileEntity.getCollisionBoundingBoxFromPool(aWorld, aX, aY, aZ); } @Override public void onEntityCollidedWithBlock(World aWorld, int aX, int aY, int aZ, Entity collider) { mMetaTileEntity.onEntityCollidedWithBlock(aWorld, aX, aY, aZ, collider); } /** * Shifts the machine Inventory index according to the change in Input/Output Slots. * This is NOT done automatically. If you want to change slot count for a machine this method needs to be adapted. * Currently this method only works for GT_MetaTileEntity_BasicMachine * * @param slotIndex The original Inventory index * @param nbtVersion The GregTech version in which the original Inventory Index was saved. * @return The corrected Inventory index */ @Override protected int migrateInventoryIndex(int slotIndex, int nbtVersion) { final int oldInputSize; final int newInputSize; final int oldOutputSize; final int newOutputSize; final int chemistryUpdateVersion = GT_Mod.calculateTotalGTVersion(509, 31); final int configCircuitAdditionVersion = GT_Mod.calculateTotalGTVersion(509, 40); final int wireAdditionVersion = GT_Mod.calculateTotalGTVersion(509, 41); // 4 is old GT_MetaTileEntity_BasicMachine.OTHER_SLOT_COUNT if (nbtVersion < configCircuitAdditionVersion && getMetaTileEntity() instanceof GT_MetaTileEntity_BasicMachine && slotIndex >= 4) slotIndex += 1; if (mID >= 211 && mID <= 218) { // Assembler if (nbtVersion < chemistryUpdateVersion) { oldInputSize = 2; oldOutputSize = 1; } else { return slotIndex; } newInputSize = 6; newOutputSize = 1; } else if (mID >= 421 && mID <= 428) { // Chemical Reactor if (nbtVersion < chemistryUpdateVersion) { oldInputSize = 2; oldOutputSize = 1; } else { return slotIndex; } newInputSize = 2; newOutputSize = 2; } else if (mID >= 531 && mID <= 538) { // Distillery if (nbtVersion < chemistryUpdateVersion) { oldInputSize = 1; oldOutputSize = 0; } else { return slotIndex; } newInputSize = 1; newOutputSize = 1; } else if (mID >= 581 && mID <= 588) { // Mixer if (nbtVersion < chemistryUpdateVersion) { oldInputSize = 4; oldOutputSize = 1; } else { return slotIndex; } newInputSize = 6; newOutputSize = 1; } else if (mID >= 351 && mID <= 355 || mID >= 11050 && mID <= 11056) { // wire mill if (nbtVersion < wireAdditionVersion) { oldInputSize = 1; oldOutputSize = 1; } else { return slotIndex; } newInputSize = 2; newOutputSize = 1; } else { return slotIndex; } int indexShift = 0; if (slotIndex >= GT_MetaTileEntity_BasicMachine.OTHER_SLOT_COUNT + oldInputSize) { indexShift += newInputSize - oldInputSize; } if (slotIndex >= GT_MetaTileEntity_BasicMachine.OTHER_SLOT_COUNT + oldInputSize + oldOutputSize) { indexShift += newOutputSize - oldOutputSize; } return slotIndex + indexShift; } @Override @Optional.Method(modid = "appliedenergistics2") public IGridNode getGridNode(ForgeDirection forgeDirection) { if (mFacing != forgeDirection.ordinal()) return null; final AENetworkProxy gp = getProxy(); return gp != null ? gp.getNode() : null; } @Override @Optional.Method(modid = "appliedenergistics2") public AECableType getCableConnectionType(ForgeDirection forgeDirection) { return mMetaTileEntity == null ? AECableType.NONE : mMetaTileEntity.getCableConnectionType(forgeDirection); } @Override @Optional.Method(modid = "appliedenergistics2") public void securityBreak() {} @Override @Optional.Method(modid = "appliedenergistics2") public IGridNode getActionableNode() { final AENetworkProxy gp = getProxy(); return gp != null ? gp.getNode() : null; } @Override @Optional.Method(modid = "appliedenergistics2") public AENetworkProxy getProxy() { return mMetaTileEntity == null ? null : mMetaTileEntity.getProxy(); } @Override @Optional.Method(modid = "appliedenergistics2") public DimensionalCoord getLocation() { return new DimensionalCoord(this); } @Override @Optional.Method(modid = "appliedenergistics2") public void gridChanged() { if (mMetaTileEntity != null) mMetaTileEntity.gridChanged(); } @TileEvent(TileEventType.WORLD_NBT_READ) @Optional.Method(modid = "appliedenergistics2") public void readFromNBT_AENetwork(final NBTTagCompound data) { final AENetworkProxy gp = getProxy(); if (gp != null) getProxy().readFromNBT(data); } @TileEvent(TileEventType.WORLD_NBT_WRITE) @Optional.Method(modid = "appliedenergistics2") public void writeToNBT_AENetwork(final NBTTagCompound data) { final AENetworkProxy gp = getProxy(); if (gp != null) gp.writeToNBT(data); } @Optional.Method(modid = "appliedenergistics2") void onChunkUnloadAE() { final AENetworkProxy gp = getProxy(); if (gp != null) gp.onChunkUnload(); } @Optional.Method(modid = "appliedenergistics2") void invalidateAE() { final AENetworkProxy gp = getProxy(); if (gp != null) gp.invalidate(); } @Override public boolean wasShutdown() { return mWasShutdown; } @Override public void setShutdownStatus(boolean newStatus) { mWasShutdown = newStatus; } @Override public IAlignment getAlignment() { return getMetaTileEntity() instanceof IAlignmentProvider ? ((IAlignmentProvider) getMetaTileEntity()).getAlignment() : getMetaTileEntity() instanceof IAlignment ? (IAlignment) getMetaTileEntity() : null; } @Nullable @Override public IConstructable getConstructable() { return getMetaTileEntity() instanceof IConstructable ? (IConstructable) getMetaTileEntity() : null; } }