package pneumaticCraft.common.tileentity;
import java.util.List;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
import org.apache.commons.lang3.tuple.Pair;
import pneumaticCraft.api.tileentity.IAirHandler;
import pneumaticCraft.api.tileentity.IPneumaticMachine;
import pneumaticCraft.api.tileentity.ISidedPneumaticMachine;
import pneumaticCraft.common.block.tubes.IInfluenceDispersing;
import pneumaticCraft.common.block.tubes.ModuleAirGrate;
import pneumaticCraft.common.block.tubes.ModuleFlowDetector;
import pneumaticCraft.common.block.tubes.ModulePressureGauge;
import pneumaticCraft.common.block.tubes.ModuleRegistrator;
import pneumaticCraft.common.block.tubes.ModuleRegulatorTube;
import pneumaticCraft.common.block.tubes.ModuleSafetyValve;
import pneumaticCraft.common.block.tubes.TubeModule;
import pneumaticCraft.common.network.DescSynced;
import pneumaticCraft.common.thirdparty.ModInteractionUtils;
import pneumaticCraft.common.thirdparty.fmp.PartPressureTube;
import pneumaticCraft.common.util.PneumaticCraftUtils;
import pneumaticCraft.lib.Log;
import pneumaticCraft.lib.ModIds;
import pneumaticCraft.lib.PneumaticValues;
import cpw.mods.fml.common.Optional;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
public class TileEntityPressureTube extends TileEntityPneumaticBase{
@DescSynced
public boolean[] sidesConnected = new boolean[6];
public TubeModule[] modules = new TubeModule[6];
private Object part;
public TileEntityPressureTube(){
super(PneumaticValues.DANGER_PRESSURE_PRESSURE_TUBE, PneumaticValues.MAX_PRESSURE_PRESSURE_TUBE, PneumaticValues.VOLUME_PRESSURE_TUBE);
}
public TileEntityPressureTube(float dangerPressurePressureTube, float maxPressurePressureTube,
int volumePressureTube){
super(dangerPressurePressureTube, maxPressurePressureTube, volumePressureTube);
}
public TileEntityPressureTube setPart(Object part){
this.part = part;
for(TubeModule module : modules) {
if(module != null) module.shouldDrop = false;
}
return this;
}
@Override
public void readFromNBT(NBTTagCompound nbt){
super.readFromNBT(nbt);
for(int i = 0; i < 6; i++) {
sidesConnected[i] = nbt.getBoolean("sideConnected" + i);
}
}
@Override
public void writeToNBT(NBTTagCompound nbt){
super.writeToNBT(nbt);
for(int i = 0; i < 6; i++) {
nbt.setBoolean("sideConnected" + i, sidesConnected[i]);
}
}
@Override
public void writeToPacket(NBTTagCompound tag){
super.writeToPacket(tag);
writeModulesToNBT(tag);
}
public void writeModulesToNBT(NBTTagCompound tag){
NBTTagList moduleList = new NBTTagList();
for(int i = 0; i < modules.length; i++) {
if(modules[i] != null) {
NBTTagCompound moduleTag = new NBTTagCompound();
moduleTag.setString("type", modules[i].getType());
modules[i].writeToNBT(moduleTag);
moduleTag.setInteger("side", i);
moduleList.appendTag(moduleTag);
}
}
tag.setTag("modules", moduleList);
}
@Override
public void readFromPacket(NBTTagCompound tag){
super.readFromPacket(tag);
modules = new TubeModule[6];
NBTTagList moduleList = tag.getTagList("modules", 10);
for(int i = 0; i < moduleList.tagCount(); i++) {
NBTTagCompound moduleTag = moduleList.getCompoundTagAt(i);
TubeModule module = ModuleRegistrator.getModule(moduleTag.getString("type"));
module.readFromNBT(moduleTag);
setModule(module, ForgeDirection.getOrientation(moduleTag.getInteger("side")));
}
if(worldObj != null && worldObj.isRemote) {
rerenderChunk();
}
}
@Override
public void updateEntity(){
super.updateEntity();
for(TubeModule module : modules) {
if(module != null) {
module.shouldDrop = true;
module.update();
}
}
List<Pair<ForgeDirection, IAirHandler>> teList = getConnectedPneumatics();
boolean hasModules = false;
for(TubeModule module : modules) {
if(module != null) {
hasModules = true;
break;
}
}
if(!hasModules && teList.size() - specialConnectedHandlers.size() == 1 && !worldObj.isRemote) {
for(Pair<ForgeDirection, IAirHandler> entry : teList) {
if(entry.getKey() != ForgeDirection.UNKNOWN && modules[entry.getKey().getOpposite().ordinal()] == null && isConnectedTo(entry.getKey().getOpposite())) airLeak(entry.getKey().getOpposite());
}
}
}
@Override
protected void onAirDispersion(int amount, ForgeDirection side){
if(side != ForgeDirection.UNKNOWN) {
int intSide = side/*.getOpposite()*/.ordinal();
if(modules[intSide] instanceof IInfluenceDispersing) {
((IInfluenceDispersing)modules[intSide]).onAirDispersion(amount);
}
}
}
@Override
protected int getMaxDispersion(ForgeDirection side){
if(side != ForgeDirection.UNKNOWN) {
int intSide = side/*.getOpposite()*/.ordinal();
if(modules[intSide] instanceof IInfluenceDispersing) {
return ((IInfluenceDispersing)modules[intSide]).getMaxDispersion();
}
}
return Integer.MAX_VALUE;
}
@Override
protected void onFirstServerUpdate(){
legacyHelper();
}
//TODO legacy, remove after a while
private void legacyHelper(){
if(getBlockMetadata() > 0) {
switch(getBlockMetadata()){
case 1:
legacyAddModule(new ModuleFlowDetector());
break;
case 2:
legacyAddModule(new ModuleSafetyValve());
break;
case 3:
legacyAddModule(new ModuleRegulatorTube());
break;
case 4:
legacyAddModule(new ModuleAirGrate());
break;
case 5:
legacyAddModule(new ModulePressureGauge());
}
NBTTagCompound tag = new NBTTagCompound();
writeToNBT(tag);
worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, 0, 3);
((TileEntityPressureTube)worldObj.getTileEntity(xCoord, yCoord, zCoord)).readFromNBT(tag);
}
}
private void legacyAddModule(TubeModule module){
for(int i = 0; i < 6; i++) {
if(sidesConnected[i] == module.isInline()) {
Log.info("Converting legacy Pressure Tube to tube with module: " + module.getType() + " at " + xCoord + ", " + yCoord + ", " + zCoord);
setModule(module, ForgeDirection.getOrientation(i));
return;
}
}
Log.warning("Converting legacy Pressure Tube. TUBES ARE ALL CONNECTED, force connecting! Module: " + module.getType() + " at " + xCoord + ", " + yCoord + ", " + zCoord);
setModule(module, ForgeDirection.getOrientation(0));
}
public void setModule(TubeModule module, ForgeDirection side){
if(module != null) {
module.setDirection(side);
module.setTube(this);
}
modules[side.ordinal()] = module;
if(worldObj != null && !worldObj.isRemote) {
if(part != null) updatePart();
sendDescriptionPacket();
}
}
@Override
public boolean isConnectedTo(ForgeDirection side){
return (modules[side.ordinal()] == null || modules[side.ordinal()].isInline()) && (part == null || ModInteractionUtils.getInstance().isMultipartWiseConnected(part, side));
}
@Override
public void onNeighborTileUpdate(){
super.onNeighborTileUpdate();
updateConnections(worldObj, xCoord, yCoord, zCoord);
for(TubeModule module : modules) {
if(module != null) module.onNeighborTileUpdate();
}
}
@Override
public void onNeighborBlockUpdate(){
super.onNeighborBlockUpdate();
updateConnections(worldObj, xCoord, yCoord, zCoord);
for(TubeModule module : modules) {
if(module != null) module.onNeighborBlockUpdate();
}
}
public void updateConnections(World world, int x, int y, int z){
sidesConnected = new boolean[6];
boolean hasModule = false;
for(ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) {
TileEntity te = getTileCache()[direction.ordinal()].getTileEntity();
IPneumaticMachine machine = ModInteractionUtils.getInstance().getMachine(te);
if(machine != null) {
sidesConnected[direction.ordinal()] = isConnectedTo(direction) && machine.isConnectedTo(direction.getOpposite());
} else if(te instanceof ISidedPneumaticMachine) {
sidesConnected[direction.ordinal()] = ((ISidedPneumaticMachine)te).getAirHandler(direction.getOpposite()) != null;
}
if(modules[direction.ordinal()] != null) {
hasModule = true;
}
}
int sidesCount = 0;
for(boolean bool : sidesConnected) {
if(bool) sidesCount++;
}
if(sidesCount == 1 && !hasModule) {
for(int i = 0; i < 6; i++) {
if(sidesConnected[i]) {
if(isConnectedTo(ForgeDirection.getOrientation(i).getOpposite())) sidesConnected[i ^ 1] = true;
break;
}
}
}
for(int i = 0; i < 6; i++) {
if(modules[i] != null && modules[i].isInline()) sidesConnected[i] = false;
}
}
@Override
@SideOnly(Side.CLIENT)
public AxisAlignedBB getRenderBoundingBox(){
return AxisAlignedBB.getBoundingBox(xCoord, yCoord, zCoord, xCoord + 1, yCoord + 1, zCoord + 1);
}
@Override
public void printManometerMessage(EntityPlayer player, List<String> text){
super.printManometerMessage(player, text);
MovingObjectPosition mop = PneumaticCraftUtils.getEntityLookedObject(player);
if(mop != null && mop.hitInfo instanceof ForgeDirection) {
ForgeDirection dir = (ForgeDirection)mop.hitInfo;
if(dir != ForgeDirection.UNKNOWN && modules[dir.ordinal()] != null) {
modules[dir.ordinal()].addInfo(text);
}
}
}
@Override
@Optional.Method(modid = ModIds.FMP)
public void sendDescriptionPacket(){
if(part != null && !worldObj.isRemote) {
((PartPressureTube)part).sendDescUpdate();
}
super.sendDescriptionPacket();
}
@Optional.Method(modid = ModIds.FMP)
public void updatePart(){
((PartPressureTube)part).onNeighborChanged();
}
}