diff --git a/src/main/java/api/hbm/energymk2/IEnergyConnectorMK2.java b/src/main/java/api/hbm/energymk2/IEnergyConnectorMK2.java index 79f678246..2245f57ff 100644 --- a/src/main/java/api/hbm/energymk2/IEnergyConnectorMK2.java +++ b/src/main/java/api/hbm/energymk2/IEnergyConnectorMK2.java @@ -23,6 +23,10 @@ public interface IEnergyConnectorMK2 extends ILoadedTile { public long getPower(); public long getMaxPower(); + public default long getConnectionSpeed() { + return this.getMaxPower(); + } + public static final boolean particleDebug = false; public default Vec3 getDebugParticlePosMK2() { diff --git a/src/main/java/api/hbm/energymk2/IEnergyProviderMK2.java b/src/main/java/api/hbm/energymk2/IEnergyProviderMK2.java index b8a05e0ae..d45feb6f9 100644 --- a/src/main/java/api/hbm/energymk2/IEnergyProviderMK2.java +++ b/src/main/java/api/hbm/energymk2/IEnergyProviderMK2.java @@ -11,6 +11,11 @@ import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; public interface IEnergyProviderMK2 extends IEnergyConnectorMK2 { + + /** Uses up available power, default implementation has no sanity checking, make sure that the requested power is lequal to the current power */ + public default void usePower(long power) { + this.setPower(this.getPower() - power); + } public void setPower(long power); diff --git a/src/main/java/api/hbm/energymk2/IEnergyReceiverMK2.java b/src/main/java/api/hbm/energymk2/IEnergyReceiverMK2.java index d68837692..dfb32f097 100644 --- a/src/main/java/api/hbm/energymk2/IEnergyReceiverMK2.java +++ b/src/main/java/api/hbm/energymk2/IEnergyReceiverMK2.java @@ -70,13 +70,36 @@ public interface IEnergyReceiverMK2 extends IEnergyConnectorMK2 { } } + /** + * Project MKUltra was an illegal human experiments program designed and undertaken by the U.S. Central Intelligence Agency (CIA) + * to develop procedures and identify drugs that could be used during interrogations to weaken people and force confessions through + * brainwashing and psychological torture. It began in 1953 and was halted in 1973. MKUltra used numerous methods to manipulate + * its subjects' mental states and brain functions, such as the covert administration of high doses of psychoactive drugs (especially LSD) + * and other chemicals without the subjects' consent, electroshocks, hypnosis, sensory deprivation, isolation, verbal and sexual + * abuse, and other forms of torture. + * MKUltra was preceded by Project Artichoke. It was organized through the CIA's Office of Scientific Intelligence and coordinated + * with the United States Army Biological Warfare Laboratories. The program engaged in illegal activities, including the + * use of U.S. and Canadian citizens as unwitting test subjects. MKUltra's scope was broad, with activities carried + * out under the guise of research at more than 80 institutions aside from the military, including colleges and universities, + * hospitals, prisons, and pharmaceutical companies. The CIA operated using front organizations, although some top officials at these + * institutions were aware of the CIA's involvement. + * MKUltra was revealed to the public in 1975 by the Church Committee of the United States Congress and Gerald Ford's United States + * President's Commission on CIA activities within the United States (the Rockefeller Commission). Investigative efforts were hampered + * by CIA Director Richard Helms's order that all MKUltra files be destroyed in 1973; the Church Committee and Rockefeller Commission + * investigations relied on the sworn testimony of direct participants and on the small number of documents that survived Helms's order. + * In 1977, a Freedom of Information Act request uncovered a cache of 20,000 documents relating to MKUltra, which led to Senate hearings. + * Some surviving information about MKUltra was declassified in 2001. + * */ public default ConnectionPriority getPriority() { return ConnectionPriority.NORMAL; } + /** More is better-er */ public enum ConnectionPriority { + LOWEST, LOW, NORMAL, - HIGH + HIGH, + HIGHEST } } diff --git a/src/main/java/api/hbm/energymk2/Nodespace.java b/src/main/java/api/hbm/energymk2/Nodespace.java index 2a9f4c23a..bdf7ce105 100644 --- a/src/main/java/api/hbm/energymk2/Nodespace.java +++ b/src/main/java/api/hbm/energymk2/Nodespace.java @@ -1,18 +1,16 @@ package api.hbm.energymk2; -import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map.Entry; import java.util.Set; -import com.hbm.packet.AuxParticlePacketNT; -import com.hbm.packet.PacketDispatcher; import com.hbm.util.fauxpointtwelve.BlockPos; import com.hbm.util.fauxpointtwelve.DirPos; -import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.server.MinecraftServer; import net.minecraft.world.World; @@ -46,16 +44,6 @@ public class Nodespace { PowerNode node = getNode(world, x, y, z); if(node != null) { worlds.get(world).popNode(node); - //markNeigbors(world, node); - } - } - - /** Grabs all neighbor nodes from the given node's connection points and removes them from the network entirely, forcing a hard reconnect */ - @Deprecated private static void markNeigbors(World world, PowerNode node) { - - for(DirPos con : node.connections) { - PowerNode conNode = getNode(world, con.getX(), con.getY(), con.getZ()); - if(conNode != null && conNode.hasValidNet()) conNode.net.leaveLink(conNode); } } @@ -95,22 +83,64 @@ public class Nodespace { int timeout = 3_000; for(PowerNetMK2 net : activePowerNets) { + + if(net.providerEntries.isEmpty()) continue; + if(net.receiverEntries.isEmpty()) continue; long timestamp = System.currentTimeMillis(); - - //TODO: start over, impose a per-tick transfer limit in order to avoid bigints + long transferCap = 100_000_000_000_000_00L; // that ought to be enough - BigInteger supply = BigInteger.valueOf(0); - BigInteger demand = BigInteger.valueOf(0); + long supply = 0; + long demand = 0; for(Entry entry : net.providerEntries.entrySet()) { IEnergyProviderMK2 provider = entry.getKey(); - if(provider.isLoaded() && timestamp - entry.getValue() < timeout) supply = supply.add(BigInteger.valueOf(provider.getPower())); + if(provider.isLoaded() && timestamp - entry.getValue() < timeout) supply += Math.min(provider.getPower(), provider.getConnectionSpeed()); } for(Entry entry : net.receiverEntries.entrySet()) { IEnergyReceiverMK2 receiver = entry.getKey(); - if(receiver.isLoaded() && timestamp - entry.getValue() < timeout) demand = demand.add(BigInteger.valueOf(receiver.getMaxPower() - receiver.getPower())); + if(receiver.isLoaded() && timestamp - entry.getValue() < timeout) demand += Math.min(receiver.getMaxPower() - receiver.getPower(), receiver.getConnectionSpeed()); + } + + double drainScale = 1D; + + if(supply > demand) { + drainScale = (double) demand / (double) supply; + } + + long toTransfer = Math.min(supply, demand); + if(toTransfer > transferCap) toTransfer = transferCap; + if(toTransfer <= 0) continue; + + //TODO: add caching for the ordered lists + List providers = new ArrayList() {{ addAll(net.providerEntries.keySet()); }}; + List receivers = new ArrayList() {{ addAll(net.receiverEntries.keySet()); }}; + receivers.sort(COMP); + + int maxIteration = 1000; + //TODO: ok this implementation is shit but we can clutch this. add a var for the current receiver index and shift that after each transfer so that transfers are spaced out instead of shit getting priority treatment + while(!receivers.isEmpty() && maxIteration > 0) { + maxIteration--; + + IEnergyProviderMK2 src = providers.get(0); + IEnergyReceiverMK2 dest = receivers.get(0); + long toDrain = Math.min((long) (src.getPower() * drainScale), src.getConnectionSpeed()); + long toFill = Math.min(dest.getMaxPower() - dest.getPower(), dest.getConnectionSpeed()); + long finalTransfer = Math.min(toDrain, toFill); + if(finalTransfer <= 0) { + receivers.remove(0); + continue; + } + + finalTransfer -= dest.transferPower(finalTransfer); + src.usePower(finalTransfer); + + toTransfer -= finalTransfer; + if(finalTransfer <= 0) { + receivers.remove(0); + continue; + } } } } @@ -222,4 +252,14 @@ public class Nodespace { this.recentlyChanged = true; } } + + public static final ReceiverComparator COMP = new ReceiverComparator(); + + public static class ReceiverComparator implements Comparator { + + @Override + public int compare(IEnergyReceiverMK2 o1, IEnergyReceiverMK2 o2) { + return o2.getPriority().ordinal() - o1.getPriority().ordinal(); + } + } }