package zmaster587.advancedRocketry.tile; import net.minecraft.block.Block; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.FluidTankInfo; import net.minecraftforge.fluids.IFluidHandler; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; import zmaster587.advancedRocketry.api.IFuelTank; import zmaster587.advancedRocketry.api.IInfrastructure; import zmaster587.advancedRocketry.api.IIntake; import zmaster587.advancedRocketry.api.IMiningDrill; import zmaster587.advancedRocketry.api.IRocketEngine; import zmaster587.advancedRocketry.api.fuel.FuelRegistry.FuelType; import zmaster587.advancedRocketry.block.BlockRocketMotor; import zmaster587.advancedRocketry.block.BlockSeat; import zmaster587.advancedRocketry.entity.EntityRocket; import zmaster587.advancedRocketry.entity.EntityStationDeployedRocket; import zmaster587.advancedRocketry.tile.TileRocketBuilder.ErrorCodes; import zmaster587.advancedRocketry.tile.hatch.TileSatelliteHatch; import zmaster587.advancedRocketry.util.StorageChunk; import zmaster587.libVulpes.block.RotatableBlock; import zmaster587.libVulpes.interfaces.INetworkEntity; import zmaster587.libVulpes.network.PacketEntity; import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.util.ZUtils; public class TileStationDeployedAssembler extends TileRocketBuilder { private final static int MAX_SIZE = 17, MAX_SIZE_Y = 17, MIN_SIZE = 3, MIN_SIZE_Y = 3; /** * Does not make sure the structure is complete, only gets max bounds! * @param world the world * @param x coord to evaluate from * @param y coord to evaluate from * @param z coord to evaluate from * @return AxisAlignedBB bounds of structure if valid otherwise null */ public AxisAlignedBB getRocketPadBounds(World world,int x, int y, int z) { ForgeDirection direction = RotatableBlock.getFront(world.getBlockMetadata(x, y, z)).getOpposite(); int xMin, zMin, xMax, zMax, yMax, yMin; int yCurrent = y; int xCurrent = x; int zCurrent = z; xMax = xMin = xCurrent; zMax = zMin = zCurrent; int xSize, zSize; yMax = ZUtils.getContinuousBlockLength(world, ForgeDirection.UP, this.xCoord, this.yCoord + 1, this.zCoord, MAX_SIZE_Y, AdvancedRocketryBlocks.blockStructureTower); //Get min and maximum Z/X bounds if(direction.offsetX != 0) { xSize = ZUtils.getContinuousBlockLength(world, direction, xCurrent, yCurrent + yMax, zCurrent, MAX_SIZE, AdvancedRocketryBlocks.blockStructureTower); zMin = ZUtils.getContinuousBlockLength(world, ForgeDirection.NORTH, xCurrent, yCurrent, zCurrent-1, MAX_SIZE, AdvancedRocketryBlocks.blockStructureTower) + 1; zMax = ZUtils.getContinuousBlockLength(world, ForgeDirection.SOUTH, xCurrent, yCurrent, zCurrent+1, MAX_SIZE - zMin, AdvancedRocketryBlocks.blockStructureTower); zSize = zMin + zMax; zMin = zCurrent - zMin +1; zMax = zCurrent + zMax; if(direction.offsetX > 0) { xMax = xCurrent + xSize - 1; xMin++; } if(direction.offsetX < 0) { xMin = xCurrent - xSize+1; xMax--; } } else { zSize = ZUtils.getContinuousBlockLength(world, direction, xCurrent, yCurrent + yMax, zCurrent, MAX_SIZE, AdvancedRocketryBlocks.blockStructureTower); xMin = ZUtils.getContinuousBlockLength(world, ForgeDirection.WEST, xCurrent - 1, yCurrent, zCurrent, MAX_SIZE, AdvancedRocketryBlocks.blockStructureTower) + 1; xMax = ZUtils.getContinuousBlockLength(world, ForgeDirection.EAST, xCurrent + 1, yCurrent, zCurrent, MAX_SIZE - xMin, AdvancedRocketryBlocks.blockStructureTower); xSize = xMin + xMax; xMin = xCurrent - xMin +1; xMax = xCurrent + xMax; if(direction.offsetZ > 0) { zMax = zCurrent + zSize - 1; zMin++; } if(direction.offsetZ < 0) { zMin = zCurrent - zSize+1; zMax --; } } //if tower does not meet criteria then reutrn null if(yMax < MIN_SIZE_Y || xSize < MIN_SIZE || zSize < MIN_SIZE) { return null; } return AxisAlignedBB.getBoundingBox(xMin, yCurrent, zMin, xMax, yCurrent + yMax - 1, zMax); } public void assembleRocket() { if(bbCache == null || worldObj.isRemote) return; //Need to scan again b/c something may have changed scanRocket(worldObj, xCoord, yCoord, zCoord, bbCache); if(status != ErrorCodes.SUCCESS) return; StorageChunk storageChunk; //Breaks if nothing is there try { storageChunk = StorageChunk.cutWorldBB(worldObj, bbCache); } catch(NegativeArraySizeException e) { return; } EntityStationDeployedRocket rocket = new EntityStationDeployedRocket(worldObj, storageChunk, stats.copy(),bbCache.minX + (bbCache.maxX-bbCache.minX)/2f +.5f, yCoord , bbCache.minZ + (bbCache.maxZ-bbCache.minZ)/2f +.5f); //TODO: setRocketDirection rocket.forwardDirection = RotatableBlock.getFront(this.blockMetadata).getOpposite(); rocket.launchDirection = ForgeDirection.DOWN; //Change engine direction for(int x = 0; x < storageChunk.getSizeX(); x++) { for(int y = 0; y < storageChunk.getSizeY(); y++) { for(int z = 0; z < storageChunk.getSizeZ(); z++) { if(storageChunk.getBlock(x, y, z) instanceof BlockRocketMotor) { storageChunk.setBlockMeta(x, y, z, rocket.forwardDirection.ordinal()); storageChunk.getTileEntity(x, y, z).blockMetadata = rocket.forwardDirection.ordinal(); ((TileModelRenderRotatable)storageChunk.getTileEntity(x, y, z)).rotation = rocket.forwardDirection; } } } } worldObj.spawnEntityInWorld(rocket); NBTTagCompound nbtdata = new NBTTagCompound(); rocket.writeToNBT(nbtdata); PacketHandler.sendToNearby(new PacketEntity((INetworkEntity)rocket, (byte)0, nbtdata), rocket.worldObj.provider.dimensionId, xCoord, yCoord, zCoord, 64); stats.reset(); this.status = ErrorCodes.UNSCANNED; this.markDirty(); this.worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); for(IInfrastructure infrastructure : getConnectedInfrastructure()) { rocket.linkInfrastructure(infrastructure); } } //TODO get direction of rocket @Override public void scanRocket(World world, int x, int y, int z, AxisAlignedBB bb) { int thrust = 0; int fuelUse = 0; int fuel = 0; int numBlocks = 0; float drillPower = 0f; stats.reset(); int actualMinX = (int)bb.maxX, actualMinY = (int)bb.maxY, actualMinZ = (int)bb.maxZ, actualMaxX = (int)bb.minX, actualMaxY = (int)bb.minY, actualMaxZ = (int)bb.minZ; for(int xCurr = (int)bb.minX; xCurr <= bb.maxX; xCurr++) { for(int zCurr = (int)bb.minZ; zCurr <= bb.maxZ; zCurr++) { for(int yCurr = (int)bb.minY; yCurr<= bb.maxY; yCurr++) { Block block = world.getBlock(xCurr, yCurr, zCurr); if(!block.isAir(world, xCurr, yCurr, zCurr)) { if(xCurr < actualMinX) actualMinX = xCurr; if(yCurr < actualMinY) actualMinY = yCurr; if(zCurr < actualMinZ) actualMinZ = zCurr; if(xCurr > actualMaxX) actualMaxX = xCurr; if(yCurr > actualMaxY) actualMaxY = yCurr; if(zCurr > actualMaxZ) actualMaxZ = zCurr; } } } } boolean hasSatellite = false; boolean hasGuidance = false; int fluidCapacity = 0; if(verifyScan(bb, world)) { for(int yCurr = (int) bb.minY; yCurr <= bb.maxY; yCurr++) { for(int xCurr = (int) bb.minX; xCurr <= bb.maxX; xCurr++) { for(int zCurr = (int) bb.minZ; zCurr <= bb.maxZ; zCurr++) { if(!world.isAirBlock(xCurr, yCurr, zCurr)) { Block block = world.getBlock(xCurr, yCurr, zCurr); int meta = world.getBlockMetadata(xCurr, yCurr, zCurr); numBlocks++; //If rocketEngine increaseThrust if(block instanceof IRocketEngine) { thrust += ((IRocketEngine)block).getThrust(world, xCurr, yCurr, z); fuelUse += ((IRocketEngine)block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); stats.addEngineLocation(xCurr - actualMinX - ((actualMaxX - actualMinX)/2f), yCurr - actualMinY, zCurr - actualMinZ - ((actualMaxZ - actualMinZ)/2f)); } if(block instanceof IFuelTank) { fuel+= ((IFuelTank)block).getMaxFill(world, xCurr, yCurr, zCurr, world.getBlockMetadata(xCurr, yCurr, zCurr)); } if(block instanceof BlockSeat) { if(stats.hasSeat()) stats.addPassengerSeat((int)(xCurr - actualMinX - ((actualMaxX - actualMinX)/2f)) , (int)(yCurr -actualMinY), (int)(zCurr - actualMinZ - ((actualMaxZ - actualMinZ)/2f))); else stats.setSeatLocation((int)(xCurr - actualMinX - ((actualMaxX - actualMinX)/2f)) , (int)(yCurr -actualMinY), (int)(zCurr - actualMinZ - ((actualMaxZ - actualMinZ)/2f))); } if(block instanceof IMiningDrill) { drillPower += ((IMiningDrill)block).getMiningSpeed(world, xCurr, yCurr, zCurr); } if(block instanceof IIntake) { stats.setStatTag("intakePower", (int)stats.getStatTag("intakePower") + ((IIntake)block).getIntakeAmt(meta)); } TileEntity tile= world.getTileEntity(xCurr, yCurr, zCurr); if(tile instanceof TileSatelliteHatch) hasSatellite = true; if(tile instanceof TileGuidanceComputer) hasGuidance = true; if(tile instanceof IFluidHandler) { for(FluidTankInfo info : ((IFluidHandler)tile).getTankInfo(ForgeDirection.UNKNOWN)) fluidCapacity += info.capacity; } } } } } stats.setFuelRate(FuelType.LIQUID,fuelUse); stats.setWeight(numBlocks); stats.setThrust(thrust); stats.setFuelCapacity(FuelType.LIQUID,fuel); stats.setDrillingPower(drillPower); stats.setStatTag("liquidCapacity", fluidCapacity); //Set status //TODO: warn if seat OR satellite missing //if(!stats.hasSeat() && !hasSatellite) //status = ErrorCodes.NOSEAT; /*else*/ if(getFuel() < getNeededFuel()*(1 + fluidCapacity/1000)) status = ErrorCodes.NOFUEL; else if(getThrust() < getNeededThrust()) status = ErrorCodes.NOENGINES; else status = ErrorCodes.SUCCESS; } } @Override public float getNeededFuel() { return getAcceleration() > 0 ? stats.getFuelRate(FuelType.LIQUID) : 0; } //No additional scanning is needed @Override protected boolean verifyScan(AxisAlignedBB bb, World world) { return true; } }