package zmaster587.advancedRocketry.tile.oxygen; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; import net.minecraft.network.play.server.S35PacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; import zmaster587.advancedRocketry.api.AdvancedRocketryFluids; import zmaster587.advancedRocketry.api.Configuration; import zmaster587.advancedRocketry.api.util.IBlobHandler; import zmaster587.advancedRocketry.atmosphere.AtmosphereHandler; import zmaster587.advancedRocketry.atmosphere.AtmosphereType; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.inventory.TextureResources; import zmaster587.advancedRocketry.api.AreaBlob; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.api.IToggleableMachine; import zmaster587.libVulpes.client.RepeatingSound; import zmaster587.libVulpes.inventory.modules.IButtonInventory; import zmaster587.libVulpes.inventory.modules.IModularInventory; import zmaster587.libVulpes.inventory.modules.ModuleBase; import zmaster587.libVulpes.inventory.modules.ModuleLiquidIndicator; import zmaster587.libVulpes.inventory.modules.ModulePower; import zmaster587.libVulpes.inventory.modules.ModuleRedstoneOutputButton; import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.network.PacketMachine; import zmaster587.libVulpes.tile.TileInventoriedRFConsumerTank; import zmaster587.libVulpes.util.BlockPosition; import zmaster587.libVulpes.util.IAdjBlockUpdate; import zmaster587.libVulpes.util.INetworkMachine; import zmaster587.libVulpes.util.ZUtils.RedstoneState; import io.netty.buffer.ByteBuf; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import cpw.mods.fml.relauncher.Side; public class TileOxygenVent extends TileInventoriedRFConsumerTank implements INetworkMachine, IBlobHandler, IModularInventory, IAdjBlockUpdate, IToggleableMachine, IButtonInventory { boolean isSealed; boolean firstRun; boolean hasFluid; boolean soundInit; int numScrubbers; List<TileCO2Scrubber> scrubbers; RedstoneState state; ModuleRedstoneOutputButton redstoneControl; public TileOxygenVent() { super(1000,2, 1000); isSealed = true; firstRun = true; hasFluid = true; soundInit = false; numScrubbers = 0; scrubbers = new LinkedList<TileCO2Scrubber>(); state = RedstoneState.ON; redstoneControl = new ModuleRedstoneOutputButton(174, 4, 0, "", this); } public TileOxygenVent(int energy, int invSize, int tankSize) { super(energy, invSize, tankSize); isSealed = false; firstRun = false; hasFluid = true; soundInit = false; scrubbers = new LinkedList<TileCO2Scrubber>(); state = RedstoneState.ON; redstoneControl = new ModuleRedstoneOutputButton(174, 4, 0, "", this); } @Override public boolean canPerformFunction() { return AtmosphereHandler.hasAtmosphereHandler(this.worldObj.provider.dimensionId); } @Override public void updateEntity() { if(canPerformFunction()) { if(hasEnoughEnergy(getPowerPerOperation())) { performFunction(); if(!worldObj.isRemote && isSealed) this.energy.extractEnergy(getPowerPerOperation(), false); } else notEnoughEnergyForFunction(); } if(!soundInit && worldObj.isRemote) { LibVulpes.proxy.playSound(new RepeatingSound(TextureResources.sndHiss, this)); } soundInit = true; } @Override public Packet getDescriptionPacket() { NBTTagCompound nbt = new NBTTagCompound(); nbt.setBoolean("sealed", isSealed); return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 0, nbt); } @Override public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { isSealed = pkt.func_148857_g().getBoolean("sealed"); } @Override public World getWorld() { return getWorldObj(); } @Override public void onAdjacentBlockUpdated() { if(isSealed) activateAdjblocks(); scrubbers.clear(); TileEntity[] tiles = new TileEntity[4]; tiles[0] = worldObj.getTileEntity(this.xCoord + 1, this.yCoord, this.zCoord); tiles[1] = worldObj.getTileEntity(this.xCoord - 1, this.yCoord, this.zCoord); tiles[2] = worldObj.getTileEntity(this.xCoord, this.yCoord, this.zCoord + 1); tiles[3] = worldObj.getTileEntity(this.xCoord, this.yCoord, this.zCoord - 1); for(TileEntity tile : tiles) { if(tile instanceof TileCO2Scrubber && worldObj.getBlock(tile.xCoord, tile.yCoord, tile.zCoord) == AdvancedRocketryBlocks.blockOxygenScrubber) scrubbers.add((TileCO2Scrubber)tile); } } private void activateAdjblocks() { numScrubbers = 0; numScrubbers = toggleAdjBlock(this.xCoord + 1, this.yCoord, this.zCoord, true) ? numScrubbers + 1 : numScrubbers; numScrubbers = toggleAdjBlock(this.xCoord - 1, this.yCoord, this.zCoord, true) ? numScrubbers + 1 : numScrubbers; numScrubbers = toggleAdjBlock(this.xCoord, this.yCoord, this.zCoord + 1, true) ? numScrubbers + 1 : numScrubbers; numScrubbers = toggleAdjBlock(this.xCoord, this.yCoord, this.zCoord - 1, true) ? numScrubbers + 1 : numScrubbers; markDirty(); worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); } private void deactivateAdjblocks() { toggleAdjBlock(this.xCoord + 1, this.yCoord, this.zCoord, false); toggleAdjBlock(this.xCoord - 1, this.yCoord, this.zCoord, false); toggleAdjBlock(this.xCoord, this.yCoord, this.zCoord + 1, false); toggleAdjBlock(this.xCoord, this.yCoord, this.zCoord - 1, false); markDirty(); worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); } private boolean toggleAdjBlock(int x, int y, int z, boolean on) { Block block = this.worldObj.getBlock(x,y,z); if(block == AdvancedRocketryBlocks.blockOxygenScrubber) { int meta = worldObj.getBlockMetadata(x,y,z); if(on && (meta & 8) == 0) worldObj.setBlockMetadataWithNotify(x, y, z, 8, 2); else if(!on && (meta & 8) == 8) worldObj.setBlockMetadataWithNotify(x, y, z, 0, 2); return true; } return false; } @Override public void invalidate() { super.invalidate(); AtmosphereHandler handler = AtmosphereHandler.getOxygenHandler(this.worldObj.provider.dimensionId); if(handler != null) AtmosphereHandler.getOxygenHandler(this.worldObj.provider.dimensionId).unregisterBlob(this); deactivateAdjblocks(); } @Override public int getPowerPerOperation() { return isSealed ? numScrubbers*10 + 1 : 0; } @Override public boolean canFill(ForgeDirection from, Fluid fluid) { return fluid == AdvancedRocketryFluids.fluidOxygen && super.canFill(from, fluid); } public boolean getEquivilentPower() { if(state == RedstoneState.OFF) return true; boolean state2 = worldObj.isBlockIndirectlyGettingPowered(xCoord, yCoord, zCoord); if(state == RedstoneState.INVERTED) state2 = !state2; return state2; } @Override public void performFunction() { /*NB: canPerformFunction returns false and must return true for perform function to execute * if there is no O2 handler, this is why we can safely call AtmosphereHandler.getOxygenHandler * And not have to worry about an NPE being thrown */ //IF first tick then register the blob and check for scrubbers if(firstRun) { if(!worldObj.isRemote) { AtmosphereHandler.getOxygenHandler(this.worldObj.provider.dimensionId).registerBlob(this, xCoord, yCoord, zCoord); onAdjacentBlockUpdated(); //isSealed starts as true so we can accurately check for scrubbers, we now set it to false to force the tile to check for a seal on first run isSealed = false; } firstRun = false; } if(!worldObj.isRemote) { if(isSealed && !getEquivilentPower() ) { AtmosphereHandler.getOxygenHandler(this.worldObj.provider.dimensionId).clearBlob(this); deactivateAdjblocks(); isSealed = false; } else if(!isSealed && getEquivilentPower() ) { AtmosphereHandler.getOxygenHandler(this.worldObj.provider.dimensionId).addBlock(this, new BlockPosition(this.xCoord, this.yCoord, this.zCoord)); isSealed = true; activateAdjblocks(); } if(isSealed) { //if(worldObj.getTotalWorldTime() % 30 == 0) //worldObj.playSoundEffect(xCoord, yCoord, zCoord, "advancedrocketry:airHissLoop", 0.3f, 0.975f + worldObj.rand.nextFloat()*0.05f); //If scrubbers exist and the config allows then use the cartridge if(Configuration.scrubberRequiresCartrige){ //TODO: could be optimized if(worldObj.getTotalWorldTime() % 20 == 0) { numScrubbers = 0; for(TileCO2Scrubber scrubber : scrubbers) { numScrubbers = scrubber.useCharge() ? numScrubbers + 1 : numScrubbers; } } } int amtToDrain = (int) (AtmosphereHandler.getOxygenHandler(this.worldObj.provider.dimensionId).getBlobSize(this)*getGasUsageMultiplier()); FluidStack drainedFluid = this.drain(ForgeDirection.UNKNOWN, amtToDrain, false); if( (drainedFluid != null && drainedFluid.amount >= amtToDrain) || amtToDrain == 0) { this.drain(ForgeDirection.UNKNOWN, amtToDrain, true); if(!hasFluid) { hasFluid = true; activateAdjblocks(); AtmosphereHandler.getOxygenHandler(this.worldObj.provider.dimensionId).setAtmosphereType(this, AtmosphereType.PRESSURIZEDAIR); } } else if(hasFluid){ AtmosphereHandler.getOxygenHandler(this.worldObj.provider.dimensionId).setAtmosphereType(this, DimensionManager.getInstance().getDimensionProperties(this.worldObj.provider.dimensionId).getAtmosphere()); deactivateAdjblocks(); hasFluid = false; } } } } public float getGasUsageMultiplier() { return Math.max(0.05f - numScrubbers*0.025f,0); } @Override public void notEnoughEnergyForFunction() { if(!worldObj.isRemote) { AtmosphereHandler handler = AtmosphereHandler.getOxygenHandler(this.worldObj.provider.dimensionId); if(handler != null) handler.clearBlob(this); deactivateAdjblocks(); isSealed = false; } } @Override public int[] getAccessibleSlotsFromSide(int p_94128_1_) { return new int[]{}; } @Override public boolean isItemValidForSlot(int slot, ItemStack itemStack) { return false; } @Override public boolean canBlobsOverlap(BlockPosition blockPosition, AreaBlob blob) { return false; } @Override public int getMaxBlobRadius() { return Configuration.oxygenVentSize; } @Override public BlockPosition getRootPosition() { return new BlockPosition(this.xCoord, this.yCoord, this.zCoord); } @Override public List<ModuleBase> getModules(int ID, EntityPlayer player) { ArrayList<ModuleBase> modules = new ArrayList<ModuleBase>(); modules.add(new ModulePower(18, 20, this)); modules.add(new ModuleLiquidIndicator(32, 20, this)); //modules.add(toggleSwitch = new ModuleToggleSwitch(160, 5, 0, "", this, TextureResources.buttonToggleImage, 11, 26, getMachineEnabled())); //TODO add itemStack slots for liqiuid return modules; } @Override public String getModularInventoryName() { return "OxygenVent"; } @Override public boolean canInteractWithContainer(EntityPlayer entity) { return true; } @Override public boolean canFormBlob() { return getEquivilentPower() ; } @Override public boolean isRunning() { return isSealed; } @Override public void onInventoryButtonPressed(int buttonId) { state = redstoneControl.getState(); PacketHandler.sendToServer(new PacketMachine(this, (byte)2)); } @Override public void writeDataToNetwork(ByteBuf out, byte id) { out.writeByte(state.ordinal()); } @Override public void readDataFromNetwork(ByteBuf in, byte packetId, NBTTagCompound nbt) { nbt.setByte("state", in.readByte()); } @Override public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { state = RedstoneState.values()[nbt.getByte("state")]; } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); state = RedstoneState.values()[nbt.getByte("redstoneState")]; redstoneControl.setRedstoneState(state); } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); nbt.setByte("redstoneState", (byte) state.ordinal()); } }