diff --git a/src/main/java/api/hbm/energymk2/Nodespace.java b/src/main/java/api/hbm/energymk2/Nodespace.java index 4016643332..5f9bcdb138 100644 --- a/src/main/java/api/hbm/energymk2/Nodespace.java +++ b/src/main/java/api/hbm/energymk2/Nodespace.java @@ -1,161 +1,40 @@ package api.hbm.energymk2; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map.Entry; -import java.util.Set; - import com.hbm.interfaces.NotableComments; +import com.hbm.uninos.GenNode; +import com.hbm.uninos.UniNodespace; +import com.hbm.uninos.networkproviders.PowerProvider; import com.hbm.util.fauxpointtwelve.BlockPos; import com.hbm.util.fauxpointtwelve.DirPos; -import net.minecraft.server.MinecraftServer; import net.minecraft.world.World; /** - * The "Nodespace" is an intermediate, "ethereal" layer of abstraction that tracks nodes (i.e. cables) even when they are no longer loaded, allowing continued operation even when unloaded + * The dead fucking corpse of nodespace MK1. + * A fantastic proof of concept, but ultimately it was killed for being just not that versatile. + * This class is mostly just a compatibility husk that should allow uninodespace to slide into the mod with as much lubrication as it deserves. + * * @author hbm - * */ -public class Nodespace { +@Deprecated public class Nodespace { - /** Contains all "NodeWorld" instances, i.e. lists of nodes existing per world */ - public static HashMap worlds = new HashMap<>(); - public static Set activePowerNets = new HashSet<>(); + public static final PowerProvider THE_POWER_PROVIDER = new PowerProvider(); public static PowerNode getNode(World world, int x, int y, int z) { - NodeWorld nodeWorld = worlds.get(world); - if(nodeWorld != null) return nodeWorld.nodes.get(new BlockPos(x, y, z)); - return null; - } - - public static void createNode(World world, PowerNode node) { - NodeWorld nodeWorld = worlds.get(world); - if(nodeWorld == null) { - nodeWorld = new NodeWorld(); - worlds.put(world, nodeWorld); - } - nodeWorld.pushNode(node); - } - - public static void destroyNode(World world, int x, int y, int z) { - PowerNode node = getNode(world, x, y, z); - if(node != null) { - worlds.get(world).popNode(node); - } - } - - /** Goes over each node and manages connections */ - public static void updateNodespace() { - - for(World world : MinecraftServer.getServer().worldServers) { - NodeWorld nodes = worlds.get(world); - - if(nodes == null) - continue; - - for(Entry entry : nodes.nodes.entrySet()) { - PowerNode node = entry.getValue(); - if(!node.hasValidNet() || node.recentlyChanged) { - checkNodeConnection(world, node); - node.recentlyChanged = false; - } - } - } - - updatePowerNets(); - } - - private static void updatePowerNets() { - - for(PowerNetMK2 net : activePowerNets) net.resetEnergyTracker(); //reset has to be done before everything else - for(PowerNetMK2 net : activePowerNets) net.transferPower(); - } - - /** Goes over each connection point of the given node, tries to find neighbor nodes and to join networks with them */ - private static void checkNodeConnection(World world, PowerNode node) { - - for(DirPos con : node.connections) { - - PowerNode conNode = getNode(world, con.getX(), con.getY(), con.getZ()); // get whatever neighbor node intersects with that connection - - if(conNode != null) { // if there is a node at that place - - if(conNode.hasValidNet() && conNode.net == node.net) continue; // if the net is valid and both nodes have the same net, skip - - if(checkConnection(conNode, con, false)) { - connectToNode(node, conNode); - } - } - } - - if(node.net == null || !node.net.isValid()) new PowerNetMK2().joinLink(node); + return (PowerNode) UniNodespace.getNode(world, x, y, z, THE_POWER_PROVIDER); } - public static boolean checkConnection(PowerNode connectsTo, DirPos connectFrom, boolean skipSideCheck) { - - for(DirPos revCon : connectsTo.connections) { - - if(revCon.getX() - revCon.getDir().offsetX == connectFrom.getX() && revCon.getY() - revCon.getDir().offsetY == connectFrom.getY() && revCon.getZ() - revCon.getDir().offsetZ == connectFrom.getZ() && (revCon.getDir() == connectFrom.getDir().getOpposite() || skipSideCheck)) { - return true; - } - } - - return false; + @Deprecated public static void createNode(World world, PowerNode node) { + UniNodespace.createNode(world, node); } - /** Links two nodes with different or potentially no networks */ - private static void connectToNode(PowerNode origin, PowerNode connection) { - - if(origin.hasValidNet() && connection.hasValidNet()) { // both nodes have nets, but the nets are different (previous assumption), join networks - if(origin.net.links.size() > connection.net.links.size()) { - origin.net.joinNetworks(connection.net); - } else { - connection.net.joinNetworks(origin.net); - } - } else if(!origin.hasValidNet() && connection.hasValidNet()) { // origin has no net, connection does, have origin join connection's net - connection.net.joinLink(origin); - } else if(origin.hasValidNet() && !connection.hasValidNet()) { // ...and vice versa - origin.net.joinLink(connection); - } - } - - public static class NodeWorld { - - /** Contains a map showing where each node is, a node is every spot that a cable exists at. - * Instead of the old proxy system, things like substation now create multiple nodes at their connection points */ - public HashMap nodes = new HashMap<>(); - - /** Adds a node at all its positions to the nodespace */ - public void pushNode(PowerNode node) { - for(BlockPos pos : node.positions) { - nodes.put(pos, node); - } - } - - /** Removes the specified node from all positions from nodespace */ - public void popNode(PowerNode node) { - if(node.net != null) node.net.destroy(); - for(BlockPos pos : node.positions) { - nodes.remove(pos); - node.expired = true; - } - } - - /** Grabs the node at one position, then removes it from all positions it occupies */ - public void popNode(BlockPos pos) { - PowerNode node = nodes.get(pos); - if(node != null) popNode(node); - } + @Deprecated public static void destroyNode(World world, int x, int y, int z) { + UniNodespace.destroyNode(world, x, y, z, THE_POWER_PROVIDER); } @NotableComments - public static class PowerNode { + public static class PowerNode extends GenNode { - public BlockPos[] positions; - public DirPos[] connections; - public PowerNetMK2 net; - public boolean expired = false; /** * Okay so here's the deal: The code has shit idiot brain fungus. I don't know why. I re-tested every part involved several times. * I don't know why. But for some reason, during neighbor checks, on certain arbitrary fucking places, the joining operation just fails. @@ -170,29 +49,14 @@ public static class PowerNode { public boolean recentlyChanged = true; public PowerNode(BlockPos... positions) { + super(THE_POWER_PROVIDER, positions); this.positions = positions; } + @Override public PowerNode setConnections(DirPos... connections) { - this.connections = connections; - return this; - } - - public PowerNode addConnection(DirPos connection) { - DirPos[] newCons = new DirPos[this.connections.length + 1]; - for(int i = 0; i < this.connections.length; i++) newCons[i] = this.connections[i]; - newCons[newCons.length - 1] = connection; - this.connections = newCons; + super.setConnections(connections); return this; } - - public boolean hasValidNet() { - return this.net != null && this.net.isValid(); - } - - public void setNet(PowerNetMK2 net) { - this.net = net; - this.recentlyChanged = true; - } } } diff --git a/src/main/java/api/hbm/energymk2/PowerNetMK2.java b/src/main/java/api/hbm/energymk2/PowerNetMK2.java index 4422cc138b..ff8043898b 100644 --- a/src/main/java/api/hbm/energymk2/PowerNetMK2.java +++ b/src/main/java/api/hbm/energymk2/PowerNetMK2.java @@ -2,124 +2,32 @@ import java.util.ArrayList; import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Set; +import com.hbm.uninos.NodeNet; import com.hbm.util.Tuple.Pair; import java.util.Map.Entry; -import java.util.Random; import api.hbm.energymk2.IEnergyReceiverMK2.ConnectionPriority; import api.hbm.energymk2.Nodespace.PowerNode; -public class PowerNetMK2 { - - public static Random rand = new Random(); - public boolean valid = true; - public Set links = new HashSet(); - - /** Maps all active subscribers to a timestamp, handy for handling timeouts. In a good system this shouldn't be necessary, but the previous system taught me to be cautious anyway */ - public HashMap receiverEntries = new HashMap(); - public HashMap providerEntries = new HashMap(); +/** + * Technically MK3 since it's now UNINOS compatible, although UNINOS was build out of 95% nodespace code + * + * @author hbm + */ +public class PowerNetMK2 extends NodeNet { public long energyTracker = 0L; - public PowerNetMK2() { - Nodespace.activePowerNets.add(this); - } - - /// SUBSCRIBER HANDLING /// - public boolean isSubscribed(IEnergyReceiverMK2 receiver) { - return this.receiverEntries.containsKey(receiver); - } - - public void addReceiver(IEnergyReceiverMK2 receiver) { - this.receiverEntries.put(receiver, System.currentTimeMillis()); - } - - public void removeReceiver(IEnergyReceiverMK2 receiver) { - this.receiverEntries.remove(receiver); - } - - /// PROVIDER HANDLING /// - public boolean isProvider(IEnergyProviderMK2 provider) { - return this.providerEntries.containsKey(provider); - } - - public void addProvider(IEnergyProviderMK2 provider) { - this.providerEntries.put(provider, System.currentTimeMillis()); - } - - public void removeProvider(IEnergyProviderMK2 provider) { - this.providerEntries.remove(provider); - } - - /// LINK JOINING /// - - /** Combines two networks into one */ - public void joinNetworks(PowerNetMK2 network) { - - if(network == this) return; //wtf?! - - List oldNodes = new ArrayList(network.links.size()); - oldNodes.addAll(network.links); // might prevent oddities related to joining - nvm it does nothing - - for(PowerNode conductor : oldNodes) forceJoinLink(conductor); - network.links.clear(); - - for(IEnergyReceiverMK2 connector : network.receiverEntries.keySet()) this.addReceiver(connector); - for(IEnergyProviderMK2 connector : network.providerEntries.keySet()) this.addProvider(connector); - network.destroy(); - } - - /** Adds the power node as part of this network's links */ - public PowerNetMK2 joinLink(PowerNode node) { - if(node.net != null) node.net.leaveLink(node); - return forceJoinLink(node); - } - - /** Adds the power node as part of this network's links, skips the part about removing it from existing networks */ - public PowerNetMK2 forceJoinLink(PowerNode node) { - this.links.add(node); - node.setNet(this); - return this; - } - - /** Removes the specified power node */ - public void leaveLink(PowerNode node) { - node.setNet(null); - this.links.remove(node); - } - - /// GENERAL POWER NET CONTROL /// - public void invalidate() { - this.valid = false; - Nodespace.activePowerNets.remove(this); - } - - public boolean isValid() { - return this.valid; - } - - public void destroy() { - this.invalidate(); - for(PowerNode link : this.links) if(link.net == this) link.setNet(null); - this.links.clear(); - this.receiverEntries.clear(); - this.providerEntries.clear(); - } - - public void resetEnergyTracker() { - this.energyTracker = 0; - } - protected static int timeout = 3_000; - public void transferPower() { + @Override public void resetTrackers() { this.energyTracker = 0; } + + @Override + public void update() { if(providerEntries.isEmpty()) return; if(receiverEntries.isEmpty()) return; @@ -170,7 +78,7 @@ public void transferPower() { toTransfer -= energyUsed; } - + this.energyTracker += energyUsed; long leftover = energyUsed; @@ -195,118 +103,6 @@ public void transferPower() { } } - @Deprecated public void transferPowerOld() { - - if(providerEntries.isEmpty()) return; - if(receiverEntries.isEmpty()) return; - - long timestamp = System.currentTimeMillis(); - long transferCap = 100_000_000_000_000_00L; // that ought to be enough - - long supply = 0; - long demand = 0; - long[] priorityDemand = new long[ConnectionPriority.values().length]; - - Iterator> provIt = providerEntries.entrySet().iterator(); - while(provIt.hasNext()) { - Entry entry = provIt.next(); - if(timestamp - entry.getValue() > timeout) { provIt.remove(); continue; } - supply += Math.min(entry.getKey().getPower(), entry.getKey().getProviderSpeed()); - } - - if(supply <= 0) return; - - Iterator> recIt = receiverEntries.entrySet().iterator(); - while(recIt.hasNext()) { - Entry entry = recIt.next(); - if(timestamp - entry.getValue() > timeout) { recIt.remove(); continue; } - long rec = Math.min(entry.getKey().getMaxPower() - entry.getKey().getPower(), entry.getKey().getReceiverSpeed()); - demand += rec; - for(int i = 0; i <= entry.getKey().getPriority().ordinal(); i++) priorityDemand[i] += rec; - } - - if(demand <= 0) return; - - long toTransfer = Math.min(supply, demand); - if(toTransfer > transferCap) toTransfer = transferCap; - if(toTransfer <= 0) return; - - List buffers = new ArrayList(); - List providers = new ArrayList(); - Set receiverSet = receiverEntries.keySet(); - for(IEnergyProviderMK2 provider : providerEntries.keySet()) { - if(receiverSet.contains(provider)) { - buffers.add(provider); - } else { - providers.add(provider); - } - } - providers.addAll(buffers); //makes buffers go last - List receivers = new ArrayList() {{ addAll(receiverSet); }}; - - receivers.sort(COMP); - - int maxIteration = 1000; - - //how much the current sender/receiver have already sent/received - long prevSrc = 0; - long prevDest = 0; - - while(!receivers.isEmpty() && !providers.isEmpty() && maxIteration > 0) { - maxIteration--; - - IEnergyProviderMK2 src = providers.get(0); - IEnergyReceiverMK2 dest = receivers.get(0); - - if(src.getPower() <= 0) { providers.remove(0); prevSrc = 0; continue; } - - if(src == dest) { // STALEMATE DETECTED - //if this happens, a buffer will waste both its share of transfer and receiving potential and do effectively nothing, essentially breaking - - //try if placing the conflicting provider at the end of the list does anything - //we do this first because providers have no priority, so we may shuffle those around as much as we want - if(providers.size() > 1) { - providers.add(providers.get(0)); - providers.remove(0); - prevSrc = 0; //this might cause slight issues due to the tracking being effectively lost while there still might be pending operations - continue; - } - //if that didn't work, try shifting the receiver by one place (to minimize priority breakage) - if(receivers.size() > 1) { - receivers.add(2, receivers.get(0)); - receivers.remove(0); - prevDest = 0; //ditto - continue; - } - - //if neither option could be performed, the only conclusion is that this buffer mode battery is alone in the power net, in which case: not my provlem - } - - long pd = priorityDemand[dest.getPriority().ordinal()]; - - long receiverShare = Math.min((long) Math.ceil((double) Math.min(dest.getMaxPower() - dest.getPower(), dest.getReceiverSpeed()) * (double) supply / (double) pd), dest.getReceiverSpeed()) - prevDest; - long providerShare = Math.min((long) Math.ceil((double) Math.min(src.getPower(), src.getProviderSpeed()) * (double) demand / (double) supply), src.getProviderSpeed()) - prevSrc; - - long toDrain = Math.min((long) (src.getPower()), providerShare); - long toFill = Math.min(dest.getMaxPower() - dest.getPower(), receiverShare); - - long finalTransfer = Math.min(toDrain, toFill); - if(toFill <= 0) { receivers.remove(0); prevDest = 0; continue; } - - finalTransfer -= dest.transferPower(finalTransfer); - src.usePower(finalTransfer); - - prevSrc += finalTransfer; - prevDest += finalTransfer; - - if(prevSrc >= src.getProviderSpeed()) { providers.remove(0); prevSrc = 0; continue; } - if(prevDest >= dest.getReceiverSpeed()) { receivers.remove(0); prevDest = 0; continue; } - - toTransfer -= finalTransfer; - this.energyTracker += finalTransfer; - } - } - public long sendPowerDiode(long power) { if(receiverEntries.isEmpty()) return power; diff --git a/src/main/java/com/hbm/main/ModEventHandler.java b/src/main/java/com/hbm/main/ModEventHandler.java index bd5ec48e4f..567ca1edcc 100644 --- a/src/main/java/com/hbm/main/ModEventHandler.java +++ b/src/main/java/com/hbm/main/ModEventHandler.java @@ -1,6 +1,5 @@ package com.hbm.main; -import api.hbm.energymk2.Nodespace; import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; import com.hbm.blocks.IStepTickReceiver; @@ -50,6 +49,7 @@ import com.hbm.tileentity.machine.rbmk.RBMKDials; import com.hbm.tileentity.network.RTTYSystem; import com.hbm.tileentity.network.RequestNetwork; +import com.hbm.uninos.UniNodespace; import com.hbm.util.*; import com.hbm.util.ArmorRegistry.HazardClass; import com.hbm.world.generator.TimedGenerator; @@ -1185,8 +1185,8 @@ public void onServerTick(TickEvent.ServerTickEvent event) { RTTYSystem.updateBroadcastQueue(); RequestNetwork.updateEntries(); TileEntityMachineRadarNT.updateSystem(); - Nodespace.updateNodespace(); - // bob i beg of you i need fluid nodespace :pray: + //Nodespace.updateNodespace(); + UniNodespace.updateNodespace(); } // There is an issue here somewhere... diff --git a/src/main/java/com/hbm/uninos/GenNode.java b/src/main/java/com/hbm/uninos/GenNode.java index b0337c1199..d65f163c1e 100644 --- a/src/main/java/com/hbm/uninos/GenNode.java +++ b/src/main/java/com/hbm/uninos/GenNode.java @@ -3,26 +3,26 @@ import com.hbm.util.fauxpointtwelve.BlockPos; import com.hbm.util.fauxpointtwelve.DirPos; -public class GenNode { +public class GenNode { public BlockPos[] positions; public DirPos[] connections; - public NodeNet net; + public N net; public boolean expired = false; public boolean recentlyChanged = true; public INetworkProvider networkProvider; - public GenNode(INetworkProvider provider, BlockPos... positions) { + public GenNode(INetworkProvider provider, BlockPos... positions) { this.networkProvider = provider; this.positions = positions; } - public GenNode setConnections(DirPos... connections) { + public GenNode setConnections(DirPos... connections) { this.connections = connections; return this; } - public GenNode addConnection(DirPos connection) { + public GenNode addConnection(DirPos connection) { DirPos[] newCons = new DirPos[this.connections.length + 1]; for(int i = 0; i < this.connections.length; i++) newCons[i] = this.connections[i]; newCons[newCons.length - 1] = connection; @@ -34,7 +34,7 @@ public boolean hasValidNet() { return this.net != null && this.net.isValid(); } - public void setNet(NodeNet net) { + public void setNet(N net) { this.net = net; this.recentlyChanged = true; } diff --git a/src/main/java/com/hbm/uninos/NodeNet.java b/src/main/java/com/hbm/uninos/NodeNet.java index 34e647196a..52fd122f15 100644 --- a/src/main/java/com/hbm/uninos/NodeNet.java +++ b/src/main/java/com/hbm/uninos/NodeNet.java @@ -7,60 +7,61 @@ import java.util.Random; import java.util.Set; -public abstract class NodeNet { +public abstract class NodeNet { + /** Global random for figuring things out like random leftover distribution */ public static Random rand = new Random(); public boolean valid = true; - public Set links = new HashSet(); + public Set links = new HashSet(); - public abstract HashMap receiverEntries(); - public abstract HashMap providerEntries(); + public HashMap receiverEntries = new HashMap(); + public HashMap providerEntries = new HashMap(); public NodeNet() { UniNodespace.activeNodeNets.add(this); } /// SUBSCRIBER HANDLING /// - public boolean isSubscribed(IGenReceiver receiver) { return this.receiverEntries().containsKey(receiver); } - public void addReceiver(IGenReceiver receiver) { this.receiverEntries().put(receiver, System.currentTimeMillis()); } - public void removeReceiver(IGenReceiver receiver) { this.receiverEntries().remove(receiver); } + public boolean isSubscribed(R receiver) { return this.receiverEntries.containsKey(receiver); } + public void addReceiver(R receiver) { this.receiverEntries.put(receiver, System.currentTimeMillis()); } + public void removeReceiver(R receiver) { this.receiverEntries.remove(receiver); } /// PROVIDER HANDLING /// - public boolean isProvider(IGenProvider provider) { return this.providerEntries().containsKey(provider); } - public void addProvider(IGenProvider provider) { this.providerEntries().put(provider, System.currentTimeMillis()); } - public void removeProvider(IGenProvider provider) { this.providerEntries().remove(provider); } + public boolean isProvider(P provider) { return this.providerEntries.containsKey(provider); } + public void addProvider(P provider) { this.providerEntries.put(provider, System.currentTimeMillis()); } + public void removeProvider(P provider) { this.providerEntries.remove(provider); } /** Combines two networks into one */ public void joinNetworks(NodeNet network) { if(network == this) return; - List oldNodes = new ArrayList(network.links.size()); + List oldNodes = new ArrayList(network.links.size()); oldNodes.addAll(network.links); - for(GenNode conductor : oldNodes) forceJoinLink(conductor); + for(L conductor : oldNodes) forceJoinLink(conductor); network.links.clear(); - for(IGenReceiver connector : network.receiverEntries().keySet()) this.addReceiver(connector); - for(IGenProvider connector : network.providerEntries().keySet()) this.addProvider(connector); + for(Object /*this is bullshit*/ connector : network.receiverEntries.keySet()) this.addReceiver((R) connector); + for(Object /*this is bullshit*/ connector : network.providerEntries.keySet()) this.addProvider((P) connector); network.destroy(); } /** Adds the node as part of this network's links */ - public NodeNet joinLink(GenNode node) { + public NodeNet joinLink(L node) { if(node.net != null) node.net.leaveLink(node); return forceJoinLink(node); } /** Adds the node as part of this network's links, skips the part about removing it from existing networks */ - public NodeNet forceJoinLink(GenNode node) { + public NodeNet forceJoinLink(L node) { this.links.add(node); node.setNet(this); return this; } /** Removes the specified node */ - public void leaveLink(GenNode node) { + public void leaveLink(L node) { node.setNet(null); this.links.remove(node); } @@ -75,7 +76,7 @@ public void destroy() { this.invalidate(); for(GenNode link : this.links) if(link.net == this) link.setNet(null); this.links.clear(); - this.receiverEntries().clear(); - this.providerEntries().clear(); + this.receiverEntries.clear(); + this.providerEntries.clear(); } } diff --git a/src/main/java/com/hbm/uninos/UniNodespace.java b/src/main/java/com/hbm/uninos/UniNodespace.java index aa92b1d1a1..ce4867386a 100644 --- a/src/main/java/com/hbm/uninos/UniNodespace.java +++ b/src/main/java/com/hbm/uninos/UniNodespace.java @@ -3,10 +3,13 @@ import java.util.HashMap; import java.util.HashSet; import java.util.Set; +import java.util.Map.Entry; import com.hbm.util.Tuple.Pair; import com.hbm.util.fauxpointtwelve.BlockPos; +import com.hbm.util.fauxpointtwelve.DirPos; +import net.minecraft.server.MinecraftServer; import net.minecraft.world.World; public class UniNodespace { @@ -36,6 +39,74 @@ public static void destroyNode(World world, int x, int y, int z, INetworkProvide } } + public static void updateNodespace() { + + for(World world : MinecraftServer.getServer().worldServers) { + UniNodeWorld nodeWorld = worlds.get(world); + + if(nodeWorld == null) continue; + + for(Entry, GenNode> entry : nodeWorld.nodes.entrySet()) { + GenNode node = entry.getValue(); + INetworkProvider provider = entry.getKey().getValue(); + if(!node.hasValidNet() || node.recentlyChanged) { + checkNodeConnection(world, node, provider); + node.recentlyChanged = false; + } + } + } + + updateNetworks(); + } + + private static void updateNetworks() { + + for(NodeNet net : activeNodeNets) net.resetTrackers(); //reset has to be done before everything else + for(NodeNet net : activeNodeNets) net.update(); + } + + /** Goes over each connection point of the given node, tries to find neighbor nodes and to join networks with them */ + private static void checkNodeConnection(World world, GenNode node, INetworkProvider provider) { + + for(DirPos con : node.connections) { + GenNode conNode = getNode(world, con.getX(), con.getY(), con.getZ(), provider); // get whatever neighbor node intersects with that connection + if(conNode != null) { // if there is a node at that place + if(conNode.hasValidNet() && conNode.net == node.net) continue; // if the net is valid and both nodes have the same net, skip + if(checkConnection(conNode, con, false)) { + connectToNode(node, conNode); + } + } + } + + if(node.net == null || !node.net.isValid()) provider.provideNetwork().joinLink(node); + } + + /** Checks if the node can be connected to given the DirPos, skipSideCheck will ignore the DirPos' direction value */ + public static boolean checkConnection(GenNode connectsTo, DirPos connectFrom, boolean skipSideCheck) { + for(DirPos revCon : connectsTo.connections) { + if(revCon.getX() - revCon.getDir().offsetX == connectFrom.getX() && revCon.getY() - revCon.getDir().offsetY == connectFrom.getY() && revCon.getZ() - revCon.getDir().offsetZ == connectFrom.getZ() && (revCon.getDir() == connectFrom.getDir().getOpposite() || skipSideCheck)) { + return true; + } + } + return false; + } + + /** Links two nodes with different or potentially no networks */ + private static void connectToNode(GenNode origin, GenNode connection) { + + if(origin.hasValidNet() && connection.hasValidNet()) { // both nodes have nets, but the nets are different (previous assumption), join networks + if(origin.net.links.size() > connection.net.links.size()) { + origin.net.joinNetworks(connection.net); + } else { + connection.net.joinNetworks(origin.net); + } + } else if(!origin.hasValidNet() && connection.hasValidNet()) { // origin has no net, connection does, have origin join connection's net + connection.net.joinLink(origin); + } else if(origin.hasValidNet() && !connection.hasValidNet()) { // ...and vice versa + origin.net.joinLink(connection); + } + } + public static class UniNodeWorld { public HashMap, GenNode> nodes = new HashMap(); diff --git a/src/main/java/com/hbm/uninos/networkproviders/PowerProvider.java b/src/main/java/com/hbm/uninos/networkproviders/PowerProvider.java index 86cf184039..0c12189918 100644 --- a/src/main/java/com/hbm/uninos/networkproviders/PowerProvider.java +++ b/src/main/java/com/hbm/uninos/networkproviders/PowerProvider.java @@ -1,12 +1,13 @@ package com.hbm.uninos.networkproviders; import com.hbm.uninos.INetworkProvider; -import com.hbm.uninos.networks.PowerNetwork; -public class PowerProvider implements INetworkProvider { +import api.hbm.energymk2.PowerNetMK2; + +public class PowerProvider implements INetworkProvider { @Override - public PowerNetwork provideNetwork() { - return new PowerNetwork(); + public PowerNetMK2 provideNetwork() { + return new PowerNetMK2(); } } diff --git a/src/main/java/com/hbm/uninos/networks/PowerNetwork.java b/src/main/java/com/hbm/uninos/networks/PowerNetwork.java deleted file mode 100644 index 9c68b0cdaf..0000000000 --- a/src/main/java/com/hbm/uninos/networks/PowerNetwork.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.hbm.uninos.networks; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map.Entry; - -import com.hbm.uninos.NodeNet; -import com.hbm.util.Tuple.Pair; - -import api.hbm.energymk2.IEnergyProviderMK2; -import api.hbm.energymk2.IEnergyReceiverMK2; -import api.hbm.energymk2.IEnergyReceiverMK2.ConnectionPriority; - -public class PowerNetwork extends NodeNet { - - /* - * the original idea was to have every part have a generic type so that once you get down to the level of nodes, you can - * still easily create new networks using the generic type. however: - * - having generics everywhere means that some overrides don't work due to "not being castable" (my ass) - * - most of the time, having generics there didn't really do anything, since the interface is already universally usable, and the type that is provided doesn't actually matter - * - for any case where network type does matter, any node handling instance (cable TEs for example) can just do handling separately, worst case it's just one extra cast - * my balls hurt - */ - - public HashMap receiverEntries = new HashMap(); - public HashMap providerEntries = new HashMap(); - - public long energyTracker = 0L; - - @Override - public HashMap receiverEntries() { - return receiverEntries; - // generic type erasure seems susipcious here - this either works because the types should be castable anyway, - // or this doesn't work because the compiler has an aneurysm and dies instantly - // technically, generics are obliterated when compiling, and the types are assignable, so i see no issue, - // but then again, HashMap *technically* isn't castable to HashMap, and the compiler might scream about it - } - - @Override - public HashMap providerEntries() { - return providerEntries; - } - - protected static int timeout = 3_000; - - @Override public void resetTrackers() { this.energyTracker = 0; } - - @Override - public void update() { - - if(providerEntries.isEmpty()) return; - if(receiverEntries.isEmpty()) return; - - long timestamp = System.currentTimeMillis(); - - List> providers = new ArrayList(); - long powerAvailable = 0; - - Iterator> provIt = providerEntries.entrySet().iterator(); - while(provIt.hasNext()) { - Entry entry = provIt.next(); - if(timestamp - entry.getValue() > timeout) { provIt.remove(); continue; } - long src = Math.min(entry.getKey().getPower(), entry.getKey().getProviderSpeed()); - providers.add(new Pair(entry.getKey(), src)); - powerAvailable += src; - } - - List>[] receivers = new ArrayList[ConnectionPriority.values().length]; - for(int i = 0; i < receivers.length; i++) receivers[i] = new ArrayList(); - long[] demand = new long[ConnectionPriority.values().length]; - long totalDemand = 0; - - Iterator> recIt = receiverEntries.entrySet().iterator(); - - while(recIt.hasNext()) { - Entry entry = recIt.next(); - if(timestamp - entry.getValue() > timeout) { recIt.remove(); continue; } - long rec = Math.min(entry.getKey().getMaxPower() - entry.getKey().getPower(), entry.getKey().getReceiverSpeed()); - int p = entry.getKey().getPriority().ordinal(); - receivers[p].add(new Pair(entry.getKey(), rec)); - demand[p] += rec; - totalDemand += rec; - } - - long toTransfer = Math.min(powerAvailable, totalDemand); - long energyUsed = 0; - - for(int i = ConnectionPriority.values().length - 1; i >= 0; i--) { - List> list = receivers[i]; - long priorityDemand = demand[i]; - - for(Pair entry : list) { - double weight = (double) entry.getValue() / (double) (priorityDemand); - long toSend = (long) Math.max(toTransfer * weight, 0D); - energyUsed += (toSend - entry.getKey().transferPower(toSend)); //leftovers are subtracted from the intended amount to use up - } - - toTransfer -= energyUsed; - } - - this.energyTracker += energyUsed; - long leftover = energyUsed; - - for(Pair entry : providers) { - double weight = (double) entry.getValue() / (double) powerAvailable; - long toUse = (long) Math.max(energyUsed * weight, 0D); - entry.getKey().usePower(toUse); - leftover -= toUse; - } - - //rounding error compensation, detects surplus that hasn't been used and removes it from random providers - int iterationsLeft = 100; // whiles without emergency brakes are a bad idea - while(iterationsLeft > 0 && leftover > 0 && providers.size() > 0) { - iterationsLeft--; - - Pair selected = providers.get(rand.nextInt(providers.size())); - IEnergyProviderMK2 scapegoat = selected.getKey(); - - long toUse = Math.min(leftover, scapegoat.getPower()); - scapegoat.usePower(toUse); - leftover -= toUse; - } - } -}