package gregtech.api.metatileentity;
import static gregtech.GT_Mod.GT_FML_LOGGER;
import static gregtech.api.enums.GT_Values.NW;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.EnumChatFormatting;
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.IFluidHandler;
import gregtech.api.GregTech_API;
import gregtech.api.enums.GT_Values;
import gregtech.api.enums.SoundResource;
import gregtech.api.enums.Textures;
import gregtech.api.graphs.Lock;
import gregtech.api.graphs.Node;
import gregtech.api.graphs.paths.NodePath;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.metatileentity.IConnectable;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IDebugableTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.interfaces.tileentity.IPipeRenderedTileEntity;
import gregtech.api.net.GT_Packet_TileEntity;
import gregtech.api.objects.GT_ItemStack;
import gregtech.api.util.GT_CoverBehaviorBase;
import gregtech.api.util.GT_Log;
import gregtech.api.util.GT_ModHandler;
import gregtech.api.util.GT_OreDictUnificator;
import gregtech.api.util.GT_Utility;
import gregtech.common.covers.CoverInfo;
import mcp.mobius.waila.api.IWailaConfigHandler;
import mcp.mobius.waila.api.IWailaDataAccessor;
/**
* NEVER INCLUDE THIS FILE IN YOUR MOD!!!
*
* This is the main TileEntity for EVERYTHING.
*/
public class BaseMetaPipeEntity extends CommonMetaTileEntity
implements IGregTechTileEntity, IPipeRenderedTileEntity, IDebugableTileEntity {
public byte mConnections = IConnectable.NO_CONNECTION;
protected MetaPipeEntity mMetaTileEntity;
private final int[] mTimeStatistics = new int[GregTech_API.TICKS_FOR_LAG_AVERAGING];
private boolean hasTimeStatisticsStarted;
private boolean mWorkUpdate = false, mWorks = true;
private byte mColor = 0, oColor = 0, oStrongRedstone = 0, oRedstoneData = 63, oTextureData = 0, oUpdateData = 0,
mLagWarningCount = 0;
private int oX = 0, oY = 0, oZ = 0, mTimeStatisticsIndex = 0;
protected Node node;
protected NodePath nodePath;
public Node getNode() {
return node;
}
public void setNode(Node node) {
this.node = node;
}
public NodePath getNodePath() {
return nodePath;
}
public void setNodePath(NodePath nodePath) {
this.nodePath = nodePath;
}
public void addToLock(TileEntity tileEntity, ForgeDirection side) {
if (node != null) {
final Lock lock = node.locks[side.ordinal()];
if (lock != null) {
lock.addTileEntity(tileEntity);
}
} else if (nodePath != null) {
nodePath.lock.addTileEntity(tileEntity);
}
}
public void removeFromLock(TileEntity tileEntity, ForgeDirection side) {
if (node != null) {
final Lock lock = node.locks[side.ordinal()];
if (lock != null) {
lock.removeTileEntity(tileEntity);
}
} else if (nodePath != null) {
nodePath.lock.removeTileEntity(tileEntity);
}
}
public void reloadLocks() {
final IMetaTileEntity meta = getMetaTileEntity();
if (meta instanceof MetaPipeEntity) {
((MetaPipeEntity) meta).reloadLocks();
}
}
public BaseMetaPipeEntity() {}
@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);
writeCoverNBT(aNBT, false);
aNBT.setByte("mConnections", mConnections);
aNBT.setByte("mColor", mColor);
aNBT.setBoolean("mWorks", !mWorks);
} 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);
} else {
if (aID <= 0) mID = (short) aNBT.getInteger("mID");
else mID = aID;
mConnections = aNBT.getByte("mConnections");
mColor = aNBT.getByte("mColor");
mWorks = !aNBT.getBoolean("mWorks");
if (mSidedRedstone.length != 6) mSidedRedstone = new byte[] { 0, 0, 0, 0, 0, 0 };
readCoverNBT(aNBT);
loadMetaTileNBT(aNBT);
}
}
@Override
public void updateEntity() {
super.updateEntity();
if (!hasValidMetaTileEntity()) {
if (mMetaTileEntity == null) return;
mMetaTileEntity.setBaseMetaTileEntity(this);
}
long tTime;
if (hasTimeStatisticsStarted) {
tTime = System.nanoTime();
} else {
tTime = 0;
}
try {
if (hasValidMetaTileEntity()) {
if (mTickTimer++ == 0) {
oX = xCoord;
oY = yCoord;
oZ = zCoord;
if (isServerSide()) checkDropCover();
else {
requestCoverDataIfNeeded();
}
worldObj.markTileEntityChunkModified(xCoord, yCoord, zCoord, this);
mMetaTileEntity.onFirstTick(this);
if (!hasValidMetaTileEntity()) return;
}
if (isClientSide()) {
if (mColor != oColor) {
mMetaTileEntity.onColorChangeClient(oColor = mColor);
issueTextureUpdate();
}
if (mNeedsUpdate) {
worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
mNeedsUpdate = false;
}
}
if (isServerSide() && mTickTimer > 10) {
if (!doCoverThings()) return;
final byte oldConnections = mConnections;
// Mask-out connection direction bits to keep only Foam related connections
mConnections = (byte) (mMetaTileEntity.mConnections | (mConnections & ~IConnectable.CONNECTED_ALL));
// If foam not hardened, tries roll chance to harden
if ((mConnections & IConnectable.HAS_FOAM) == IConnectable.HAS_FRESHFOAM
&& getRandomNumber(1000) == 0) {
mConnections = (byte) ((mConnections & ~IConnectable.HAS_FRESHFOAM)
| IConnectable.HAS_HARDENEDFOAM);
}
if (mTickTimer > 12 && oldConnections != mConnections)
GregTech_API.causeCableUpdate(worldObj, xCoord, yCoord, zCoord);
}
mMetaTileEntity.onPreTick(this, mTickTimer);
if (!hasValidMetaTileEntity()) return;
if (isServerSide()) {
if (mTickTimer == 10) {
updateCoverBehavior();
issueBlockUpdate();
joinEnet();
}
if (xCoord != oX || yCoord != oY || zCoord != oZ) {
oX = xCoord;
oY = yCoord;
oZ = zCoord;
issueClientUpdate();
clearTileEntityBuffer();
}
}
mMetaTileEntity.onPostTick(this, mTickTimer);
if (!hasValidMetaTileEntity()) return;
if (isServerSide()) {
if (mTickTimer % 10 == 0) {
sendClientData();
}
if (mTickTimer > 10) {
if (mConnections != oTextureData) sendBlockEvent((byte) 0, oTextureData = mConnections);
byte tData = mMetaTileEntity.getUpdateData();
if (tData != oUpdateData) sendBlockEvent((byte) 1, oUpdateData = tData);
if (mColor != oColor) sendBlockEvent((byte) 2, 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((byte) 3, oRedstoneData = tData);
}
if (mNeedsBlockUpdate) {
updateNeighbours(mStrongRedstone, oStrongRedstone);
oStrongRedstone = mStrongRedstone;
mNeedsBlockUpdate = false;
}
}
}
} catch (Throwable e) {
e.printStackTrace();
e.printStackTrace(GT_Log.err);
}
if (isServerSide() && hasTimeStatisticsStarted && hasValidMetaTileEntity()) {
tTime = System.nanoTime() - tTime;
mTimeStatisticsIndex = (mTimeStatisticsIndex + 1) % mTimeStatistics.length;
mTimeStatistics[mTimeStatisticsIndex] = (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 = false;
}
private void sendClientData() {
if (mSendClientData) {
NW.sendPacketToAllPlayersInRange(
worldObj,
new GT_Packet_TileEntity(
xCoord,
(short) yCoord,
zCoord,
mID,
getCoverInfoAtSide(ForgeDirection.DOWN).getCoverID(),
getCoverInfoAtSide(ForgeDirection.UP).getCoverID(),
getCoverInfoAtSide(ForgeDirection.NORTH).getCoverID(),
getCoverInfoAtSide(ForgeDirection.SOUTH).getCoverID(),
getCoverInfoAtSide(ForgeDirection.WEST).getCoverID(),
getCoverInfoAtSide(ForgeDirection.EAST).getCoverID(),
oTextureData = mConnections,
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 aUpdateData, byte aRedstoneData, byte aColorData) {
issueTextureUpdate();
if (aID > 0 && mID != aID) {
mID = aID;
createNewMetatileEntity(mID);
}
setCoverIDAtSide(ForgeDirection.DOWN, aCover0);
setCoverIDAtSide(ForgeDirection.UP, aCover1);
setCoverIDAtSide(ForgeDirection.NORTH, aCover2);
setCoverIDAtSide(ForgeDirection.SOUTH, aCover3);
setCoverIDAtSide(ForgeDirection.WEST, aCover4);
setCoverIDAtSide(ForgeDirection.EAST, aCover5);
receiveClientEvent(GregTechTileClientEvents.CHANGE_COMMON_DATA, aTextureData);
receiveClientEvent(GregTechTileClientEvents.CHANGE_CUSTOM_DATA, aUpdateData);
receiveClientEvent(GregTechTileClientEvents.CHANGE_COLOR, aColorData);
receiveClientEvent(GregTechTileClientEvents.CHANGE_REDSTONE_OUTPUT, aRedstoneData);
}
@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_FML_LOGGER.error("Encountered Exception while receiving Data from the Server", e);
}
}
if (isClientSide()) {
issueTextureUpdate();
switch (aEventID) {
case GregTechTileClientEvents.CHANGE_COMMON_DATA -> mConnections = (byte) aValue;
case GregTechTileClientEvents.CHANGE_CUSTOM_DATA -> {
if (hasValidMetaTileEntity()) mMetaTileEntity.onValueUpdate((byte) aValue);
}
case GregTechTileClientEvents.CHANGE_COLOR -> {
if (aValue > 16 || aValue < 0) aValue = 0;
mColor = (byte) aValue;
}
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);
}
case GregTechTileClientEvents.DO_SOUND -> {
if (hasValidMetaTileEntity() && mTickTimer > 20)
mMetaTileEntity.doSound((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5);
}
case GregTechTileClientEvents.START_SOUND_LOOP -> {
if (hasValidMetaTileEntity() && mTickTimer > 20)
mMetaTileEntity.startSoundLoop((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5);
}
case GregTechTileClientEvents.STOP_SOUND_LOOP -> {
if (hasValidMetaTileEntity() && mTickTimer > 20)
mMetaTileEntity.stopSoundLoop((byte) aValue, xCoord + 0.5, yCoord + 0.5, zCoord + 0.5);
}
}
}
return true;
}
@Override
public ArrayList getDebugInfo(EntityPlayer aPlayer, int aLogLevel) {
final ArrayList tList = new ArrayList<>();
if (aLogLevel > 3) {
tList.add(
"Meta-ID: " + EnumChatFormatting.BLUE
+ mID
+ EnumChatFormatting.RESET
+ (hasValidMetaTileEntity() ? EnumChatFormatting.GREEN + " valid" + EnumChatFormatting.RESET
: EnumChatFormatting.RED + " invalid" + EnumChatFormatting.RESET)
+ (mMetaTileEntity == null
? EnumChatFormatting.RED + " MetaTileEntity == null!" + EnumChatFormatting.RESET
: " "));
}
if (aLogLevel > 1) {
if (hasTimeStatisticsStarted) {
double tAverageTime = 0;
double tWorstTime = 0;
int amountOfZero = 0;
for (int tTime : mTimeStatistics) {
tAverageTime += tTime;
if (tTime > tWorstTime) {
tWorstTime = tTime;
}
if (tTime == 0) {
amountOfZero += 1;
}
}
// tick time zero means it has not been updated yet
int samples = mTimeStatistics.length - amountOfZero;
if (samples > 0) {
tList.add(
"Average CPU-load of ~" + (tAverageTime / samples)
+ "ns since "
+ samples
+ " ticks with worst time of "
+ tWorstTime
+ "ns.");
}
} else {
startTimeStatistics();
tList.add("Just started tick time statistics.");
}
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.");
}
if (mMetaTileEntity != null) {
tList.add(
"Is" + (mMetaTileEntity.isAccessAllowed(aPlayer) ? " "
: EnumChatFormatting.RED + " not " + EnumChatFormatting.RESET) + "accessible for you");
}
}
if (joinedIc2Enet) tList.add("Joined IC2 ENet");
return mMetaTileEntity != null ? mMetaTileEntity.getSpecialDebugInfo(this, aPlayer, aLogLevel, tList)
: new ArrayList<>();
}
@Override
public boolean isGivingInformation() {
if (canAccessData()) return mMetaTileEntity.isGivingInformation();
return false;
}
@Override
public ForgeDirection getBackFacing() {
return getFrontFacing().getOpposite();
}
@Override
public ForgeDirection getFrontFacing() {
return ForgeDirection.UNKNOWN;
}
@Override
public void setFrontFacing(ForgeDirection aFacing) {
doEnetUpdate();
}
@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) {
markDirty();
mInventoryChanged = true;
if (canAccessData()) 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() {
/* Do nothing */
}
@Override
public void closeInventory() {
/* Do nothing */
}
@Override
public boolean isUseableByPlayer(EntityPlayer aPlayer) {
return hasValidMetaTileEntity() && mTickTimer > 1
&& 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;
if (hasValidMetaTileEntity()) {
mMetaTileEntity.onRemoval();
mMetaTileEntity.setBaseMetaTileEntity(null);
}
leaveEnet();
super.invalidate();
}
@Override
public boolean hasCustomInventoryName() {
return false;
}
@Override
public ItemStack getStackInSlotOnClosing(int slot) {
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();
}
/**
* 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;
reloadLocks();
}
@Override
public void disableWorking() {
mWorks = false;
reloadLocks();
}
@Override
public boolean isAllowedToWork() {
return mWorks;
}
@Override
public boolean hasWorkJustBeenEnabled() {
return mWorkUpdate;
}
@Override
public byte getWorkDataValue() {
return 0;
}
@Override
public void setWorkDataValue(byte aValue) {
/* Do nothing */
}
@Override
public int getMetaTileID() {
return mID;
}
@Override
public int setMetaTileID(short aID) {
return mID = aID;
}
@Override
public boolean isActive() {
return false;
}
@Override
public void setActive(boolean aActive) {
/* Do nothing */
}
@Override
public long getTimer() {
return mTickTimer;
}
@Override
public boolean decreaseStoredEnergyUnits(long aEnergy, boolean aIgnoreTooLessEnergy) {
return false;
}
@Override
public boolean increaseStoredEnergyUnits(long aEnergy, boolean aIgnoreTooMuchEnergy) {
return false;
}
@Override
public boolean inputEnergyFrom(ForgeDirection side) {
return false;
}
@Override
public boolean inputEnergyFrom(ForgeDirection side, boolean waitForActive) {
return false;
}
@Override
public boolean outputsEnergyTo(ForgeDirection side) {
return false;
}
@Override
public boolean outputsEnergyTo(ForgeDirection side, boolean waitForActive) {
return false;
}
@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 long getUniversalEnergyStored() {
return Math.max(getStoredEU(), getStoredSteam());
}
@Override
public long getUniversalEnergyCapacity() {
return Math.max(getEUCapacity(), getSteamCapacity());
}
@Override
public long getStoredEU() {
return 0;
}
@Override
public long getEUCapacity() {
return 0;
}
@Override
public ITexture[] getTexture(Block aBlock, ForgeDirection side) {
final ITexture rIcon = getCoverTexture(side);
if (rIcon != null) return new ITexture[] { rIcon };
return getTextureUncovered(side);
}
@Override
public ITexture[] getTextureCovered(ForgeDirection side) {
final ITexture coverTexture = getCoverTexture(side);
final ITexture[] textureUncovered = getTextureUncovered(side);
final ITexture[] textureCovered;
if (coverTexture != null) {
textureCovered = Arrays.copyOf(textureUncovered, textureUncovered.length + 1);
textureCovered[textureUncovered.length] = coverTexture;
return textureCovered;
} else {
return textureUncovered;
}
}
@Override
public ITexture[] getTextureUncovered(ForgeDirection sideDirection) {
if ((mConnections & IConnectable.HAS_FRESHFOAM) != 0) return Textures.BlockIcons.FRESHFOAM;
if ((mConnections & IConnectable.HAS_HARDENEDFOAM) != 0) return Textures.BlockIcons.HARDENEDFOAMS[mColor];
if ((mConnections & IConnectable.HAS_FOAM) != 0) return Textures.BlockIcons.ERROR_RENDERING;
int tConnections = mConnections;
if (tConnections == IConnectable.CONNECTED_WEST || tConnections == IConnectable.CONNECTED_EAST)
tConnections = IConnectable.CONNECTED_WEST | IConnectable.CONNECTED_EAST;
else if (tConnections == IConnectable.CONNECTED_DOWN || tConnections == IConnectable.CONNECTED_UP)
tConnections = IConnectable.CONNECTED_DOWN | IConnectable.CONNECTED_UP;
else if (tConnections == IConnectable.CONNECTED_NORTH || tConnections == IConnectable.CONNECTED_SOUTH)
tConnections = IConnectable.CONNECTED_NORTH | IConnectable.CONNECTED_SOUTH;
if (hasValidMetaTileEntity()) return mMetaTileEntity.getTexture(
this,
sideDirection,
tConnections,
mColor - 1,
tConnections == 0 || (tConnections & sideDirection.flag) != 0,
getOutputRedstoneSignal(sideDirection) > 0);
return Textures.BlockIcons.ERROR_RENDERING;
}
@Override
protected boolean hasValidMetaTileEntity() {
return mMetaTileEntity != null && mMetaTileEntity.getBaseMetaTileEntity() == this;
}
@Override
public void doExplosion(long aAmount) {
if (canAccessData()) {
mMetaTileEntity.onExplosion();
mMetaTileEntity.doExplosion(aAmount);
}
}
@Override
public ArrayList getDrops() {
final ItemStack rStack = new ItemStack(GregTech_API.sBlockMachines, 1, mID);
final NBTTagCompound tNBT = new NBTTagCompound();
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);
}
@Override
public boolean onRightclick(EntityPlayer aPlayer, ForgeDirection side, float aX, float aY, float aZ) {
if (isClientSide()) {
// Configure Cover, sneak can also be: screwdriver, wrench, side cutter, soldering iron
if (aPlayer.isSneaking()) {
final ForgeDirection tSide = (getCoverIDAtSide(side) == 0)
? GT_Utility.determineWrenchingSide(side, aX, aY, aZ)
: side;
return (getCoverInfoAtSide(tSide).hasCoverGUI());
} else if (getCoverBehaviorAtSideNew(side).onCoverRightclickClient(side, this, aPlayer, aX, aY, aZ)) {
return true;
}
}
if (isServerSide()) {
final ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem();
if (tCurrentItem != null) {
if (getColorization() >= 0
&& GT_Utility.areStacksEqual(new ItemStack(Items.water_bucket, 1), tCurrentItem)) {
mMetaTileEntity.markDirty();
tCurrentItem.func_150996_a(Items.bucket);
setColorization((byte) -1);
return true;
}
final ForgeDirection tSide = GT_Utility.determineWrenchingSide(side, aX, aY, aZ);
if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWrenchList)) {
if (mMetaTileEntity.onWrenchRightClick(side, tSide, aPlayer, aX, aY, aZ, tCurrentItem)) {
mMetaTileEntity.markDirty();
GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer);
GT_Utility.sendSoundToPlayers(
worldObj,
SoundResource.IC2_TOOLS_WRENCH,
1.0F,
-1,
xCoord,
yCoord,
zCoord);
}
return true;
}
if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sScrewdriverList)) {
if (getCoverIDAtSide(side) == 0 && getCoverIDAtSide(tSide) != 0) {
if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 200, aPlayer)) {
setCoverDataAtSide(
tSide,
getCoverInfoAtSide(tSide).onCoverScrewdriverClick(aPlayer, 0.5F, 0.5F, 0.5F));
mMetaTileEntity.onScrewdriverRightClick(tSide, aPlayer, aX, aY, aZ, tCurrentItem);
mMetaTileEntity.markDirty();
GT_Utility.sendSoundToPlayers(
worldObj,
SoundResource.IC2_TOOLS_WRENCH,
1.0F,
-1,
xCoord,
yCoord,
zCoord);
}
} else {
if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer)) {
setCoverDataAtSide(
side,
getCoverInfoAtSide(side).onCoverScrewdriverClick(aPlayer, aX, aY, aZ));
mMetaTileEntity.onScrewdriverRightClick(side, aPlayer, aX, aY, aZ, tCurrentItem);
mMetaTileEntity.markDirty();
GT_Utility.sendSoundToPlayers(
worldObj,
SoundResource.IC2_TOOLS_WRENCH,
1.0F,
-1,
xCoord,
yCoord,
zCoord);
}
}
return true;
}
if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sHardHammerList)) {
return true;
}
if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSoftHammerList)) {
if (GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer)) {
if (mWorks) disableWorking();
else enableWorking();
mMetaTileEntity.markDirty();
GT_Utility.sendChatToPlayer(
aPlayer,
GT_Utility.trans("090", "Machine Processing: ")
+ (isAllowedToWork() ? GT_Utility.trans("088", "Enabled")
: GT_Utility.trans("087", "Disabled")));
GT_Utility.sendSoundToPlayers(
worldObj,
SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE,
1.0F,
-1,
xCoord,
yCoord,
zCoord);
}
return true;
}
if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWireCutterList)) {
if (mMetaTileEntity.onWireCutterRightClick(side, tSide, aPlayer, aX, aY, aZ, tCurrentItem)) {
mMetaTileEntity.markDirty();
// logic handled internally
GT_Utility.sendSoundToPlayers(
worldObj,
SoundResource.IC2_TOOLS_WRENCH,
1.0F,
-1,
xCoord,
yCoord,
zCoord);
}
doEnetUpdate();
return true;
}
if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSolderingToolList)) {
if (mMetaTileEntity.onSolderingToolRightClick(side, tSide, aPlayer, aX, aY, aZ, tCurrentItem)) {
mMetaTileEntity.markDirty();
// 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)) {
mMetaTileEntity.markDirty();
mStrongRedstone ^= tSide.flag;
GT_Utility.sendChatToPlayer(
aPlayer,
GT_Utility.trans("091", "Redstone Output at Side ") + tSide
+ GT_Utility.trans("092", " set to: ")
+ ((mStrongRedstone & tSide.flag) != 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();
return true;
}
ForgeDirection coverSide = side;
if (getCoverIDAtSide(side) == 0) coverSide = tSide;
final CoverInfo coverInfo = getCoverInfoAtSide(coverSide);
if (coverInfo.getCoverID() == 0) {
if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sCovers.keySet())) {
final GT_CoverBehaviorBase> coverBehavior = GregTech_API.getCoverBehaviorNew(tCurrentItem);
if (coverBehavior.isCoverPlaceable(coverSide, tCurrentItem, this)
&& mMetaTileEntity.allowCoverOnSide(coverSide, new GT_ItemStack(tCurrentItem))) {
setCoverItemAtSide(coverSide, tCurrentItem);
coverBehavior.onPlayerAttach(aPlayer, tCurrentItem, this, side);
mMetaTileEntity.markDirty();
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, side, false);
mMetaTileEntity.markDirty();
}
return true;
}
}
} else if (aPlayer.isSneaking()) { // Sneak click, no tool -> open cover config or turn back.
side = (getCoverIDAtSide(side) == 0) ? GT_Utility.determineWrenchingSide(side, aX, aY, aZ) : side;
final CoverInfo coverInfo = getCoverInfoAtSide(side);
return coverInfo.isValid() && coverInfo.onCoverShiftRightClick(aPlayer);
}
if (getCoverInfoAtSide(side).onCoverRightClick(aPlayer, aX, aY, aZ)) return true;
}
if (!getCoverInfoAtSide(side).isGUIClickable()) return false;
try {
if (!aPlayer.isSneaking() && hasValidMetaTileEntity()) {
final boolean handled = mMetaTileEntity.onRightclick(this, aPlayer, side, aX, aY, aZ);
if (handled) {
mMetaTileEntity.markDirty();
}
return handled;
}
} catch (Throwable e) {
GT_FML_LOGGER.error("Encountered Exception while right clicking TileEntity", e);
}
return false;
}
@Override
public void onLeftclick(EntityPlayer aPlayer) {
try {
if (aPlayer != null && hasValidMetaTileEntity()) mMetaTileEntity.onLeftclick(this, aPlayer);
} catch (Throwable e) {
GT_FML_LOGGER.error("Encountered Exception while left clicking TileEntity", e);
}
}
@Override
public boolean isDigitalChest() {
return false;
}
@Override
public ItemStack[] getStoredItemData() {
return null;
}
@Override
public void setItemCount(int aCount) {
//
}
@Override
public int 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 ordinalSide) {
final CoverInfo coverInfo = getCoverInfoAtSide(ForgeDirection.getOrientation(ordinalSide));
if (canAccessData() && (coverInfo.letsItemsOut(-1) || coverInfo.letsItemsIn(-1)))
return mMetaTileEntity.getAccessibleSlotsFromSide(ordinalSide);
return GT_Values.emptyIntArray;
}
/**
* Can put aStack into Slot at Side
*/
@Override
public boolean canInsertItem(int aIndex, ItemStack aStack, int ordinalSide) {
return canAccessData() && getCoverInfoAtSide(ForgeDirection.getOrientation(ordinalSide)).letsItemsIn(aIndex)
&& mMetaTileEntity.canInsertItem(aIndex, aStack, ordinalSide);
}
/**
* Can pull aStack out of Slot from Side
*/
@Override
public boolean canExtractItem(int aIndex, ItemStack aStack, int ordinalSide) {
final ForgeDirection side = ForgeDirection.getOrientation(ordinalSide);
return canAccessData()
&& getCoverBehaviorAtSideNew(side)
.letsItemsOut(side, getCoverIDAtSide(side), getComplexCoverDataAtSide(side), aIndex, this)
&& mMetaTileEntity.canExtractItem(aIndex, aStack, ordinalSide);
}
@Override
public boolean isUpgradable() {
return false;
}
@Override
public boolean isSteamEngineUpgradable() {
return isUpgradable() && !hasSteamEngineUpgrade() && getSteamCapacity() > 0;
}
@Override
public boolean addSteamEngineUpgrade() {
if (isSteamEngineUpgradable()) {
issueBlockUpdate();
return true;
}
return false;
}
@Override
public boolean hasSteamEngineUpgrade() {
return false;
}
@Override
public void setGenericRedstoneOutput(boolean aOnOff) {
// Do nothing
}
@Override
public int getErrorDisplayID() {
return 0;
}
@Override
public void setErrorDisplayID(int aErrorID) {
//
}
@Override
public IMetaTileEntity getMetaTileEntity() {
return hasValidMetaTileEntity() ? mMetaTileEntity : null;
}
@Override
public void setMetaTileEntity(IMetaTileEntity aMetaTileEntity) {
mMetaTileEntity = (MetaPipeEntity) aMetaTileEntity;
}
@Override
public void setLightValue(byte aLightValue) {
//
}
@Override
public long getAverageElectricInput() {
return 0;
}
@Override
public long getAverageElectricOutput() {
return 0;
}
@Override
public String getOwnerName() {
return "Player";
}
@Override
public String setOwnerName(String aName) {
return "Player";
}
@Override
public UUID getOwnerUuid() {
return GT_Utility.defaultUuid;
}
@Override
public void setOwnerUuid(UUID uuid) {}
@Override
public byte getComparatorValue(ForgeDirection side) {
return canAccessData() ? mMetaTileEntity.getComparatorValue(side) : 0;
}
@Override
public ItemStack decrStackSize(int aIndex, int aAmount) {
if (canAccessData()) {
mInventoryChanged = true;
return mMetaTileEntity.decrStackSize(aIndex, aAmount);
}
return null;
}
@Override
public long injectEnergyUnits(ForgeDirection side, long aVoltage, long aAmperage) {
if (canAccessData()) return mMetaTileEntity.injectEnergyUnits(side, aVoltage, aAmperage);
return 0;
}
@Override
public boolean drainEnergyUnits(ForgeDirection side, long aVoltage, long aAmperage) {
return false;
}
@Override
public boolean acceptsRotationalEnergy(ForgeDirection side) {
if (!canAccessData() || getCoverIDAtSide(side) != 0) return false;
return mMetaTileEntity.acceptsRotationalEnergy(side);
}
@Override
public boolean injectRotationalEnergy(ForgeDirection side, long aSpeed, long aEnergy) {
if (!canAccessData() || getCoverIDAtSide(side) != 0) return false;
return mMetaTileEntity.injectRotationalEnergy(side, aSpeed, aEnergy);
}
private boolean canMoveFluidOnSide(ForgeDirection side, Fluid fluid, boolean isFill) {
if (side == ForgeDirection.UNKNOWN) return true;
final IFluidHandler tTileEntity = getITankContainerAtSide(side);
// Only require a connection if there's something to connect to - Allows fluid cells & buckets to interact with
// the pipe
if (tTileEntity != null && !mMetaTileEntity.isConnectedAtSide(side)) return false;
if (isFill && mMetaTileEntity.isLiquidInput(side) && getCoverInfoAtSide(side).letsFluidIn(fluid)) return true;
return !isFill && mMetaTileEntity.isLiquidOutput(side) && getCoverInfoAtSide(side).letsFluidOut(fluid);
}
@Override
public int fill(ForgeDirection side, FluidStack aFluidStack, boolean doFill) {
if (mTickTimer > 5 && canAccessData()
&& canMoveFluidOnSide(side, aFluidStack == null ? null : aFluidStack.getFluid(), true))
return mMetaTileEntity.fill(side, aFluidStack, doFill);
return 0;
}
@Override
public FluidStack drain(ForgeDirection side, int maxDrain, boolean doDrain) {
if (mTickTimer > 5 && canAccessData()
&& canMoveFluidOnSide(
side,
mMetaTileEntity.getFluid() == null ? null
: mMetaTileEntity.getFluid()
.getFluid(),
false))
return mMetaTileEntity.drain(side, maxDrain, doDrain);
return null;
}
@Override
public FluidStack drain(ForgeDirection side, FluidStack aFluidStack, boolean doDrain) {
if (mTickTimer > 5 && canAccessData()
&& canMoveFluidOnSide(side, aFluidStack == null ? null : aFluidStack.getFluid(), false))
return mMetaTileEntity.drain(side, aFluidStack, doDrain);
return null;
}
@Override
public boolean canFill(ForgeDirection side, Fluid aFluid) {
if (mTickTimer > 5 && canAccessData() && canMoveFluidOnSide(side, aFluid, true))
return mMetaTileEntity.canFill(side, aFluid);
return false;
}
@Override
public boolean canDrain(ForgeDirection side, Fluid aFluid) {
if (mTickTimer > 5 && canAccessData() && canMoveFluidOnSide(side, aFluid, false))
return mMetaTileEntity.canDrain(side, aFluid);
return false;
}
@Override
public FluidTankInfo[] getTankInfo(ForgeDirection side) {
final CoverInfo coverInfo = getCoverInfoAtSide(side);
if (canAccessData()
&& (side == ForgeDirection.UNKNOWN || (mMetaTileEntity.isLiquidInput(side) && coverInfo.letsFluidIn(null))
|| (mMetaTileEntity.isLiquidOutput(side) && coverInfo.letsFluidOut(null))
// Doesn't need to be connected to get Tank Info -- otherwise things can't connect
)) return mMetaTileEntity.getTankInfo(side);
return new FluidTankInfo[] {};
}
@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())) {
markDirty();
tStack.stackSize += aStack.stackSize;
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 getThickNess() {
if (canAccessData()) return mMetaTileEntity.getThickNess();
return 1.0F;
}
public boolean renderInside(ForgeDirection side) {
if (canAccessData()) return mMetaTileEntity.renderInside(side);
return false;
}
@Override
public float getBlastResistance(ForgeDirection side) {
return canAccessData() ? Math.max(0, getMetaTileEntity().getExplosionResistance(side)) : 5.0F;
}
@Override
public void onBlockDestroyed() {
if (canAccessData()) getMetaTileEntity().onBlockDestroyed();
}
@Override
public boolean isMufflerUpgradable() {
return false;
}
@Override
public boolean addMufflerUpgrade() {
return false;
}
@Override
public boolean hasMufflerUpgrade() {
return false;
}
@Override
public boolean isUniversalEnergyStored(long aEnergyAmount) {
return getUniversalEnergyStored() >= aEnergyAmount;
}
@Override
public String[] getInfoData() {
if (canAccessData()) return getMetaTileEntity().getInfoData();
return new String[] {};
}
@Override
public byte getConnections() {
return mConnections;
}
public void onNeighborBlockChange(int aX, int aY, int aZ) {
if (canAccessData()) {
final IMetaTileEntity meta = getMetaTileEntity();
if (meta instanceof MetaPipeEntity) {
// Trigger a checking of connections in case someone placed down a block that the pipe/wire shouldn't be
// connected to.
// However; don't do it immediately in case the world isn't finished loading
// (This caused issues with AE2 GTEU p2p connections.
((MetaPipeEntity) meta).setCheckConnections();
}
}
}
@Override
public int getLightOpacity() {
return mMetaTileEntity == null ? 0 : 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);
}
@Override
public int[] getTimeStatistics() {
return mTimeStatistics;
}
@Override
public void startTimeStatistics() {
hasTimeStatisticsStarted = true;
}
@Override
public void getWailaBody(ItemStack itemStack, List currentTip, IWailaDataAccessor accessor,
IWailaConfigHandler config) {
super.getWailaBody(itemStack, currentTip, accessor, config);
mMetaTileEntity.getWailaBody(itemStack, currentTip, accessor, config);
}
}