package mcjty.deepresonance.blocks.generator; import cofh.api.energy.IEnergyConnection; import cofh.api.energy.IEnergyProvider; import com.google.common.collect.Sets; import elec332.core.world.WorldHelper; import mcjty.deepresonance.generatornetwork.DRGeneratorNetwork; import mcjty.deepresonance.varia.EnergyTools; import mcjty.lib.entity.GenericTileEntity; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.ITickable; import net.minecraft.util.math.BlockPos; import java.util.HashSet; import java.util.Set; public class GeneratorTileEntity extends GenericTileEntity implements IEnergyProvider, ITickable { private int networkId = -1; public GeneratorTileEntity() { super(); } public void addBlockToNetwork() { Set<Integer> adjacentGeneratorIds = new HashSet<Integer>(); for (EnumFacing direction : EnumFacing.VALUES) { BlockPos pos = getPos().offset(direction); Block block = WorldHelper.getBlockAt(worldObj, pos); if (block == GeneratorSetup.generatorBlock) { GeneratorTileEntity generatorTileEntity = (GeneratorTileEntity) WorldHelper.getTileAt(worldObj, pos); adjacentGeneratorIds.add(generatorTileEntity.getNetworkId()); } } DRGeneratorNetwork generatorNetwork = DRGeneratorNetwork.getChannels(worldObj); if (adjacentGeneratorIds.isEmpty()) { // New network. networkId = generatorNetwork.newChannel(); DRGeneratorNetwork.Network network = generatorNetwork.getOrCreateNetwork(networkId); network.setGeneratorBlocks(1); } else if (adjacentGeneratorIds.size() == 1) { // Only one network adjacent. So we can simply join this new block to that network. networkId = adjacentGeneratorIds.iterator().next(); DRGeneratorNetwork.Network network = generatorNetwork.getOrCreateNetwork(networkId); network.setActive(false); // Deactivate to make sure it properly restarts network.incGeneratorBlocks(); } else { // We need to merge networks. The first network will be the master. First we // calculate the total amount of energy in all the networks that are merged this way. int energy = 0; for (Integer netId : adjacentGeneratorIds) { DRGeneratorNetwork.Network network = generatorNetwork.getOrCreateNetwork(netId); network.setActive(false); // Deactivate to make sure it properly restarts energy += network.getEnergy(); } int id = adjacentGeneratorIds.iterator().next(); Set<BlockPos> done = Sets.newHashSet(); setBlocksToNetwork(pos, done, id); DRGeneratorNetwork.Network network = generatorNetwork.getOrCreateNetwork(networkId); network.setEnergy(energy); } generatorNetwork.save(worldObj); } private void setBlocksToNetwork(BlockPos c, Set<BlockPos> done, int newId) { done.add(c); DRGeneratorNetwork generatorNetwork = DRGeneratorNetwork.getChannels(worldObj); GeneratorTileEntity generatorTileEntity = (GeneratorTileEntity) WorldHelper.getTileAt(worldObj, c); int oldNetworkId = generatorTileEntity.getNetworkId(); if (oldNetworkId != newId) { if (oldNetworkId != -1) { generatorNetwork.getOrCreateNetwork(oldNetworkId).decGeneratorBlocks(); } generatorTileEntity.setNetworkId(newId); if (newId != -1) { generatorNetwork.getOrCreateNetwork(newId).incGeneratorBlocks(); } } for (EnumFacing direction : EnumFacing.VALUES) { BlockPos newC = c.offset(direction); if (!done.contains(newC)) { Block block = WorldHelper.getBlockAt(worldObj, newC); if (block == GeneratorSetup.generatorBlock) { setBlocksToNetwork(newC, done, newId); } } } } public void removeBlockFromNetwork() { int totalEnergy = 0; int totalBlocks = 0; if (networkId != -1) { DRGeneratorNetwork generatorNetwork = DRGeneratorNetwork.getChannels(worldObj); DRGeneratorNetwork.Network network = generatorNetwork.getOrCreateNetwork(networkId); network.setActive(false); // Deactivate to make sure it properly restarts network.decGeneratorBlocks(); totalEnergy = network.getEnergy(); totalBlocks = network.getGeneratorBlocks(); setNetworkId(-1); } // Safety: if (totalBlocks < 1) { totalBlocks = 1; } DRGeneratorNetwork generatorNetwork = DRGeneratorNetwork.getChannels(worldObj); // Clear all networks adjacent to this one. for (EnumFacing direction : EnumFacing.VALUES) { BlockPos newC = getPos().offset(direction); Block block = WorldHelper.getBlockAt(worldObj, newC); if (block == GeneratorSetup.generatorBlock) { Set<BlockPos> done = Sets.newHashSet(); done.add(pos); setBlocksToNetwork(newC, done, -1); } } // Now assign new ones. int idToUse = networkId; for (EnumFacing direction : EnumFacing.VALUES) { BlockPos newC = getPos().offset(direction); Block block = WorldHelper.getBlockAt(worldObj, newC); if (block == GeneratorSetup.generatorBlock) { GeneratorTileEntity generatorTileEntity = (GeneratorTileEntity) WorldHelper.getTileAt(worldObj, newC); if (generatorTileEntity.getNetworkId() == -1) { if (idToUse == -1) { idToUse = generatorNetwork.newChannel(); } Set<BlockPos> done = Sets.newHashSet(); done.add(getPos()); setBlocksToNetwork(newC, done, idToUse); generatorNetwork.getOrCreateNetwork(idToUse).setEnergy(-1); // Marker so we know what energy to set later. idToUse = -1; } } } // Now we need to redistribute the total energy based on the size of the adjacent networks. int energy = totalEnergy / totalBlocks; int remainder = totalEnergy % totalBlocks; for (EnumFacing direction : EnumFacing.VALUES) { BlockPos newC = getPos().offset(direction); Block block = WorldHelper.getBlockAt(worldObj, newC); if (block == GeneratorSetup.generatorBlock) { GeneratorTileEntity generatorTileEntity = (GeneratorTileEntity) WorldHelper.getTileAt(worldObj, newC); DRGeneratorNetwork.Network network = generatorTileEntity.getNetwork(); if (network.getEnergy() == -1) { network.setEnergy(energy * network.getGeneratorBlocks() + remainder); remainder = 0; // Only the first network gets the remainder. } } } generatorNetwork.save(worldObj); } // Move this tile entity to another network. public void setNetworkId(int newId) { networkId = newId; markDirty(); IBlockState state = worldObj.getBlockState(pos); worldObj.notifyBlockUpdate(pos, state, state, 3); } public int getNetworkId() { return networkId; } public DRGeneratorNetwork.Network getNetwork() { if (networkId == -1) { return null; } DRGeneratorNetwork generatorNetwork = DRGeneratorNetwork.getChannels(worldObj); return generatorNetwork.getOrCreateNetwork(networkId); } public void activate(boolean active) { DRGeneratorNetwork.Network network = getNetwork(); if (network != null && network.isActive() != active) { network.setActive(active); DRGeneratorNetwork generatorNetwork = DRGeneratorNetwork.getChannels(worldObj); generatorNetwork.save(worldObj); Set<BlockPos> done = Sets.newHashSet(); activateBlocks(getPos(), done, active); } } private void activateBlocks(BlockPos c, Set<BlockPos> done, boolean active) { done.add(c); IBlockState state = worldObj.getBlockState(c); if (state.getValue(GeneratorBlock.ENABLED) != active) { worldObj.setBlockState(c, state.withProperty(GeneratorBlock.ENABLED, active), 3); } for (EnumFacing direction : EnumFacing.VALUES) { BlockPos newC = c.offset(direction); if (!done.contains(newC)) { Block block = WorldHelper.getBlockAt(worldObj, newC); if (block == GeneratorSetup.generatorBlock) { activateBlocks(newC, done, active); } } } } @Override public void readFromNBT(NBTTagCompound tagCompound) { super.readFromNBT(tagCompound); networkId = tagCompound.getInteger("networkId"); } @Override public void writeToNBT(NBTTagCompound tagCompound) { super.writeToNBT(tagCompound); tagCompound.setInteger("networkId", networkId); } @Override public void update() { if (!worldObj.isRemote) { checkStateServer(); } } private void checkStateServer() { int energyStored = getEnergyStored(EnumFacing.DOWN); if (energyStored <= 0) { return; } for (int i = 0 ; i < 6 ; i++) { BlockPos pos = getPos().offset(EnumFacing.VALUES[i]); TileEntity te = WorldHelper.getTileAt(worldObj, pos); if (EnergyTools.isEnergyTE(te)) { IEnergyConnection connection = (IEnergyConnection) te; EnumFacing opposite = EnumFacing.VALUES[i].getOpposite(); if (connection.canConnectEnergy(opposite)) { int rfToGive; if (GeneratorConfiguration.rfPerTickGenerator <= energyStored) { rfToGive = GeneratorConfiguration.rfPerTickGenerator; } else { rfToGive = energyStored; } int received = EnergyTools.receiveEnergy(te, opposite, rfToGive); energyStored -= extractEnergy(EnumFacing.DOWN, received, false); if (energyStored <= 0) { break; } } } } } @Override public int extractEnergy(EnumFacing from, int maxExtract, boolean simulate) { if (networkId == -1) { return 0; } DRGeneratorNetwork.Network network = getNetwork(); int energy = network.getEnergy(); if (maxExtract > energy) { maxExtract = energy; } if (maxExtract > GeneratorConfiguration.rfPerTickGenerator) { maxExtract = GeneratorConfiguration.rfPerTickGenerator; } if (!simulate) { network.setEnergy(energy - maxExtract); DRGeneratorNetwork.getChannels(worldObj).save(worldObj); } return maxExtract; } @Override public int getEnergyStored(EnumFacing from) { if (networkId == -1) { return 0; } DRGeneratorNetwork.Network network = getNetwork(); return network.getEnergy(); } @Override public int getMaxEnergyStored(EnumFacing from) { if (networkId == -1) { return 0; } DRGeneratorNetwork.Network network = getNetwork(); return network.getGeneratorBlocks() * GeneratorConfiguration.rfPerGeneratorBlock; } @Override public boolean canConnectEnergy(EnumFacing from) { return true; } }