package pneumaticCraft.common.tileentity;
import java.util.List;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.ChunkPosition;
import net.minecraftforge.common.util.ForgeDirection;
import pneumaticCraft.common.block.BlockPneumaticDoor;
import pneumaticCraft.common.block.Blockss;
import pneumaticCraft.common.item.ItemMachineUpgrade;
import pneumaticCraft.common.item.Itemss;
import pneumaticCraft.common.network.DescSynced;
import pneumaticCraft.common.network.GuiSynced;
import pneumaticCraft.common.network.LazySynced;
import pneumaticCraft.common.util.PneumaticCraftUtils;
import pneumaticCraft.lib.PneumaticValues;
import pneumaticCraft.lib.TileEntityConstants;
public class TileEntityPneumaticDoorBase extends TileEntityPneumaticBase implements IInventory, IRedstoneControl,
IMinWorkingPressure{
private TileEntityPneumaticDoor door;
private TileEntityPneumaticDoorBase doubleDoor;
@DescSynced
public boolean rightGoing;
public float oldProgress;
@DescSynced
@LazySynced
public float progress;
@DescSynced
private boolean opening;
public boolean wasPowered;
@DescSynced
private ItemStack[] inventory = new ItemStack[5];
@GuiSynced
public int redstoneMode;
@DescSynced
public ForgeDirection orientation = ForgeDirection.UNKNOWN;
public static final int UPGRADE_SLOT_1 = 0;
public static final int UPGRADE_SLOT_4 = 3;
public static final int CAMO_SLOT = 4;
private ItemStack oldCamo;
public TileEntityPneumaticDoorBase(){
super(PneumaticValues.DANGER_PRESSURE_PNEUMATIC_DOOR, PneumaticValues.MAX_PRESSURE_PNEUMATIC_DOOR, PneumaticValues.VOLUME_PNEUMATIC_DOOR);
setUpgradeSlots(new int[]{UPGRADE_SLOT_1, 1, 2, UPGRADE_SLOT_4});
}
@Override
public void updateEntity(){
super.updateEntity();
oldProgress = progress;
if(!worldObj.isRemote) {
if(getPressure(ForgeDirection.UNKNOWN) >= PneumaticValues.MIN_PRESSURE_PNEUMATIC_DOOR) {
if(worldObj.getTotalWorldTime() % 60 == 0) {
TileEntity te = worldObj.getTileEntity(orientation.offsetX * 3 + xCoord, yCoord, orientation.offsetZ * 3 + zCoord);
if(te instanceof TileEntityPneumaticDoorBase) {
doubleDoor = (TileEntityPneumaticDoorBase)te;
} else {
doubleDoor = null;
}
}
setOpening(shouldOpen() || isNeighborOpening());
setNeighborOpening(isOpening());
} else {
setOpening(true);
}
}
float targetProgress = opening ? 1F : 0F;
float speedMultiplier = getSpeedMultiplierFromUpgrades(getUpgradeSlots());
if(progress < targetProgress) {
if(progress < targetProgress - TileEntityConstants.PNEUMATIC_DOOR_EXTENSION) {
progress += TileEntityConstants.PNEUMATIC_DOOR_SPEED_FAST * speedMultiplier;
} else {
progress += TileEntityConstants.PNEUMATIC_DOOR_SPEED_SLOW * speedMultiplier;
}
if(progress > targetProgress) progress = targetProgress;
}
if(progress > targetProgress) {
if(progress > targetProgress + TileEntityConstants.PNEUMATIC_DOOR_EXTENSION) {
progress -= TileEntityConstants.PNEUMATIC_DOOR_SPEED_FAST * speedMultiplier;
} else {
progress -= TileEntityConstants.PNEUMATIC_DOOR_SPEED_SLOW * speedMultiplier;
}
if(progress < targetProgress) progress = targetProgress;
}
if(!worldObj.isRemote) addAir((int)(-Math.abs(oldProgress - progress) * PneumaticValues.USAGE_PNEUMATIC_DOOR * (getSpeedUsageMultiplierFromUpgrades(getUpgradeSlots()) / speedMultiplier)), ForgeDirection.UNKNOWN);
// if(worldObj.isRemote) System.out.println("progress: " + progress);
door = getDoor();
if(door != null) {
door.setRotation(progress * 90);
if(!worldObj.isRemote) rightGoing = door.rightGoing;
}
if(oldCamo != inventory[CAMO_SLOT]) {
oldCamo = inventory[CAMO_SLOT];
worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, inventory[CAMO_SLOT] != null ? inventory[CAMO_SLOT].getItemDamage() % 16 : 0, 2);
worldObj.markBlockRangeForRenderUpdate(xCoord, yCoord, zCoord, xCoord, yCoord, zCoord);
}
}
private boolean shouldOpen(){
switch(redstoneMode){
case 0:
case 1:
int range = TileEntityConstants.RANGE_PNEUMATIC_DOOR_BASE + this.getUpgrades(ItemMachineUpgrade.UPGRADE_RANGE);
AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(xCoord - range, yCoord - range, zCoord - range, xCoord + range + 1, yCoord + range + 1, zCoord + range + 1);
List<EntityPlayer> players = worldObj.getEntitiesWithinAABB(EntityPlayer.class, aabb);
for(EntityPlayer player : players) {
if(PneumaticCraftUtils.getProtectingSecurityStations(worldObj, xCoord, yCoord, zCoord, player, false, false) == 0) {
if(redstoneMode == 0) {
return true;
} else {
((BlockPneumaticDoor)Blockss.pneumaticDoor).isTrackingPlayerEye = true;
ChunkPosition lookedPosition = PneumaticCraftUtils.getEntityLookedBlock(player, range * 1.41F); //max range = range * sqrt(2).
((BlockPneumaticDoor)Blockss.pneumaticDoor).isTrackingPlayerEye = false;
if(lookedPosition != null) {
if(lookedPosition.equals(new ChunkPosition(xCoord, yCoord, zCoord))) {
return true;
} else {
if(door != null) {
if(lookedPosition.equals(new ChunkPosition(door.xCoord, door.yCoord, door.zCoord))) return true;
if(lookedPosition.equals(new ChunkPosition(door.xCoord, door.yCoord + (door.getBlockMetadata() < 6 ? 1 : -1), door.zCoord))) return true;
}
}
}
}
}
}
return false;
case 2:
return opening;
}
return false;
}
public void setOpening(boolean opening){
this.opening = opening;
}
public boolean isOpening(){
return opening;
}
private boolean isNeighborOpening(){
return doubleDoor != null ? doubleDoor.shouldOpen() : false;
}
public void setNeighborOpening(boolean opening){
if(doubleDoor != null && doubleDoor.getPressure(ForgeDirection.UNKNOWN) >= PneumaticValues.MIN_PRESSURE_PNEUMATIC_DOOR) {
doubleDoor.setOpening(opening);
}
}
@Override
public boolean isConnectedTo(ForgeDirection side){
return side != ForgeDirection.UP;
}
private TileEntityPneumaticDoor getDoor(){
TileEntity te = worldObj.getTileEntity(orientation.offsetX + xCoord, yCoord - 1, orientation.offsetZ + zCoord);
if(te instanceof TileEntityPneumaticDoor) {
if(orientation.getRotation(ForgeDirection.UP) == ForgeDirection.getOrientation(te.getBlockMetadata()) && !((TileEntityPneumaticDoor)te).rightGoing) {
return (TileEntityPneumaticDoor)te;
} else if(orientation.getRotation(ForgeDirection.DOWN) == ForgeDirection.getOrientation(te.getBlockMetadata()) && ((TileEntityPneumaticDoor)te).rightGoing) {
return (TileEntityPneumaticDoor)te;
}
}
return null;
}
// NBT methods-----------------------------------------------
@Override
public void readFromNBT(NBTTagCompound tag){
super.readFromNBT(tag);
progress = tag.getFloat("extension");
opening = tag.getBoolean("opening");
redstoneMode = tag.getInteger("redstoneMode");
orientation = ForgeDirection.getOrientation(tag.getInteger("orientation"));
rightGoing = tag.getBoolean("rightGoing");
// Read in the ItemStacks in the inventory from NBT
NBTTagList tagList = tag.getTagList("Items", 10);
inventory = new ItemStack[getSizeInventory()];
for(int i = 0; i < tagList.tagCount(); ++i) {
NBTTagCompound tagCompound = tagList.getCompoundTagAt(i);
byte slot = tagCompound.getByte("Slot");
if(slot >= 0 && slot < inventory.length) {
inventory[slot] = ItemStack.loadItemStackFromNBT(tagCompound);
}
}
}
@Override
public void writeToNBT(NBTTagCompound tag){
super.writeToNBT(tag);
tag.setFloat("extension", progress);
tag.setBoolean("opening", opening);
tag.setInteger("orientation", orientation.ordinal());
tag.setInteger("redstoneMode", redstoneMode);
tag.setBoolean("rightGoing", rightGoing);
// Write the ItemStacks in the inventory to NBT
NBTTagList tagList = new NBTTagList();
for(int currentIndex = 0; currentIndex < inventory.length; ++currentIndex) {
if(inventory[currentIndex] != null) {
NBTTagCompound tagCompound = new NBTTagCompound();
tagCompound.setByte("Slot", (byte)currentIndex);
inventory[currentIndex].writeToNBT(tagCompound);
tagList.appendTag(tagCompound);
}
}
tag.setTag("Items", tagList);
}
@Override
public void handleGUIButtonPress(int buttonID, EntityPlayer player){
if(buttonID == 0) {
redstoneMode++;
if(redstoneMode > 2) redstoneMode = 0;
}
}
// INVENTORY METHODS-
// ------------------------------------------------------------
/**
* Returns the number of slots in the inventory.
*/
@Override
public int getSizeInventory(){
return inventory.length;
}
/**
* Returns the stack in slot i
*/
@Override
public ItemStack getStackInSlot(int slot){
return inventory[slot];
}
@Override
public ItemStack decrStackSize(int slot, int amount){
ItemStack itemStack = getStackInSlot(slot);
if(itemStack != null) {
if(itemStack.stackSize <= amount) {
setInventorySlotContents(slot, null);
} else {
itemStack = itemStack.splitStack(amount);
if(itemStack.stackSize == 0) {
setInventorySlotContents(slot, null);
}
}
}
return itemStack;
}
@Override
public ItemStack getStackInSlotOnClosing(int slot){
ItemStack itemStack = getStackInSlot(slot);
if(itemStack != null) {
setInventorySlotContents(slot, null);
}
return itemStack;
}
@Override
public void setInventorySlotContents(int slot, ItemStack itemStack){
// super.setInventorySlotContents(slot, itemStack);
inventory[slot] = itemStack;
if(itemStack != null && itemStack.stackSize > getInventoryStackLimit()) {
itemStack.stackSize = getInventoryStackLimit();
}
}
@Override
public int getInventoryStackLimit(){
return 64;
}
@Override
public String getInventoryName(){
return Blockss.pneumaticDoorBase.getUnlocalizedName();
}
@Override
public void openInventory(){}
@Override
public void closeInventory(){}
@Override
public boolean isItemValidForSlot(int i, ItemStack itemstack){
return i == CAMO_SLOT || itemstack.getItem() == Itemss.machineUpgrade;
}
@Override
public boolean hasCustomInventoryName(){
return false;
}
@Override
public boolean isUseableByPlayer(EntityPlayer var1){
return isGuiUseableByPlayer(var1);
}
@Override
public float getMinWorkingPressure(){
return PneumaticValues.MIN_PRESSURE_PNEUMATIC_DOOR;
}
@Override
public int getRedstoneMode(){
return redstoneMode;
}
}