package pneumaticCraft.common.tileentity;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.passive.EntityVillager;
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.World;
import net.minecraftforge.common.util.ForgeDirection;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import pneumaticCraft.api.recipe.IPressureChamberRecipe;
import pneumaticCraft.api.recipe.PressureChamberRecipe;
import pneumaticCraft.api.tileentity.IPneumaticMachine;
import pneumaticCraft.common.Config;
import pneumaticCraft.common.DamageSourcePneumaticCraft;
import pneumaticCraft.common.block.Blockss;
import pneumaticCraft.common.item.ItemMachineUpgrade;
import pneumaticCraft.common.item.Itemss;
import pneumaticCraft.common.util.PneumaticCraftUtils;
import pneumaticCraft.lib.PneumaticValues;
public class TileEntityPressureChamberValve extends TileEntityPneumaticBase implements IInventory, IMinWorkingPressure{
public int multiBlockX;
public int multiBlockY;
public int multiBlockZ;
public int multiBlockSize;
public List<TileEntityPressureChamberValve> accessoryValves;
private final List<int[]> nbtValveList;
private boolean readNBT = false;
public boolean isValidRecipeInChamber;
public boolean isSufficientPressureInChamber;
public boolean areEntitiesDoneMoving;
public float recipePressure;
private ItemStack[] inventory = new ItemStack[4];
public static final int UPGRADE_SLOT_1 = 0;
public static final int UPGRADE_SLOT_4 = 3;
private final Random rand = new Random();
// private float oldPressure;
// private int pressureUpdateTimer = 60;
public TileEntityPressureChamberValve(){
super(PneumaticValues.DANGER_PRESSURE_PRESSURE_CHAMBER, PneumaticValues.MAX_PRESSURE_PRESSURE_CHAMBER, PneumaticValues.VOLUME_PRESSURE_CHAMBER);
accessoryValves = new ArrayList<TileEntityPressureChamberValve>();
nbtValveList = new ArrayList<int[]>();
setUpgradeSlots(new int[]{UPGRADE_SLOT_1, 1, 2, UPGRADE_SLOT_4});
}
// pneumatic methods-------------------------------------------------------
// used in the air dispersion methods.
@Override
public boolean isConnectedTo(ForgeDirection side){
switch(ForgeDirection.getOrientation(getBlockMetadata())){
case UP:
case DOWN:
return side == ForgeDirection.UP || side == ForgeDirection.DOWN;
case NORTH:
case SOUTH:
return side == ForgeDirection.NORTH || side == ForgeDirection.SOUTH;
case EAST:
case WEST:
return side == ForgeDirection.EAST || side == ForgeDirection.WEST;
}
return false;
}
@Override
public List<Pair<ForgeDirection, IPneumaticMachine>> getConnectedPneumatics(){
List<Pair<ForgeDirection, IPneumaticMachine>> teList = super.getConnectedPneumatics();
if(accessoryValves != null) {
for(TileEntityPressureChamberValve valve : accessoryValves) {
if(valve != this) teList.add(new ImmutablePair(ForgeDirection.UNKNOWN, valve));
}
}
return teList;
}
@Override
protected int getVolumeFromUpgrades(int[] upgradeSlots){
return super.getVolumeFromUpgrades(getUpgradeSlots()) + (multiBlockSize > 0 ? (int)Math.pow(multiBlockSize - 2, 3) * PneumaticValues.VOLUME_PRESSURE_CHAMBER_PER_EMPTY : 0);
}
// main update method
@Override
public void updateEntity(){
if(readNBT) {// this way of doing this is needed because other TE's are
// loaded after the reading of the NBT of this TE.
readNBT = false;
accessoryValves.clear();
for(int[] valve : nbtValveList) {
TileEntity te = worldObj.getTileEntity(valve[0], valve[1], valve[2]);
if(te instanceof TileEntityPressureChamberValve) {
accessoryValves.add((TileEntityPressureChamberValve)te);
}
}
if(worldObj.isRemote) worldObj.markBlockRangeForRenderUpdate(xCoord, yCoord, zCoord, xCoord, yCoord, zCoord);
}
if(!worldObj.isRemote) {
//code to check if we need to leak air.
boolean[] connected = new boolean[]{true, true, true, true, true, true};//assume we are not leaking at any side
switch(ForgeDirection.getOrientation(getBlockMetadata())){//take off the sides that tubes can connect to.
case UP:
case DOWN:
connected[ForgeDirection.UP.ordinal()] = false;
connected[ForgeDirection.DOWN.ordinal()] = false;
break;
case NORTH:
case SOUTH:
connected[ForgeDirection.NORTH.ordinal()] = false;
connected[ForgeDirection.SOUTH.ordinal()] = false;
break;
case EAST:
case WEST:
connected[ForgeDirection.EAST.ordinal()] = false;
connected[ForgeDirection.WEST.ordinal()] = false;
break;
}
List<Pair<ForgeDirection, IPneumaticMachine>> teList = super.getConnectedPneumatics();//we need the super method, as the overridden method adds the other valves.
for(Pair<ForgeDirection, IPneumaticMachine> entry : teList) {
connected[entry.getKey().ordinal()] = true;
}
//retrieve the valve that is controlling the (potential) chamber.
TileEntityPressureChamberValve baseValve = null;
for(TileEntityPressureChamberValve valve : accessoryValves) {
if(valve.multiBlockSize > 0) {
baseValve = valve;
break;
}
}
//if we found one, we can scratch one side to be leaking air.
if(baseValve != null) {
switch(ForgeDirection.getOrientation(getBlockMetadata())){
case UP:
case DOWN:
if(baseValve.multiBlockY == yCoord) connected[ForgeDirection.UP.ordinal()] = true;
else connected[ForgeDirection.DOWN.ordinal()] = true;
break;
case NORTH:
case SOUTH:
if(baseValve.multiBlockZ == zCoord) connected[ForgeDirection.SOUTH.ordinal()] = true;
else connected[ForgeDirection.NORTH.ordinal()] = true;
break;
case EAST:
case WEST:
if(baseValve.multiBlockX == xCoord) connected[ForgeDirection.EAST.ordinal()] = true;
else connected[ForgeDirection.WEST.ordinal()] = true;
break;
}
}
for(int i = 0; i < 6; i++)
if(!connected[i]) airLeak(ForgeDirection.getOrientation(i));
}
super.updateEntity();
/*
* FIXME pressure chamber particle effects not updating properly
* if(!worldObj.isRemote){ pressureUpdateTimer++;
* System.out.println("timer: " + pressureUpdateTimer);
* if(pressureUpdateTimer > 60){ pressureUpdateTimer = 0;
* updatePressuresToClient(); } }
*/
if(multiBlockSize != 0 && !worldObj.isRemote) {
ItemStack[] stacksInChamber = getStacksInChamber();
boolean oldValidRecipes = isValidRecipeInChamber;
boolean oldSufficientPressure = isSufficientPressureInChamber;
isValidRecipeInChamber = false;
isSufficientPressureInChamber = false;
recipePressure = Float.MAX_VALUE;
//simple recipes
for(PressureChamberRecipe recipe : PressureChamberRecipe.chamberRecipes) {
boolean isValidRecipeInChamberFlag = canBeCompressed(recipe, stacksInChamber);
boolean isSufficientPressureInChamberFlag = recipe.pressure <= getPressure(ForgeDirection.UNKNOWN) && recipe.pressure > 0F || recipe.pressure >= getPressure(ForgeDirection.UNKNOWN) && recipe.pressure < 0F;
if(isValidRecipeInChamberFlag) {
isValidRecipeInChamber = true;
if(Math.abs(recipe.pressure) < Math.abs(recipePressure)) {
recipePressure = recipe.pressure;
}
}
if(isSufficientPressureInChamberFlag) isSufficientPressureInChamber = true;
if(isValidRecipeInChamberFlag && isSufficientPressureInChamberFlag && areEntitiesDoneMoving) {
double[] outputPosition = clearStacksInChamber(recipe.input);
giveOutput(recipe.output, recipe.outputAsBlock, outputPosition);
}
}
//special recipes
for(IPressureChamberRecipe recipe : PressureChamberRecipe.specialRecipes) {
ItemStack[] removedStacks = recipe.isValidRecipe(stacksInChamber);
boolean isValidRecipeInChamberFlag = removedStacks != null;
boolean isSufficientPressureInChamberFlag = recipe.getCraftingPressure() <= getPressure(ForgeDirection.UNKNOWN) && recipe.getCraftingPressure() > 0F || recipe.getCraftingPressure() >= getPressure(ForgeDirection.UNKNOWN) && recipe.getCraftingPressure() < 0F;
if(isValidRecipeInChamberFlag) {
isValidRecipeInChamber = true;
if(Math.abs(recipe.getCraftingPressure()) < Math.abs(recipePressure)) {
recipePressure = recipe.getCraftingPressure();
}
}
if(isSufficientPressureInChamberFlag) isSufficientPressureInChamber = true;
if(isValidRecipeInChamberFlag && isSufficientPressureInChamberFlag && areEntitiesDoneMoving) {
double[] outputPosition = clearStacksInChamber(removedStacks);
giveOutput(recipe.craftRecipe(stacksInChamber, removedStacks), false, outputPosition);
}
}
if(oldValidRecipes != isValidRecipeInChamber || oldSufficientPressure != isSufficientPressureInChamber) {
sendDescriptionPacket();
}
if(getPressure(ForgeDirection.UNKNOWN) > PneumaticValues.MAX_PRESSURE_LIVING_ENTITY) {
AxisAlignedBB bbBox = AxisAlignedBB.getBoundingBox(multiBlockX + 1, multiBlockY + 1, multiBlockZ + 1, multiBlockX + multiBlockSize - 1, multiBlockY + multiBlockSize - 1, multiBlockZ + multiBlockSize - 1);
List<EntityLivingBase> entities = worldObj.getEntitiesWithinAABB(EntityLivingBase.class, bbBox);
for(EntityLivingBase entity : entities) {
if(entity instanceof EntityVillager) {
EntityVillager villager = (EntityVillager)entity;
if(villager.getProfession() != Config.villagerMechanicID) {
villager.setProfession(Config.villagerMechanicID);
NBTTagCompound tag = new NBTTagCompound();
villager.writeEntityToNBT(tag);
if(tag.hasKey("Offers")) {//reset the trade list
tag.removeTag("Offers");
villager.readEntityFromNBT(tag);
}
}
}
entity.attackEntityFrom(DamageSourcePneumaticCraft.pressure, (int)(getPressure(ForgeDirection.UNKNOWN) * 2D));
}
}
}
// move entities to eachother.
AxisAlignedBB bbBox = AxisAlignedBB.getBoundingBox(multiBlockX, multiBlockY, multiBlockZ, multiBlockX + multiBlockSize, multiBlockY + multiBlockSize, multiBlockZ + multiBlockSize);
List<EntityItem> entities = worldObj.getEntitiesWithinAABB(EntityItem.class, bbBox);
areEntitiesDoneMoving = true; // set to true, set to false when one of
// the entities is moving.
for(int i = 0; i < entities.size() - 1; i++) {
EntityItem lastEntity = entities.get(i);
EntityItem entity = entities.get(i + 1);
// XP Orb code snippet
double d0 = 8.0D;
double d1 = (lastEntity.posX - entity.posX) / d0;
double d3 = (lastEntity.posZ - entity.posZ) / d0;
double d4 = Math.sqrt(d1 * d1 + d3 * d3);
double d5 = 1.0D - d4;
if(d5 > 0.0D && d4 > 0.02D) {
d5 *= d5;
entity.motionX += d1 / d4 * d5 * 0.01D;
entity.motionZ += d3 / d4 * d5 * 0.01D;
lastEntity.motionX -= d1 / d4 * d5 * 0.01D;
lastEntity.motionZ -= d3 / d4 * d5 * 0.01D;
areEntitiesDoneMoving = false;
}
}
boolean lifeUpgrade = getUpgrades(ItemMachineUpgrade.UPGRADE_ITEM_LIFE, getUpgradeSlots()) > 0;
if(lifeUpgrade && !worldObj.isRemote) {
for(EntityItem entity : entities) {
entity.age--;
}
}
// particles
if(worldObj.isRemote && getPressure(ForgeDirection.UNKNOWN) > 0.2D) {
int particles = (int)Math.pow(multiBlockSize - 2, 3);
for(int i = 0; i < particles; i++) {
if(rand.nextInt(Math.max(1, 8 - (int)(getPressure(ForgeDirection.UNKNOWN) * 2D))) == 0) {
double posX = multiBlockX + 1D + rand.nextDouble() * (multiBlockSize - 2D);
double posY = multiBlockY + 1D + rand.nextDouble() * (multiBlockSize - 2D);
double posZ = multiBlockZ + 1D + rand.nextDouble() * (multiBlockSize - 2D);
worldObj.spawnParticle("explode", posX, posY, posZ, 0D, 0D, 0D);
}
}
}
}
private boolean canBeCompressed(PressureChamberRecipe recipe, ItemStack[] items){
for(ItemStack in : recipe.input) {
if(in != null) {
int amount = 0;
for(ItemStack item : items) {
if(item != null && (in.isItemEqual(item) || PneumaticCraftUtils.isSameOreDictStack(in, item))) amount += item.stackSize;
}
if(amount < in.stackSize) return false;
}
}
return true;
}
public ItemStack[] getStacksInChamber(){
List<ItemStack> stackList = new ArrayList<ItemStack>(); // first make a
// list, convert
// it to an
// array
// afterwards.
/*for(int i = 0; i < multiBlockSize - 2; i++) {
for(int j = 0; j < multiBlockSize - 2; j++) {
for(int k = 0; k < multiBlockSize - 2; k++) {
Block blockID = worldObj.getBlock(i + multiBlockX + 1, j + multiBlockY + 1, k + multiBlockZ + 1);
if(!blockID.isAir(worldObj, i + multiBlockX + 1, j + multiBlockY + 1, k + multiBlockZ + 1)) {
ItemStack stack = new ItemStack(blockID, 1, worldObj.getBlockMetadata(i + multiBlockX + 1, j + multiBlockY + 1, k + multiBlockZ + 1));
if(stack.getItem() != null) addStackToList(stackList, stack);//getItem() shouldn't ever be able to be null, but still some defence cuz https://github.com/MineMaarten/PneumaticCraft-API/issues/60
}
}
}
}*/
// add Item entities lying on the ground.
AxisAlignedBB bbBox = AxisAlignedBB.getBoundingBox(multiBlockX, multiBlockY, multiBlockZ, multiBlockX + multiBlockSize, multiBlockY + multiBlockSize, multiBlockZ + multiBlockSize);
List<EntityItem> entities = worldObj.getEntitiesWithinAABB(EntityItem.class, bbBox);
for(EntityItem entity : entities) {
if(entity.isDead) continue;
stackList.add(entity.getEntityItem());
}
return stackList.toArray(new ItemStack[stackList.size()]); // return an
// into an
// array
// converted
// list
}
public double[] clearStacksInChamber(ItemStack... stacksToClear){
int[] stackSizes = new int[stacksToClear.length];
for(int i = 0; i < stacksToClear.length; i++) {
stackSizes[i] = stacksToClear[i].stackSize;
}
// default the output position to the middle of the chamber.
double[] outputPosition = new double[]{multiBlockX + multiBlockSize / 2D, multiBlockY + 1.2D, multiBlockZ + multiBlockSize / 2D};
// get the in world blocks
/* for(int i = 0; i < multiBlockSize - 2; i++) {
for(int j = multiBlockSize - 3; j >= 0; j--) {
for(int k = 0; k < multiBlockSize - 2; k++) {
Block blockID = worldObj.getBlock(i + multiBlockX + 1, j + multiBlockY + 1, k + multiBlockZ + 1);
if(!blockID.isAir(worldObj, i + multiBlockX + 1, j + multiBlockY + 1, k + multiBlockZ + 1)) {
for(int l = 0; l < stacksToClear.length; l++) {
if(Block.getBlockFromItem(stacksToClear[l].getItem()) == blockID && stackSizes[l] > 0) {
worldObj.func_147480_a(i + multiBlockX + 1, j + multiBlockY + 1, k + multiBlockZ + 1, false);
stackSizes[l]--;
outputPosition[0] = i + multiBlockX + 1.5D;
outputPosition[1] = j + multiBlockY + 1.5D;
outputPosition[2] = k + multiBlockZ + 1.5D;
break;
}
}
}
}
}
}*/
// get the in world EntityItems
AxisAlignedBB bbBox = AxisAlignedBB.getBoundingBox(multiBlockX, multiBlockY, multiBlockZ, multiBlockX + multiBlockSize, multiBlockY + multiBlockSize, multiBlockZ + multiBlockSize);
List<EntityItem> entities = worldObj.getEntitiesWithinAABB(EntityItem.class, bbBox);
for(EntityItem entity : entities) {
if(entity.isDead) continue;
ItemStack entityStack = entity.getEntityItem();
for(int l = 0; l < stacksToClear.length; l++) {
if(stacksToClear[l].isItemEqual(entityStack) && stackSizes[l] > 0) {
outputPosition[0] = entity.posX;
outputPosition[1] = entity.posY;
outputPosition[2] = entity.posZ;
int removedItems = Math.min(stackSizes[l], entityStack.stackSize);
stackSizes[l] -= removedItems;
entityStack.stackSize -= removedItems;
if(entityStack.stackSize <= 0) entity.setDead();
break;
}
}
}
return outputPosition;
}
private void giveOutput(ItemStack[] output, boolean outputAsBlock, double[] outputPosition){
for(ItemStack iStack : output) {
if(outputAsBlock)// when the output is a block.
{
int stackSize = iStack.stackSize;
for(int i = 0; i < multiBlockSize - 2; i++) {
for(int j = 0; j < multiBlockSize - 2; j++) {
for(int k = 0; k < multiBlockSize - 2; k++) {
if(stackSize <= 0) continue;
if(worldObj.isAirBlock(j + multiBlockX + 1, i + multiBlockY + 1, k + multiBlockZ + 1)) {
worldObj.setBlock(j + multiBlockX + 1, i + multiBlockY + 1, k + multiBlockZ + 1, Block.getBlockFromItem(iStack.getItem()), iStack.getItemDamage(), 3);
stackSize--;
}
}
}
}
} else {
EntityItem item = new EntityItem(worldObj, outputPosition[0], outputPosition[1], outputPosition[2], iStack.copy());
worldObj.spawnEntityInWorld(item);
}
}
}
private void addStackToList(List<ItemStack> list, ItemStack stack){
for(ItemStack listStack : list) {
if(canCombineStacks(listStack, stack)) {
listStack.stackSize += stack.stackSize;
return;
}
}
list.add(stack);
}
private boolean canCombineStacks(ItemStack iStack1, ItemStack iStack2){
if(iStack1.getItem() != iStack2.getItem()) {
return false;
} else if(iStack1.hasTagCompound() ^ iStack2.hasTagCompound()) {
return false;
} else if(iStack1.hasTagCompound() && !iStack1.getTagCompound().equals(iStack2.getTagCompound())) {
return false;
} else if(iStack1.getItem().getHasSubtypes() && iStack1.getItemDamage() != iStack2.getItemDamage()) {
return false;
} else if(iStack1.stackSize + iStack2.stackSize > iStack1.getMaxStackSize()) {
return false;
} else {
return true;
}
}
// NBT methods-----------------------------------------------
@Override
public void readFromNBT(NBTTagCompound tag){
super.readFromNBT(tag);
multiBlockX = tag.getInteger("multiBlockX");
multiBlockY = tag.getInteger("multiBlockY");
multiBlockZ = tag.getInteger("multiBlockZ");
multiBlockSize = tag.getInteger("multiBlockSize");
isSufficientPressureInChamber = tag.getBoolean("sufPressure");
isValidRecipeInChamber = tag.getBoolean("validRecipe");
recipePressure = tag.getFloat("recipePressure");
// 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);
}
}
// Read in the accessory valves from NBT
NBTTagList tagList2 = tag.getTagList("Valves", 10);
nbtValveList.clear();
for(int i = 0; i < tagList2.tagCount(); ++i) {
NBTTagCompound tagCompound = tagList2.getCompoundTagAt(i);
if(tagCompound != null) {
nbtValveList.add(new int[]{tagCompound.getInteger("xCoord"), tagCompound.getInteger("yCoord"), tagCompound.getInteger("zCoord")});
}
}
readNBT = true;
}
@Override
public void writeToNBT(NBTTagCompound tag){
super.writeToNBT(tag);
tag.setInteger("multiBlockX", multiBlockX);
tag.setInteger("multiBlockY", multiBlockY);
tag.setInteger("multiBlockZ", multiBlockZ);
tag.setInteger("multiBlockSize", multiBlockSize);
tag.setBoolean("sufPressure", isSufficientPressureInChamber);
tag.setBoolean("validRecipe", isValidRecipeInChamber);
tag.setFloat("recipePressure", recipePressure);
// 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);
// Write the accessory valve to NBT
NBTTagList tagList2 = new NBTTagList();
for(TileEntityPressureChamberValve valve : accessoryValves) {
NBTTagCompound tagCompound = new NBTTagCompound();
tagCompound.setInteger("xCoord", valve.xCoord);
tagCompound.setInteger("yCoord", valve.yCoord);
tagCompound.setInteger("zCoord", valve.zCoord);
tagList2.appendTag(tagCompound);
}
tag.setTag("Valves", tagList2);
}
// Multi-block structure methods
// --------------------------------------------------------
public void onMultiBlockBreak(){
dropInventory(worldObj, multiBlockX + multiBlockSize / 2D, multiBlockY + multiBlockSize / 2D, multiBlockZ + multiBlockSize / 2D);
invalidateMultiBlock();
}
private void dropInventory(World world, double x, double y, double z){
IInventory inventory = this;
Random rand = new Random();
for(int i = 0; i < inventory.getSizeInventory(); i++) {
ItemStack itemStack = inventory.getStackInSlot(i);
if(itemStack != null && itemStack.stackSize > 0) {
float dX = rand.nextFloat() * 0.8F - 0.4F;
float dY = rand.nextFloat() * 0.8F - 0.4F;
float dZ = rand.nextFloat() * 0.8F - 0.4F;
EntityItem entityItem = new EntityItem(world, x + dX, y + dY, z + dZ, new ItemStack(itemStack.getItem(), itemStack.stackSize, itemStack.getItemDamage()));
if(itemStack.hasTagCompound()) {
entityItem.getEntityItem().setTagCompound((NBTTagCompound)itemStack.getTagCompound().copy());
}
float factor = 0.05F;
entityItem.motionX = rand.nextGaussian() * factor;
entityItem.motionY = rand.nextGaussian() * factor + 0.2F;
entityItem.motionZ = rand.nextGaussian() * factor;
world.spawnEntityInWorld(entityItem);
// itemStack.stackSize = 0;
}
}
this.inventory = new ItemStack[4];
}
private void invalidateMultiBlock(){
for(int x = 0; x < multiBlockSize; x++) {
for(int y = 0; y < multiBlockSize; y++) {
for(int z = 0; z < multiBlockSize; z++) {
TileEntity te = worldObj.getTileEntity(x + multiBlockX, y + multiBlockY, z + multiBlockZ);
if(te instanceof TileEntityPressureChamberWall) {
TileEntityPressureChamberWall teWall = (TileEntityPressureChamberWall)te;
teWall.setCore(null); // Clear the base TE's, so that
// the walls can be used in a new
// MultiBlock
}
}
}
}
if(accessoryValves != null) {
for(TileEntityPressureChamberValve valve : accessoryValves) {
valve.setMultiBlockCoords(0, 0, 0, 0);
if(valve != this) {
valve.accessoryValves.clear();
valve.sendDescriptionPacket();
}
}
accessoryValves.clear();
}
sendDescriptionPacket();
}
public void setMultiBlockCoords(int size, int baseX, int baseY, int baseZ){
multiBlockSize = size;
multiBlockX = baseX;
multiBlockY = baseY;
multiBlockZ = baseZ;
}
public static boolean checkIfProperlyFormed(World world, int x, int y, int z){
// ArrayList<int[]> blockList = getAccessoryTiles(new
// ArrayList<int[]>(), world, x,y,z);
for(int i = 3; i < 6; i++) {
if(checkForShiftedCubeOfSize(i, world, x, y, z)) {
return true;
}
}
return false;
}
private static boolean checkForShiftedCubeOfSize(int size, World world, int baseX, int baseY, int baseZ){
for(int wallX = 0; wallX < size; wallX++) {
for(int wallY = 0; wallY < size; wallY++) {
// check every possible configuration the block can be in.
if(checkForCubeOfSize(size, world, baseX, baseY - wallY, baseZ - wallX)) return true;
if(checkForCubeOfSize(size, world, baseX, baseY + wallY, baseZ + wallX)) return true;
if(checkForCubeOfSize(size, world, baseX - wallX, baseY - wallY, baseZ)) return true;
if(checkForCubeOfSize(size, world, baseX + wallX, baseY + wallY, baseZ)) return true;
if(checkForCubeOfSize(size, world, baseX - wallX, baseY, baseZ - wallY)) return true;
if(checkForCubeOfSize(size, world, baseX + wallX, baseY, baseZ + wallY)) return true;
if(checkForCubeOfSize(size, world, baseX - size + 1, baseY - wallY, baseZ - wallX)) return true;
if(checkForCubeOfSize(size, world, baseX - size + 1, baseY + wallY, baseZ + wallX)) return true;
if(checkForCubeOfSize(size, world, baseX - wallX, baseY - wallY, baseZ - size + 1)) return true;
if(checkForCubeOfSize(size, world, baseX + wallX, baseY + wallY, baseZ - size + 1)) return true;
if(checkForCubeOfSize(size, world, baseX - wallX, baseY - size + 1, baseZ - wallY)) return true;
if(checkForCubeOfSize(size, world, baseX + wallX, baseY - size + 1, baseZ + wallY)) return true;
}
}
return false;
}
private static boolean checkForCubeOfSize(int size, World world, int baseX, int baseY, int baseZ){
boolean validValveFound = false;
for(int x = 0; x < size; x++) {
for(int y = 0; y < size; y++) {
for(int z = 0; z < size; z++) {
if(x != 0 && x != size - 1 && y != 0 && y != size - 1 && z != 0 && z != size - 1) continue;
if(world.getBlock(x + baseX, y + baseY, z + baseZ) != Blockss.pressureChamberWall && world.getBlock(x + baseX, y + baseY, z + baseZ) != Blockss.pressureChamberValve && world.getBlock(x + baseX, y + baseY, z + baseZ) != Blockss.pressureChamberInterface) {
return false;
} else if(world.getBlock(x + baseX, y + baseY, z + baseZ) == Blockss.pressureChamberValve) {
boolean xMid = x != 0 && x != size - 1;
boolean yMid = y != 0 && y != size - 1;
boolean zMid = z != 0 && z != size - 1;
ForgeDirection facing = ForgeDirection.getOrientation(world.getBlockMetadata(x + baseX, y + baseY, z + baseZ));
if(xMid && yMid && (facing == ForgeDirection.NORTH || facing == ForgeDirection.SOUTH) || xMid && zMid && (facing == ForgeDirection.UP || facing == ForgeDirection.DOWN) || yMid && zMid && (facing == ForgeDirection.EAST || facing == ForgeDirection.WEST)) {
validValveFound = true;
} else {
return false;
}
} else {// when blockID == wall/interface
TileEntity te = world.getTileEntity(x + baseX, y + baseY, z + baseZ);
if(te instanceof TileEntityPressureChamberWall && ((TileEntityPressureChamberWall)te).getCore() != null) {
return false;
}
}
}
}
}
// when the code makes it to here we've found a valid structure. it only
// depends on whether there is a valid valve in the structure now.
if(!validValveFound) return false;
TileEntityPressureChamberValve teValve = null;
List<TileEntityPressureChamberValve> valveList = new ArrayList<TileEntityPressureChamberValve>();
for(int x = 0; x < size; x++) {
for(int y = 0; y < size; y++) {
for(int z = 0; z < size; z++) {
TileEntity te = world.getTileEntity(x + baseX, y + baseY, z + baseZ);
if(te instanceof TileEntityPressureChamberValve) {
boolean xMid = x != 0 && x != size - 1;
boolean yMid = y != 0 && y != size - 1;
boolean zMid = z != 0 && z != size - 1;
ForgeDirection facing = ForgeDirection.getOrientation(world.getBlockMetadata(x + baseX, y + baseY, z + baseZ));
if(xMid && yMid && (facing == ForgeDirection.NORTH || facing == ForgeDirection.SOUTH) || xMid && zMid && (facing == ForgeDirection.UP || facing == ForgeDirection.DOWN) || yMid && zMid && (facing == ForgeDirection.EAST || facing == ForgeDirection.WEST)) {
teValve = (TileEntityPressureChamberValve)te;
valveList.add(teValve);
}
}
}
}
}
if(teValve == null) return false;// this line shouldn't be triggered
// ever.
// put the list of all the valves in the structure in all the valve
// TE's.
for(TileEntityPressureChamberValve valve : valveList) {
valve.accessoryValves = new ArrayList<TileEntityPressureChamberValve>(valveList);
valve.sendDescriptionPacket();
}
// set the redirections of right clicking and breaking a wall block to
// the valve.
for(int x = 0; x < size; x++) {
for(int y = 0; y < size; y++) {
for(int z = 0; z < size; z++) {
TileEntity te = world.getTileEntity(x + baseX, y + baseY, z + baseZ);
if(te instanceof TileEntityPressureChamberWall) {
TileEntityPressureChamberWall teWall = (TileEntityPressureChamberWall)te;
teWall.setCore(teValve); // set base TE to the valve
// found.
}
}
}
}
// set the multi-block coords in the valve TE
teValve.setMultiBlockCoords(size, baseX, baseY, baseZ);
teValve.sendDescriptionPacket();
return true;
}
public boolean isCoordWithinChamber(World world, int x, int y, int z){
if(x > multiBlockX && x < multiBlockX + multiBlockSize - 1 && y > multiBlockY && y < multiBlockY + multiBlockSize - 1 && z > multiBlockZ && z < multiBlockZ + multiBlockSize - 1) {
return true;
}
return false;
}
// INVENTORY METHODS- && NBT
// ------------------------------------------------------------
/**
* 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.pressureChamberValve.getUnlocalizedName();
}
@Override
public boolean isItemValidForSlot(int i, ItemStack itemstack){
return itemstack.getItem() == Itemss.machineUpgrade;
}
@Override
public boolean hasCustomInventoryName(){
return false;
}
@Override
public boolean isUseableByPlayer(EntityPlayer var1){
return isGuiUseableByPlayer(var1);
}
@Override
public void openInventory(){}
@Override
public void closeInventory(){}
@Override
public float getMinWorkingPressure(){
return recipePressure;
}
}