/** * Copyright (c) Lambda Innovation, 2013-2015 * 本作品版权由Lambda Innovation所有。 * http://www.li-dev.cn/ * <p/> * This project is open-source, and it is distributed under * the terms of GNU General Public License. You can modify * and distribute freely as long as you follow the license. * 本项目是一个开源项目,且遵循GNU通用公共授权协议。 * 在遵照该协议的情况下,您可以自由传播和修改。 * http://www.gnu.org/licenses/gpl.html */ package cn.academy.energy.internal; import cn.academy.energy.api.block.IWirelessGenerator; import cn.academy.energy.api.block.IWirelessNode; import cn.academy.energy.api.block.IWirelessReceiver; import cn.academy.energy.internal.VBlocks.VNGenerator; import cn.academy.energy.internal.VBlocks.VNNode; import cn.academy.energy.internal.VBlocks.VNReceiver; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.world.World; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; /** * @author WeAthFolD * */ public class NodeConn { static final int UPDATE_INTERVAL = 40; final WiWorldData data; final VNNode node; boolean disposed = false; boolean active = false; int counter = UPDATE_INTERVAL; List<VNReceiver> receivers = new LinkedList(); List<VNGenerator> generators = new LinkedList(); public NodeConn(WiWorldData _data, VNNode _node) { data = _data; node = _node; } public NodeConn(WiWorldData _data, NBTTagCompound tag) { data = _data; node = new VNNode(tag.getCompoundTag("node")); NBTTagList list = (NBTTagList) tag.getTag("receivers"); for (int i = 0; i < list.tagCount(); ++i) { addReceiver(new VNReceiver(list.getCompoundTagAt(i))); } list = (NBTTagList) tag.getTag("generators"); for (int i = 0; i < list.tagCount(); ++i) { addGenerator(new VNGenerator(list.getCompoundTagAt(i))); } } NBTTagCompound toNBT() { World world = getWorld(); NBTTagCompound ret = new NBTTagCompound(); NBTTagList list; list = new NBTTagList(); for (VNReceiver r : receivers) { if (!r.isLoaded(world) || r.get(world) != null) { list.appendTag(r.toNBT()); } } ret.setTag("receivers", list); list = new NBTTagList(); for (VNGenerator g : generators) { if (!g.isLoaded(world) || g.get(world) != null) { list.appendTag(g.toNBT()); } } ret.setTag("generators", list); ret.setTag("node", node.toNBT()); return ret; } public void dispose() { disposed = true; } public boolean isDisposed() { return disposed; } boolean addReceiver(VNReceiver receiver) { if (getLoad() >= getCapacity()) return false; World world = getWorld(); if (world != null) { NodeConn old = data.getNodeConnection(receiver.get(world)); if (old != null) { old.removeReceiver(receiver); } } receivers.add(receiver); data.nodeLookup.put(receiver, this); return true; } void removeReceiver(VNReceiver receiver) { receivers.remove(receiver); data.nodeLookup.remove(receiver); } boolean addGenerator(VNGenerator gen) { if (getLoad() >= getCapacity()) return false; World world = getWorld(); NodeConn old = data.getNodeConnection(gen.get(world)); if (old != null) { old.removeGenerator(gen); } generators.add(gen); data.nodeLookup.put(gen, this); return true; } void removeGenerator(VNGenerator gen) { generators.remove(gen); data.nodeLookup.remove(gen); } void onAdded(WiWorldData data) { data.nodeLookup.put(node, this); } void onCleanup(WiWorldData data) { data.nodeLookup.remove(node); for (VNGenerator gen : generators) data.nodeLookup.remove(gen); for (VNReceiver rec : receivers) data.nodeLookup.remove(rec); } private void checkIsActive() { World world = getWorld(); for (VNGenerator gen : generators) { if (gen.isLoaded(world)) { active = true; return; } } for (VNReceiver rec : receivers) { if (rec.isLoaded(world)) { active = true; return; } } active = false; } public void tick() { World world = getWorld(); if (!active) { --counter; if (counter == 0) { counter = UPDATE_INTERVAL; checkIsActive(); } return; } IWirelessNode iNode = node.get(world); if (iNode == null) { if (!node.isLoaded(world)) { System.out.println(node + " destroyed, destroy NodeConn..."); dispose(); } return; } double transferLeft = iNode.getBandwidth(); { Collections.shuffle(generators); Iterator<VNGenerator> iter = generators.iterator(); while (transferLeft != 0 && iter.hasNext()) { VNGenerator gen = iter.next(); if (gen.isLoaded(world)) { IWirelessGenerator igen = gen.get(world); if (igen == null) { iter.remove(); } else { double cur = iNode.getEnergy(); double required = Math.min(transferLeft, Math.min(igen.getBandwidth(), iNode.getMaxEnergy() - cur)); double amt = igen.getProvidedEnergy(required); if (amt > required) { //AcademyCraft.log.warn("Energy input overflow for generator " + igen); amt = required; } cur += amt; iNode.setEnergy(cur); transferLeft -= amt; } } } } transferLeft = iNode.getBandwidth(); { Collections.shuffle(receivers); Iterator<VNReceiver> iter = receivers.iterator(); while (transferLeft != 0 && iter.hasNext()) { VNReceiver rec = iter.next(); if (rec.isLoaded(world)) { IWirelessReceiver irec = rec.get(world); if (irec == null) { iter.remove(); } else { double cur = iNode.getEnergy(); double give = Math.min(cur, Math.min(transferLeft, irec.getBandwidth())); give = Math.min(irec.getRequiredEnergy(), give); give = give - irec.injectEnergy(give); cur -= give; transferLeft -= give; iNode.setEnergy(cur); } } } } // Kill dummy networks if (generators.size() == 0 && receivers.size() == 0) { dispose(); } } public IWirelessNode getNode() { return node.get(getWorld()); } private World getWorld() { return data.world; } public int getLoad() { return receivers.size() + generators.size(); } public int getCapacity() { World world = getWorld(); IWirelessNode inode = world == null ? null : node.get(getWorld()); return inode == null ? Integer.MAX_VALUE : inode.getCapacity(); } }