package zmaster587.advancedRocketry.tile.multiblock; import io.netty.buffer.ByteBuf; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Random; import cpw.mods.fml.relauncher.Side; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.EnumFacing; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; import zmaster587.advancedRocketry.api.AdvancedRocketryItems; import zmaster587.advancedRocketry.api.DataStorage; import zmaster587.advancedRocketry.api.DataStorage.DataType; import zmaster587.advancedRocketry.inventory.TextureResources; import zmaster587.advancedRocketry.inventory.modules.ModuleData; import zmaster587.advancedRocketry.item.ItemAsteroidChip; import zmaster587.advancedRocketry.item.ItemPlanetIdentificationChip; import zmaster587.advancedRocketry.tile.hatch.TileDataBus; import zmaster587.advancedRocketry.util.ITilePlanetSystemSelectable; import zmaster587.advancedRocketry.world.util.MultiData; import zmaster587.libVulpes.block.BlockMeta; import zmaster587.libVulpes.client.util.ProgressBarImage; import zmaster587.libVulpes.inventory.modules.IModularInventory; import zmaster587.libVulpes.inventory.modules.ModuleBase; import zmaster587.libVulpes.inventory.modules.ModuleButton; import zmaster587.libVulpes.inventory.modules.ModuleOutputSlotArray; import zmaster587.libVulpes.inventory.modules.ModulePower; import zmaster587.libVulpes.inventory.modules.ModuleProgress; import zmaster587.libVulpes.inventory.modules.ModuleSlotArray; import zmaster587.libVulpes.inventory.modules.ModuleText; import zmaster587.libVulpes.inventory.modules.ModuleTexturedSlotArray; import zmaster587.libVulpes.inventory.modules.ModuleToggleSwitch; import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.network.PacketMachine; import zmaster587.libVulpes.tile.multiblock.TileMultiPowerConsumer; import zmaster587.libVulpes.tile.multiblock.hatch.TileInputHatch; import zmaster587.libVulpes.tile.multiblock.hatch.TileInventoryHatch; import zmaster587.libVulpes.tile.multiblock.hatch.TileOutputHatch; import zmaster587.libVulpes.util.EmbeddedInventory; public class TileAstrobodyDataProcessor extends TileMultiPowerConsumer implements IModularInventory, IInventory { private static final Object[][][] structure = new Object[][][]{ {{Blocks.stone_slab, 'c', Blocks.stone_slab}, {Blocks.stone_slab, Blocks.stone_slab, Blocks.stone_slab}}, {{'P','I', 'O'}, {'D','D','D'}} }; private TileDataBus dataCables[]; private boolean researchingDistance, researchingAtmosphere, researchingMass; private int atmosphereProgress, distanceProgress, massProgress; private static final int maxResearchTime = 20; private EmbeddedInventory inventory; TileInventoryHatch inputHatch, outputHatch; public TileAstrobodyDataProcessor() { dataCables = new TileDataBus[3]; powerPerTick = 100; massProgress = distanceProgress = atmosphereProgress = -1; inventory = new EmbeddedInventory(3); } @Override public List<BlockMeta> getAllowableWildCardBlocks() { List<BlockMeta> list = super.getAllowableWildCardBlocks(); list.add(new BlockMeta(Blocks.iron_block,BlockMeta.WILDCARD)); return list; } @Override protected void integrateTile(TileEntity tile) { super.integrateTile(tile); if(tile instanceof TileDataBus) { for(int i = 0; i < dataCables.length; i++) { if(dataCables[i] == null) { dataCables[i] = (TileDataBus)tile; switch(i) { case 0: dataCables[i].lockData(DataStorage.DataType.COMPOSITION); break; case 1: dataCables[i].lockData(DataStorage.DataType.DISTANCE); break; case 2: dataCables[i].lockData(DataStorage.DataType.MASS); } break; } } } else if(tile instanceof TileInputHatch) { inputHatch = (TileInventoryHatch) tile; } else if(tile instanceof TileOutputHatch) { outputHatch = (TileInventoryHatch) tile; } } @Override public void deconstructMultiBlock(World world, int destroyedX, int destroyedY, int destroyedZ, boolean blockBroken) { //Make sure to unlock the data cables for(int i = 0; i < dataCables.length; i++) { if(dataCables[i] != null) dataCables[i].lockData(null); } super.deconstructMultiBlock(world, destroyedX, destroyedY, destroyedZ, blockBroken); } @Override public void resetCache() { super.resetCache(); Arrays.fill(dataCables, null); inputHatch = null; outputHatch = null; } @Override public Object[][][] getStructure() { return structure; } @Override public String getMachineName() { return "tile.planetanalyser.name"; } @Override public AxisAlignedBB getRenderBoundingBox() { //TODO return AxisAlignedBB.getBoundingBox(xCoord -2,yCoord -2, zCoord -2, xCoord + 2, yCoord + 2, zCoord + 2); } private boolean canProcess() { ItemStack inputStack = this.getStackInSlot(0); return !super.isRunning() && inputStack != null && inputStack.getItem().equals(AdvancedRocketryItems.itemAsteroidChip) && !inputStack.hasTagCompound() && this.getStackInSlot(1) == null; } private void process() { //Disable user input while the machine is processing to prevent the outcome being modified this.decrStackSize(0, 1); completionTime = 500; } @Override public void onInventoryUpdated() { super.onInventoryUpdated(); if(inputHatch == null) return; if(inventory.getStackInSlot(1) != null) { for(int i = 0; i < outputHatch.getSizeInventory(); i++) { if(outputHatch.getStackInSlot(i) == null) { outputHatch.setInventorySlotContentsNoUpdate(i, inventory.getStackInSlot(1)); inventory.setInventorySlotContents(1, null); break; } } } ItemStack stack0 = inventory.getStackInSlot(0); if(stack0 == null || stack0.stackSize < stack0.getMaxStackSize()) for(int i = 0; i < inputHatch.getSizeInventory(); i++){ ItemStack stack = inputHatch.getStackInSlot(i); if(stack != null && stack.getItem() instanceof ItemAsteroidChip && ((ItemAsteroidChip)stack.getItem()).getUUID(stack) == null ) { if(stack0 == null) { inventory.setInventorySlotContents(0, stack); inputHatch.setInventorySlotContentsNoUpdate(i, null); } else { stack0.stackSize += inputHatch.decrStackSize(i, stack0.getMaxStackSize() - stack0.stackSize).stackSize; //inventory.setInventorySlotContents(0, stack0); } if(!worldObj.isRemote) { markDirty(); inputHatch.markDirty(); worldObj.markBlockForUpdate(this.xCoord, this.yCoord, this.zCoord); worldObj.markBlockForUpdate(inputHatch.xCoord, inputHatch.yCoord, inputHatch.zCoord); } } if(canProcess()) process(); } if(getStackInSlot(2) == null) { for(int j = 0; j < inputHatch.getSizeInventory(); j++) { ItemStack stack2 = inputHatch.getStackInSlot(j); if(stack2 != null && stack2.getItem() instanceof ItemAsteroidChip && ((ItemAsteroidChip)stack2.getItem()).getUUID(stack2) != null) { setInventorySlotContents(2, inputHatch.decrStackSize(j, 1)); break; } } } attemptAllResearchStart(); } @Override protected void processComplete() { super.processComplete(); //The machine is done re-enable user input if(!worldObj.isRemote) { ItemStack outputItem = new ItemStack(AdvancedRocketryItems.itemAsteroidChip); ItemAsteroidChip item = (ItemAsteroidChip)outputItem.getItem(); //Get UUID item.setUUID(outputItem, (new Random(worldObj.getTotalWorldTime())).nextLong() % 10000); item.setMaxData(outputItem, 2000); //TODO: fix naming system //int dimensionId = DimensionManager.getInstance().generateRandom("", baseAtmosphere, baseDistance, baseGravity, atmosphereFactor, distanceFactor, gravityFactor); for(int i = 0; i < outputHatch.getSizeInventory(); i++) { if(outputHatch.getStackInSlot(i) == null) { outputHatch.setInventorySlotContents(i, outputItem); return; } } this.setInventorySlotContents(1, outputItem); } } @Override public boolean completeStructure() { boolean result = super.completeStructure(); if(result) { worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, this.getBlockMetadata() | 8, 2); } else worldObj.setBlockMetadataWithNotify(xCoord, yCoord, zCoord, this.getBlockMetadata() & 7, 2); return result; } private void incrementDataOnChip(int planetId, int amount, DataStorage.DataType dataType) { ItemStack stack = getStackInSlot(2); if(stack != null && stack.getItem().equals(AdvancedRocketryItems.itemAsteroidChip)) { ItemAsteroidChip item = (ItemAsteroidChip)stack.getItem(); item.addData(stack, amount, dataType); int maxData = item.getMaxData(stack); if(item.getData(stack, DataType.COMPOSITION) == maxData && item.getData(stack, DataType.DISTANCE) == maxData && item.getData(stack, DataType.MASS) == maxData) { for(int i = 0; i < outputHatch.getSizeInventory(); i++) { if(outputHatch.getStackInSlot(i) == null) { outputHatch.setInventorySlotContents(i, stack); setInventorySlotContents(2, null); return; } } } } } private void attemptAllResearchStart() { ItemStack stack = getStackInSlot(2); if(stack == null || !(stack.getItem() instanceof ItemAsteroidChip)) return; ItemAsteroidChip item = (ItemAsteroidChip)stack.getItem(); if(researchingAtmosphere && atmosphereProgress < 0 && extractData(1, DataStorage.DataType.COMPOSITION, false) > 0 && !item.isFull(stack, DataStorage.DataType.COMPOSITION)) atmosphereProgress = 0; if(researchingDistance && distanceProgress < 0 && extractData(1, DataStorage.DataType.DISTANCE, false) > 0 && !item.isFull(stack, DataStorage.DataType.DISTANCE)) distanceProgress = 0; if(researchingMass && massProgress < 0 && extractData(1, DataStorage.DataType.MASS, false) > 0 && !item.isFull(stack, DataStorage.DataType.MASS)) massProgress = 0; this.markDirty(); worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); } private int extractData(int amt, DataStorage.DataType type, boolean simulate) { switch(type) { case COMPOSITION: if(dataCables[0] != null) return dataCables[0].extractData(1, DataStorage.DataType.COMPOSITION, ForgeDirection.UNKNOWN, !simulate); case DISTANCE: if(dataCables[1] != null) return dataCables[1].extractData(1, DataStorage.DataType.DISTANCE, ForgeDirection.UNKNOWN, !simulate); case MASS: if(dataCables[2] != null) return dataCables[2].extractData(1, DataStorage.DataType.MASS, ForgeDirection.UNKNOWN, !simulate); default: return 0; } } @Override protected void onRunningPoweredTick() { if(completionTime > 0) super.onRunningPoweredTick(); ItemStack stack = getStackInSlot(2); if(stack != null && stack.getItem().equals(AdvancedRocketryItems.itemAsteroidChip)) { ItemAsteroidChip item = (ItemAsteroidChip) stack.getItem(); if(researchingAtmosphere && extractData(1, DataStorage.DataType.COMPOSITION, true) > 0 && !item.isFull(stack, DataStorage.DataType.COMPOSITION)) { if(atmosphereProgress == maxResearchTime) { atmosphereProgress = -1; if(!worldObj.isRemote) { incrementDataOnChip(0, 1, DataType.COMPOSITION); extractData(1, DataStorage.DataType.COMPOSITION, false); //attemptAllResearchStart(); } } else atmosphereProgress++; } if(researchingMass && extractData(1, DataStorage.DataType.MASS, true) > 0 && !item.isFull(stack, DataStorage.DataType.MASS)) { if(massProgress == maxResearchTime) { massProgress = -1; if(!worldObj.isRemote) { incrementDataOnChip(0, 1, DataType.MASS); extractData(1, DataStorage.DataType.MASS, false); //attemptAllResearchStart(); } } else massProgress++; } if(researchingDistance && extractData(1, DataStorage.DataType.DISTANCE, true) > 0 && !item.isFull(stack, DataStorage.DataType.DISTANCE)) { if(distanceProgress == maxResearchTime) { distanceProgress = -1; if(!worldObj.isRemote) { incrementDataOnChip(0, 1, DataType.DISTANCE); extractData(1, DataStorage.DataType.DISTANCE, false); //attemptAllResearchStart(); } } else distanceProgress++; } } } @Override public boolean isRunning() { return super.isRunning() || (getStackInSlot(2) != null && getStackInSlot(2).getItem().equals(AdvancedRocketryItems.itemAsteroidChip) && (researchingAtmosphere || researchingDistance || researchingMass)); } @Override public void onInventoryButtonPressed(int buttonId) { if(buttonId == 0) super.onInventoryButtonPressed(buttonId); else if(buttonId == 1) { //Process button is pressed PacketHandler.sendToServer(new PacketMachine(this, (byte)2)); } else if(buttonId == 2) { //densitySetting = densityButton.getOptionSelected(); //distanceSetting = distanceButton.getOptionSelected(); //PacketHandler.sendToServer(new PacketMachine(this,(byte)101)); } else if(buttonId == 4) { researchingAtmosphere = !researchingAtmosphere; PacketHandler.sendToServer(new PacketMachine(this, (byte)4)); } else if(buttonId == 5) { researchingDistance = !researchingDistance; PacketHandler.sendToServer(new PacketMachine(this, (byte)4)); } else if(buttonId == 6) { researchingMass = ! researchingMass; PacketHandler.sendToServer(new PacketMachine(this, (byte)4)); } } @Override public void writeDataToNetwork(ByteBuf out, byte id) { super.writeDataToNetwork(out, id); if(id == 4) { out.writeInt((researchingAtmosphere ? 1 : 0) | (researchingDistance ? 2 : 0) | (researchingMass ? 4 : 0)); } } @Override public void readDataFromNetwork(ByteBuf in, byte packetId, NBTTagCompound nbt) { super.readDataFromNetwork(in, packetId, nbt); if(packetId == 3 || packetId == 4 || packetId > 100) { nbt.setInteger("state", in.readInt()); } } @Override public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { super.useNetworkData(player, side, id, nbt); if(id == 2) { if(canProcess()) process(); } else if (id == 4) { int states = nbt.getInteger("state"); researchingAtmosphere = (states & 1) != 0; researchingDistance = (states & 2) != 0; researchingMass = (states & 4) != 0; attemptAllResearchStart(); this.markDirty(); worldObj.markBlockForUpdate(xCoord, yCoord, zCoord); } } @Override public List<ModuleBase> getModules(int ID, EntityPlayer player) { LinkedList<ModuleBase> modules = new LinkedList<ModuleBase>(); modules.add(new ModulePower(18, 20, getBatteries())); //TODO: write NBT for(int i = 0; i < 3; i++) { if(dataCables[i] != null) modules.add(new ModuleData(32 + (i*30), 20, 0, dataCables[i], dataCables[i].getDataObject())); } int xStart = 150; int yStart = 14; modules.add(new ModuleTexturedSlotArray(xStart, yStart, this, 0, 1, TextureResources.idChip)); modules.add(new ModuleOutputSlotArray(xStart, yStart + 40, this, 1, 2)); modules.add(new ModuleProgress(xStart, yStart + 20, 0, new ProgressBarImage(217,0, 17, 17, 234, 0, ForgeDirection.DOWN, TextureResources.progressBars), this)); modules.add(new ModuleButton(xStart, yStart + 20, 1, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonNull, "Process discovery", 17, 17)); modules.add(new ModuleText(15, 76, "Research",0x404040)); modules.add(new ModuleToggleSwitch(15, 86, 4, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonToggleImage, "Composition Research", 11, 26, researchingAtmosphere)); modules.add(new ModuleToggleSwitch(65, 86, 5, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonToggleImage,"Distance Research", 11, 26, researchingDistance)); modules.add(new ModuleToggleSwitch(125, 86, 6, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonToggleImage, "Mass Research", 11, 26, researchingMass)); //Research indicators modules.add(new ModuleProgress(26, 86, 1, TextureResources.progressScience, this)); modules.add(new ModuleProgress(76, 86, 2, TextureResources.progressScience, this)); modules.add(new ModuleProgress(136, 86, 3, TextureResources.progressScience, this)); modules.add(new ModuleSlotArray(26, 120, this, 2, 3)); /*modules.add(new ModuleText(15, 76, "Atmos",0x404040)); modules.add(new ModuleText(65, 76, "Distance",0x404040)); modules.add(new ModuleText(125, 76, "Mass",0x404040));*/ /*List<ModuleBase> subModule = new LinkedList<ModuleBase>(); int solarRadius = 100; int center = 1000/2; subModule.add(new ModuleButton(center-solarRadius/2, center-solarRadius/2, 99, "", this, new ResourceLocation[] { TextureResources.locationSunPng}, solarRadius, solarRadius)); DimensionProperties properties = DimensionManager.getSol().getPlanets().get(0); subModule.add(new ModuleButton(center + properties.getMapDisplayPositionX() , center + properties.getMapDisplayPositionY(), 99, "", this, new ResourceLocation[] { properties.getPlanetIcon() }, properties.getName(), properties.getMapDisplayeSize(), properties.getMapDisplayeSize())); properties = DimensionManager.getInstance().getDimensionProperties(2); subModule.add(new ModuleButton(center + properties.getMapDisplayPositionX() , center + properties.getMapDisplayPositionY(), 99, "", this, new ResourceLocation[] { properties.getPlanetIcon() }, properties.getName(), properties.getMapDisplayeSize(), properties.getMapDisplayeSize()));*/ return modules; } @Override public int getProgress(int id) { if(id == 0) return super.getProgress(id); else if(id == 1) return atmosphereProgress; else if(id == 2) return distanceProgress; else if(id == 3) return massProgress; return 0; } @Override public int getTotalProgress(int id) { if(id == 0) return super.getTotalProgress(id); return maxResearchTime; } @Override public float getNormallizedProgress(int id) { if(id != 0) return getProgress(id)/ (float)getTotalProgress(id); else return completionTime > 0 ? currentTime/(float)completionTime : 0f; } @Override public void setProgress(int id, int progress) { if(id == 0) super.setProgress(id, progress); else if(id == 1) atmosphereProgress = progress; else if(id == 2) distanceProgress = progress; else massProgress = progress; } @Override public void setTotalProgress(int id, int progress) { if(id == 0) super.setTotalProgress(id, progress); } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); inventory.readFromNBT(nbt); researchingAtmosphere = nbt.getBoolean("researchingAtmosphere"); researchingDistance = nbt.getBoolean("researchingDistance"); researchingMass = nbt.getBoolean("researchingMass"); atmosphereProgress = nbt.getInteger("atmosphereProgress"); distanceProgress = nbt.getInteger("distanceProgress"); massProgress = nbt.getInteger("massProgress"); } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); inventory.writeToNBT(nbt); nbt.setBoolean("researchingAtmosphere", researchingAtmosphere); nbt.setBoolean("researchingDistance", researchingDistance); nbt.setBoolean("researchingMass", researchingMass); nbt.setInteger("atmosphereProgress", atmosphereProgress); nbt.setInteger("distanceProgress", distanceProgress); nbt.setInteger("massProgress", massProgress); } @Override public int getSizeInventory() { return inventory.getSizeInventory(); } @Override public ItemStack getStackInSlot(int slot) { return inventory.getStackInSlot(slot); } @Override public ItemStack decrStackSize(int slot, int amount) { return inventory.decrStackSize(slot, amount); } @Override public ItemStack getStackInSlotOnClosing(int slot) { return inventory.getStackInSlotOnClosing(slot); } @Override public void setInventorySlotContents(int slot, ItemStack stack) { inventory.setInventorySlotContents(slot, stack); onInventoryUpdated(); } @Override public String getInventoryName() { return getMachineName(); } @Override public boolean hasCustomInventoryName() { return false; } @Override public int getInventoryStackLimit() { return inventory.getInventoryStackLimit(); } @Override public boolean isUseableByPlayer(EntityPlayer player) { return player.getDistance(xCoord, yCoord, zCoord) < 64; } @Override public void openInventory() { } @Override public void closeInventory() { } @Override public boolean isItemValidForSlot(int slot, ItemStack stack) { return false;//inventory.isItemValidForSlot(slot, stack); } }