/* * Purpose: validate the rocket structure as well as give feedback to the player as to what needs to be * changed to complete the rocket structure * Also will be used to "build" the rocket components from the placed frames, control fuel flow etc */ package zmaster587.advancedRocketry.tile; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import io.netty.buffer.ByteBuf; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import cpw.mods.fml.relauncher.Side; import zmaster587.advancedRocketry.AdvancedRocketry; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; import zmaster587.advancedRocketry.api.fuel.FuelRegistry.FuelType; import zmaster587.advancedRocketry.api.Configuration; import zmaster587.advancedRocketry.api.EntityRocketBase; import zmaster587.advancedRocketry.api.IFuelTank; import zmaster587.advancedRocketry.api.IInfrastructure; import zmaster587.advancedRocketry.api.IMiningDrill; import zmaster587.advancedRocketry.api.IRocketEngine; import zmaster587.advancedRocketry.api.RocketEvent.RocketLandedEvent; import zmaster587.advancedRocketry.api.StatsRocket; import zmaster587.advancedRocketry.block.BlockSeat; import zmaster587.advancedRocketry.entity.EntityRocket; import zmaster587.advancedRocketry.inventory.TextureResources; import zmaster587.advancedRocketry.tile.hatch.TileSatelliteHatch; import zmaster587.advancedRocketry.util.StorageChunk; import zmaster587.libVulpes.block.RotatableBlock; import zmaster587.libVulpes.client.util.ProgressBarImage; import zmaster587.libVulpes.interfaces.ILinkableTile; import zmaster587.libVulpes.interfaces.INetworkEntity; import zmaster587.libVulpes.inventory.modules.IButtonInventory; import zmaster587.libVulpes.inventory.modules.IDataSync; import zmaster587.libVulpes.inventory.modules.IModularInventory; import zmaster587.libVulpes.inventory.modules.IProgressBar; import zmaster587.libVulpes.inventory.modules.ModuleBase; import zmaster587.libVulpes.inventory.modules.ModuleButton; import zmaster587.libVulpes.inventory.modules.ModuleImage; import zmaster587.libVulpes.inventory.modules.ModulePower; import zmaster587.libVulpes.inventory.modules.ModuleProgress; import zmaster587.libVulpes.inventory.modules.ModuleSync; import zmaster587.libVulpes.inventory.modules.ModuleText; import zmaster587.libVulpes.items.ItemLinker; import zmaster587.libVulpes.network.PacketEntity; import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.network.PacketMachine; import zmaster587.libVulpes.tile.IMultiblock; import zmaster587.libVulpes.tile.TileEntityRFConsumer; import zmaster587.libVulpes.tile.TilePointer; import zmaster587.libVulpes.util.BlockPosition; import zmaster587.libVulpes.util.INetworkMachine; import zmaster587.libVulpes.util.IconResource; import zmaster587.libVulpes.util.ZUtils; import net.minecraft.block.Block; 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.NBTTagIntArray; import net.minecraft.nbt.NBTTagList; 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.util.AxisAlignedBB; import net.minecraft.util.ChatComponentText; import net.minecraft.util.MathHelper; import net.minecraft.util.ResourceLocation; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.util.ForgeDirection; public class TileRocketBuilder extends TileEntityRFConsumer implements IButtonInventory, INetworkMachine, IDataSync, IModularInventory, IProgressBar, ILinkableTile { private final int MAX_SIZE = 16; private final int MIN_SIZE = 3; private final int MAX_SIZE_Y = 64; private final int MIN_SIZE_Y = 4; private final int MAXSCANDELAY = 10; private final int ENERGYFOROP = 100; //private final int ENERGY = 100; protected static final ResourceLocation backdrop = new ResourceLocation("advancedrocketry","textures/gui/rocketBuilder.png"); private static final ProgressBarImage horizontalProgressBar = new ProgressBarImage(89, 9, 81, 17, 176, 0, 80, 15, 0, 2, ForgeDirection.EAST, backdrop); protected static final ProgressBarImage verticalProgressBar = new ProgressBarImage(76, 93, 8, 52, 176, 15, 2, 38, 3, 2, ForgeDirection.UP, backdrop); private ModuleText thrustText, weightText, fuelText, accelerationText; protected ModuleText errorText; private int totalProgress; private int progress; // How long until scan is finished from 0 -> num blocks private int prevProgress; // Used for client/server sync private boolean building; //True is rocket is being built, false if only scanning or otherwise protected StatsRocket stats; protected AxisAlignedBB bbCache; protected ErrorCodes status; private List<BlockPosition> blockPos; protected static enum ErrorCodes { SUCCESS("Clear for liftoff!"), NOFUEL("Not enough fuel capacity!"), NOSEAT("Missing Seat or satellite!"), NOENGINES("You do not have enough thrust!"), NOGUIDANCE("Missing Guidance Computer"), UNSCANNED("Rocket unscanned."), SUCCESS_STATION("Ready!"), EMPTY("Nothing here"), FINISHED("Build Complete!"), INCOMPLETESTRCUTURE("Invalid Launch Pad Structure!"), NOSATELLITEHATCH("Missing Sat Bay"), NOSATELLITECHIP("Missing Chip"), OUTPUTBLOCKED("Output slot blocked"); String code; private ErrorCodes(String code) { this.code = code; } public String getErrorCode() { return code; } } public TileRocketBuilder() { super(100000); blockPos = new LinkedList<BlockPosition>(); status = ErrorCodes.UNSCANNED; stats = new StatsRocket(); building = false; prevProgress = 0; MinecraftForge.EVENT_BUS.register(this); } @Override public void invalidate() { super.invalidate(); MinecraftForge.EVENT_BUS.unregister(this); for(BlockPosition pos : blockPos) { TileEntity tile = worldObj.getTileEntity(pos.x, pos.y, pos.z); if(tile instanceof IMultiblock) ((IMultiblock)tile).setIncomplete(); } } @Override public void onChunkUnload() { super.onChunkUnload(); MinecraftForge.EVENT_BUS.unregister(this); } public ErrorCodes getStatus() { return status; } public StatsRocket getRocketStats() { return stats; } public AxisAlignedBB getBBCache() { return bbCache;} public int getTotalProgress() { return totalProgress; } public void setTotalProgress(int scanTotalBlocks) { this.totalProgress = scanTotalBlocks; } public int getProgress() { return progress; } public void setProgress(int scanTime) { this.progress = scanTime; } public double getNormallizedProgress() { return progress/(double)(totalProgress*MAXSCANDELAY); } public float getAcceleration() { return stats.getAcceleration(); } public int getWeight() { return stats.getWeight(); } public int getThrust() { return (int) (stats.getThrust()); } public float getNeededThrust() {return getWeight();} public float getNeededFuel() { return getAcceleration() > 0 ? stats.getFuelRate(FuelType.LIQUID)*MathHelper.sqrt_float((2*(Configuration.orbit-this.yCoord))/getAcceleration()) : 0; } public int getFuel() {return (int) (stats.getFuelCapacity(FuelType.LIQUID)*Configuration.fuelCapacityMultiplier);} public boolean isBuilding() { return building; } public void setBuilding(boolean building) { this.building = building; } public void setStatus(int value) { status = ErrorCodes.values()[value]; } @Override public boolean canUpdate() { return true; } @Override public boolean shouldRenderInPass(int pass) { return pass == 1; } @Override public int getPowerPerOperation() { return ENERGYFOROP; } @Override public void performFunction() { if(progress >= (totalProgress*MAXSCANDELAY)) { if(!worldObj.isRemote) { if(building) assembleRocket(); else scanRocket(worldObj, xCoord, yCoord, zCoord, bbCache); } totalProgress = -1; progress = 0; prevProgress = 0; building = false; //Done building //TODO call function instead if(thrustText != null) updateText(); } progress++; if(!this.worldObj.isRemote && this.energy.getEnergyStored() < getPowerPerOperation() && progress - prevProgress > 0) { prevProgress = progress; PacketHandler.sendToNearby(new PacketMachine(this, (byte)2), this.worldObj.provider.dimensionId, this.xCoord, this.yCoord, this.zCoord, 32); } } @Override public boolean canPerformFunction() { return isScanning(); } @Override public AxisAlignedBB getRenderBoundingBox() { if(isScanning() && bbCache != null) { return bbCache; } return super.getRenderBoundingBox(); } public boolean isScanning() { return totalProgress > 0; } 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; 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); 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); } TileEntity tile= world.getTileEntity(xCurr, yCurr, zCurr); if(tile instanceof TileSatelliteHatch) hasSatellite = true; if(tile instanceof TileGuidanceComputer) hasGuidance = true; } } } } stats.setFuelRate(FuelType.LIQUID,fuelUse); stats.setWeight(numBlocks); stats.setThrust(thrust); stats.setFuelCapacity(FuelType.LIQUID,fuel); stats.setDrillingPower(drillPower); //Set status //TODO: warn if seat OR satellite missing //if(!stats.hasSeat() && !hasSatellite) //status = ErrorCodes.NOSEAT; /*else*/ if(!hasGuidance && !hasSatellite) status = ErrorCodes.NOGUIDANCE; else if(getFuel() < getNeededFuel()) status = ErrorCodes.NOFUEL; else if(getThrust() < getNeededThrust()) status = ErrorCodes.NOENGINES; else status = ErrorCodes.SUCCESS; } } 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; } EntityRocket rocket = new EntityRocket(worldObj, storageChunk, stats.copy(),bbCache.minX + (bbCache.maxX-bbCache.minX)/2f +.5f, yCoord , bbCache.minZ + (bbCache.maxZ-bbCache.minZ)/2f +.5f); 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); } } /** * 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; int yCurrent = y -1; int xCurrent = x + direction.offsetX; int zCurrent = z + direction.offsetZ; xMax = xMin = xCurrent; zMax = zMin = zCurrent; int xSize, zSize; if(world.isRemote) return null; //Get min and maximum Z/X bounds if(direction.offsetX != 0) { xSize = ZUtils.getContinuousBlockLength(world, direction, xCurrent, yCurrent, zCurrent, MAX_SIZE, AdvancedRocketryBlocks.blockLaunchpad); zMin = ZUtils.getContinuousBlockLength(world, ForgeDirection.NORTH, xCurrent, yCurrent, zCurrent, MAX_SIZE, AdvancedRocketryBlocks.blockLaunchpad); zMax = ZUtils.getContinuousBlockLength(world, ForgeDirection.SOUTH, xCurrent, yCurrent, zCurrent+1, MAX_SIZE - zMin, AdvancedRocketryBlocks.blockLaunchpad); zSize = zMin + zMax; zMin = zCurrent - zMin + 1; zMax = zCurrent + zMax; if(direction.offsetX > 0) { xMax = xCurrent + xSize-1; } if(direction.offsetX < 0) { xMin = xCurrent - xSize+1; } } else { zSize = ZUtils.getContinuousBlockLength(world, direction, xCurrent, yCurrent, zCurrent, MAX_SIZE, AdvancedRocketryBlocks.blockLaunchpad); xMin = ZUtils.getContinuousBlockLength(world, ForgeDirection.WEST, xCurrent, yCurrent, zCurrent, MAX_SIZE, AdvancedRocketryBlocks.blockLaunchpad); xMax = ZUtils.getContinuousBlockLength(world, ForgeDirection.EAST, xCurrent+1, yCurrent, zCurrent, MAX_SIZE - xMin, AdvancedRocketryBlocks.blockLaunchpad); xSize = xMin + xMax; xMin = xCurrent - xMin + 1; xMax = xCurrent + xMax; if(direction.offsetZ > 0) { zMax = zCurrent + zSize-1; } if(direction.offsetZ < 0) { zMin = zCurrent - zSize+1; } } int maxTowerSize = 0; //Check perimeter for structureBlocks and get the size for(int i = xMin; i <= xMax; i++) { if(world.getBlock(i, yCurrent, zMin-1) == AdvancedRocketryBlocks.blockStructureTower) { maxTowerSize = Math.max(maxTowerSize, ZUtils.getContinuousBlockLength(world, ForgeDirection.UP, i, yCurrent, zMin-1, MAX_SIZE_Y, AdvancedRocketryBlocks.blockStructureTower)); } if(world.getBlock(i, yCurrent, zMax+1) == AdvancedRocketryBlocks.blockStructureTower) { maxTowerSize = Math.max(maxTowerSize, ZUtils.getContinuousBlockLength(world, ForgeDirection.UP, i, yCurrent, zMax+1, MAX_SIZE_Y, AdvancedRocketryBlocks.blockStructureTower)); } } for(int i = zMin; i <= zMax; i++) { if(world.getBlock(xMin-1, yCurrent, i) == AdvancedRocketryBlocks.blockStructureTower) { maxTowerSize = Math.max(maxTowerSize, ZUtils.getContinuousBlockLength(world, ForgeDirection.UP, xMin-1, yCurrent, i, MAX_SIZE_Y, AdvancedRocketryBlocks.blockStructureTower)); } if(world.getBlock(xMax+1, yCurrent, i) == AdvancedRocketryBlocks.blockStructureTower) { maxTowerSize = Math.max(maxTowerSize, ZUtils.getContinuousBlockLength(world, ForgeDirection.UP, xMax+1, yCurrent, i, MAX_SIZE_Y, AdvancedRocketryBlocks.blockStructureTower)); } } //if tower does not meet criteria then reutrn null if(maxTowerSize < MIN_SIZE_Y || xSize < MIN_SIZE || zSize < MIN_SIZE) { return null; } return AxisAlignedBB.getBoundingBox(xMin, yCurrent+1, zMin, xMax, yCurrent + maxTowerSize- 1, zMax); } protected boolean verifyScan(AxisAlignedBB bb, World world) { boolean whole = true; boundLoop: for(int xx = (int)bb.minX; xx <= (int)bb.maxX; xx++) { for(int zz = (int)bb.minZ; zz <= (int)bb.maxZ && whole; zz++) { if(world.getBlock(xx, (int)bb.minY-1, zz) != AdvancedRocketryBlocks.blockLaunchpad) { whole = false; break boundLoop; } } } return whole; } public int getVolume(World world, int x, int y, int z, AxisAlignedBB bb) { return (int) ((bb.maxX - bb.minX) * (bb.maxY - bb.minY) * (bb.maxZ - bb.minZ)); } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); stats.writeToNBT(nbt); nbt.setInteger("scanTime", progress); nbt.setInteger("scanTotalBlocks", totalProgress); nbt.setBoolean("building", building); if(bbCache != null) { NBTTagCompound tag = new NBTTagCompound(); tag.setDouble("minX", bbCache.minX); tag.setDouble("minY", bbCache.minY); tag.setDouble("minZ", bbCache.minZ); tag.setDouble("maxX", bbCache.maxX); tag.setDouble("maxY", bbCache.maxY); tag.setDouble("maxZ", bbCache.maxZ); nbt.setTag("bb", tag); } if(!blockPos.isEmpty()) { int[] array = new int[blockPos.size()*3]; int counter = 0; for(BlockPosition pos : blockPos) { array[counter] = pos.x; array[counter+1] = pos.y; array[counter+2] = pos.z; counter += 3; } nbt.setIntArray("infrastructureLocations", array); } } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); stats.readFromNBT(nbt); prevProgress = progress = nbt.getInteger("scanTime"); totalProgress = nbt.getInteger("scanTotalBlocks"); building = nbt.getBoolean("building"); if(nbt.hasKey("bb")) { NBTTagCompound tag = nbt.getCompoundTag("bb"); bbCache = AxisAlignedBB.getBoundingBox(tag.getDouble("minX"), tag.getDouble("minY"), tag.getDouble("minZ"), tag.getDouble("maxX"), tag.getDouble("maxY"), tag.getDouble("maxZ")); } blockPos.clear(); if(nbt.hasKey("infrastructureLocations")) { int array[] = nbt.getIntArray("infrastructureLocations"); for(int counter = 0; counter < array.length; counter += 3) { blockPos.add(new BlockPosition(array[counter], array[counter+1], array[counter+2])); } } } @Override public Packet getDescriptionPacket() { super.getDescriptionPacket(); NBTTagCompound nbt = new NBTTagCompound(); writeToNBT(nbt); return new S35PacketUpdateTileEntity(xCoord, yCoord, zCoord, 0, nbt); } @Override public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) { readFromNBT(pkt.func_148857_g()); } //Creates the effects for building the rocket and changes state to build public void startBuild(int x, int y, int z) { } @Override public void writeDataToNetwork(ByteBuf out, byte id) { //Used to sync clinet/server if(id == 2) { out.writeInt(energy.getEnergyStored()); out.writeInt(this.progress); } } @Override public void readDataFromNetwork(ByteBuf in, byte id, NBTTagCompound nbt) { if(id == 2) { nbt.setInteger("pwr", in.readInt()); nbt.setInteger("tik", in.readInt()); } } public boolean canScan() { return bbCache != null; } @Override public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { if(id == 0) { AxisAlignedBB bb = getRocketPadBounds(worldObj, xCoord, yCoord, zCoord); bbCache = bb; if(!canScan()) return; totalProgress = (int) (Configuration.buildSpeedMultiplier*this.getVolume(worldObj, xCoord, yCoord, zCoord, bbCache)/10); this.markDirty(); this.worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); } else if(id == 1) { if(isScanning()) return; building = true; AxisAlignedBB bb = getRocketPadBounds(worldObj, xCoord, yCoord, zCoord); bbCache = bb; if(!canScan()) return; totalProgress =(int) (Configuration.buildSpeedMultiplier*this.getVolume(worldObj, xCoord, yCoord, zCoord,bbCache)/10); this.markDirty(); this.worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); } else if(id == 2){ energy.setEnergyStored(nbt.getInteger("pwr")); this.progress = nbt.getInteger("tik"); } } protected void updateText() { thrustText.setText(isScanning() ? "Thrust: ???" : String.format("Thrust: %dN",getThrust())); weightText.setText(isScanning() ? "Weight: ???" : String.format("Weight: %dN",getWeight())); fuelText.setText(isScanning() ? "Fuel: ???" : String.format("Fuel: %dmb/s", getRocketStats().getFuelRate(FuelType.LIQUID))); accelerationText.setText(isScanning() ? "Acc: ???" : String.format("Acc: %.2fm/s", getAcceleration()*20f)); if(!worldObj.isRemote) { if(getRocketPadBounds(worldObj, xCoord, yCoord, zCoord) == null) setStatus(ErrorCodes.INCOMPLETESTRCUTURE.ordinal()); else if( ErrorCodes.INCOMPLETESTRCUTURE.equals(getStatus())) setStatus(ErrorCodes.UNSCANNED.ordinal()); } errorText.setText(getStatus().getErrorCode()); } @Override public List<ModuleBase> getModules(int ID, EntityPlayer player) { List<ModuleBase> modules = new LinkedList<ModuleBase>(); modules.add(new ModulePower(160, 90, this)); if(worldObj.isRemote) modules.add(new ModuleImage(4, 9, new IconResource(4, 9, 168, 74, backdrop))); modules.add(new ModuleProgress(89, 47, 0, horizontalProgressBar, this)); modules.add(new ModuleProgress(89, 66, 1, horizontalProgressBar, this)); modules.add(new ModuleProgress(89, 28, 3, horizontalProgressBar, this)); modules.add(new ModuleProgress(89, 9, 4, horizontalProgressBar, this)); modules.add(new ModuleProgress(149, 90, 2, verticalProgressBar, this)); modules.add(new ModuleButton(5, 94, 0, "Scan", this, zmaster587.libVulpes.inventory.TextureResources.buttonScan)); ModuleButton buttonBuild; modules.add(buttonBuild = new ModuleButton(5, 120, 1, "Build", this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); buttonBuild.setColor(0xFFFF2222); modules.add(thrustText = new ModuleText(8, 15, "", 0xFF22FF22)); modules.add(weightText = new ModuleText(8, 34, "", 0xFF22FF22)); modules.add(fuelText = new ModuleText(8, 52, "", 0xFF22FF22)); modules.add(accelerationText = new ModuleText(8, 71, "", 0xFF22FF22)); modules.add(errorText = new ModuleText(5, 84, "", 0xFFFFFF22)); updateText(); for(int i = 0; i < 5; i++) modules.add(new ModuleSync(i, this)); return modules; } @Override public String getModularInventoryName() { return ""; } @Override public float getNormallizedProgress(int id) { if(isScanning() && id != 2) return 0f; switch(id) { case 0: return (this.getAcceleration() > 0) ? MathHelper.clamp_float(0.5f + 0.5f*((this.getFuel() - this.getNeededFuel())/this.getNeededFuel()), 0f, 1f) : 0; case 1: return MathHelper.clamp_float(0.5f + this.getAcceleration()*10, 0f, 1f); case 2: return (float)this.getNormallizedProgress(); case 3: return this.getWeight() > 0 ? 0.5f : 0f; case 4: return this.getThrust() > 0 ? 0.9f : 0f; } return 0f; } @Override public void setProgress(int id, int progress) { if(id == 2) setProgress(progress); } @Override public int getProgress(int id) { if(id == 2) return getProgress(); return 0; } @Override public int getTotalProgress(int id) { if(id == 2) return getTotalProgress(); return 0; } @Override public void setTotalProgress(int id, int progress) { if(id == 2) { setTotalProgress(progress); updateText(); } } @Override public void setData(int id, int value) { switch(id) { case 0: getRocketStats().setFuelRate(FuelType.LIQUID, value); break; case 1: getRocketStats().setWeight(value); break; case 2: getRocketStats().setThrust(value); break; case 3: getRocketStats().setFuelCapacity(FuelType.LIQUID, value); break; case 4: setStatus(value); } updateText(); } @Override public int getData(int id) { switch(id) { case 0: return getRocketStats().getFuelRate(FuelType.LIQUID); case 1: return getRocketStats().getWeight(); case 2: return getRocketStats().getThrust(); case 3: return getRocketStats().getFuelCapacity(FuelType.LIQUID); case 4: return getStatus().ordinal(); } return 0; } @Override public void onInventoryButtonPressed(int buttonId) { PacketHandler.sendToServer(new PacketMachine(this,(byte)( buttonId)) ); updateText(); } @Override public boolean canInteractWithContainer(EntityPlayer entity) { return true; } @Override public boolean canConnectEnergy(ForgeDirection arg0) { return true; } @Override public boolean onLinkStart(ItemStack item, TileEntity entity, EntityPlayer player, World world) { return true; } @Override public boolean onLinkComplete(ItemStack item, TileEntity entity, EntityPlayer player, World world) { TileEntity tile = world.getTileEntity(((ItemLinker)item.getItem()).getMasterX(item), ((ItemLinker)item.getItem()).getMasterY(item), ((ItemLinker)item.getItem()).getMasterZ(item)); if(tile instanceof IInfrastructure) { BlockPosition pos = new BlockPosition(tile.xCoord, tile.yCoord, tile.zCoord); if(!blockPos.contains(pos)) blockPos.add(pos); if(getBBCache() == null) { bbCache = getRocketPadBounds(worldObj, xCoord, yCoord, zCoord); } if(getBBCache() != null) { List<EntityRocketBase> rockets = worldObj.getEntitiesWithinAABB(EntityRocketBase.class, bbCache); for(EntityRocketBase rocket : rockets) { rocket.linkInfrastructure((IInfrastructure) tile); } } if(!worldObj.isRemote) { player.addChatMessage(new ChatComponentText("Linked Sucessfully")); if(tile instanceof IMultiblock) ((IMultiblock)tile).setMasterBlock(xCoord, yCoord, zCoord); } ItemLinker.resetPosition(item); return true; } return false; } public void removeConnectedInfrastructure(TileEntity tile) { blockPos.remove(new BlockPosition(tile.xCoord, tile.yCoord, tile.zCoord)); if(getBBCache() == null) { bbCache = getRocketPadBounds(worldObj, xCoord, yCoord, zCoord); } if(getBBCache() != null) { List<EntityRocketBase> rockets = worldObj.getEntitiesWithinAABB(EntityRocketBase.class, bbCache); for(EntityRocketBase rocket : rockets) { rocket.unlinkInfrastructure((IInfrastructure) tile); } } } public List<IInfrastructure> getConnectedInfrastructure() { List<IInfrastructure> infrastructure = new LinkedList<IInfrastructure>(); Iterator<BlockPosition> iter = blockPos.iterator(); while(iter.hasNext()) { BlockPosition position = iter.next(); TileEntity tile = worldObj.getTileEntity(position.x, position.y, position.z); if((tile = worldObj.getTileEntity(position.x, position.y, position.z)) instanceof IInfrastructure) { infrastructure.add((IInfrastructure)tile); } else iter.remove(); } return infrastructure; } @SubscribeEvent public void onRocketLand(RocketLandedEvent event) { EntityRocketBase rocket = (EntityRocketBase)event.entity; if(getBBCache() == null) { bbCache = getRocketPadBounds(worldObj, xCoord, yCoord, zCoord); } if(getBBCache() != null) { List<EntityRocketBase> rockets = worldObj.getEntitiesWithinAABB(EntityRocketBase.class, bbCache); if(rockets.contains(rocket)) { for(IInfrastructure infrastructure : getConnectedInfrastructure()) { rocket.linkInfrastructure(infrastructure); } } } } }