diff --git a/src/main/java/techreborn/Core.java b/src/main/java/techreborn/Core.java index d4b78508b..4f08418b7 100644 --- a/src/main/java/techreborn/Core.java +++ b/src/main/java/techreborn/Core.java @@ -45,6 +45,7 @@ import techreborn.init.RecipeCompact; import techreborn.lib.ModInfo; import techreborn.packets.PacketAesu; import techreborn.packets.PacketIdsu; +import techreborn.power.PowerTickEvent; import techreborn.proxies.CommonProxy; import techreborn.tiles.idsu.IDSUManager; import techreborn.world.TROreGen; diff --git a/src/main/java/techreborn/events/TRTickHandler.java b/src/main/java/techreborn/events/TRTickHandler.java index 084a46325..140daa61e 100644 --- a/src/main/java/techreborn/events/TRTickHandler.java +++ b/src/main/java/techreborn/events/TRTickHandler.java @@ -3,15 +3,23 @@ package techreborn.events; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.potion.Potion; +import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import techreborn.init.ModItems; +import techreborn.power.PowerTickEvent; +import techreborn.power.TRPowerNet; + +import java.util.ArrayList; +import java.util.List; public class TRTickHandler { public Item previouslyWearing; + public static List oldNets = new ArrayList<>(); + @SubscribeEvent(priority = EventPriority.NORMAL, receiveCanceled = true) public void onPlayerTick(TickEvent.PlayerTickEvent e) { EntityPlayer player = e.player; @@ -24,5 +32,16 @@ public class TRTickHandler { previouslyWearing = chestslot; } + @SubscribeEvent + public void worldTick(TickEvent.WorldTickEvent e) { + if(!oldNets.isEmpty()){ + for(TRPowerNet powerNet : oldNets){ + MinecraftForge.EVENT_BUS.unregister(powerNet); + } + oldNets.clear(); + } + if(!e.world.isRemote) + MinecraftForge.EVENT_BUS.post(new PowerTickEvent()); + } } diff --git a/src/main/java/techreborn/parts/CableMultipart.java b/src/main/java/techreborn/parts/CableMultipart.java index 119d7e016..b41d157a9 100644 --- a/src/main/java/techreborn/parts/CableMultipart.java +++ b/src/main/java/techreborn/parts/CableMultipart.java @@ -25,6 +25,7 @@ import net.minecraftforge.common.property.Properties; import reborncore.api.power.IEnergyInterfaceTile; import reborncore.common.misc.Functions; import reborncore.common.misc.vecmath.Vecs3dCube; +import techreborn.power.TRPowerNet; import techreborn.utils.damageSources.ElectrialShockSource; import java.util.*; @@ -169,6 +170,12 @@ public abstract class CableMultipart extends Multipart implements IOccludingPart if (cableMultipart != null && cableMultipart.internalShouldConnectTo(dir.getOpposite())) { return true; } + } else { + TileEntity tile = getNeighbourTile(dir); + + if (tile instanceof IEnergyInterfaceTile) { + return true; + } } } return false; @@ -186,13 +193,9 @@ public abstract class CableMultipart extends Multipart implements IOccludingPart return false; } - if (getPartFromWorld(getWorld(), getPos().offset(dir), dir.getOpposite()) != null) { - return true; - } + CableMultipart cableMultipart = getPartFromWorld(getWorld(), getPos().offset(dir), dir.getOpposite()); - TileEntity tile = getNeighbourTile(dir); - - if (tile instanceof IEnergyInterfaceTile) { + if (cableMultipart != null && cableMultipart.getCableType() == getCableType()) { return true; } return false; @@ -229,6 +232,9 @@ public abstract class CableMultipart extends Multipart implements IOccludingPart checkConnectedSides(); } } + if (network == null) { + this.findAndJoinNetwork(getWorld(), getPos()); + } } @Override @@ -300,4 +306,56 @@ public abstract class CableMultipart extends Multipart implements IOccludingPart public ItemStack getPickBlock(EntityPlayer player, PartMOP hit) { return new ItemStack(TechRebornParts.cables, 1, getCableType().ordinal()); } + + private TRPowerNet network; + + public final void findAndJoinNetwork(World world, BlockPos pos) { + network = new TRPowerNet(); + network.setIOLimit(this.getCableType().transferRate); + network.addElement(this); + for(EnumFacing dir : EnumFacing.VALUES){ + CableMultipart cableMultipart = getPartFromWorld(getWorld(), getPos().offset(dir), dir); + if(cableMultipart != null && cableMultipart.getCableType() == getCableType()){ + TRPowerNet net = cableMultipart.getNetwork(); + if(net != null){ + net.merge(network); + } + } + TileEntity te = getNeighbourTile(dir); + if(te != null && te instanceof IEnergyInterfaceTile){ + if(((IEnergyInterfaceTile) te).canAcceptEnergy(dir) || ((IEnergyInterfaceTile) te).canProvideEnergy(dir)){ + network.addConnection((IEnergyInterfaceTile) te, dir.getOpposite()); + } + } + } + } + + public final TRPowerNet getNetwork() { + return network; + } + + public final void setNetwork(TRPowerNet n) { + if (n == null) { + } else { + network = n; + network.addElement(this); + } + } + + public final void removeFromNetwork() { + if (network == null) { + } else + network.removeElement(this); + } + + public final void rebuildNetwork() { + this.removeFromNetwork(); + this.resetNetwork(); + this.findAndJoinNetwork(getWorld(), getPos()); + } + + public final void resetNetwork() { + network = null; + } + } diff --git a/src/main/java/techreborn/power/PowerTickEvent.java b/src/main/java/techreborn/power/PowerTickEvent.java new file mode 100644 index 000000000..dd83502d0 --- /dev/null +++ b/src/main/java/techreborn/power/PowerTickEvent.java @@ -0,0 +1,9 @@ +package techreborn.power; + + +import net.minecraftforge.fml.common.eventhandler.Event; + +public class PowerTickEvent extends Event { + public PowerTickEvent() { + } +} diff --git a/src/main/java/techreborn/power/TRPowerNet.java b/src/main/java/techreborn/power/TRPowerNet.java new file mode 100644 index 000000000..bccc24c95 --- /dev/null +++ b/src/main/java/techreborn/power/TRPowerNet.java @@ -0,0 +1,272 @@ +package techreborn.power; + +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import reborncore.api.power.IEnergyInterfaceTile; +import techreborn.parts.CableMultipart; + +import java.util.ArrayList; + +public class TRPowerNet { + int i = 0; + private ArrayList cables = new ArrayList(); + private ArrayList endpoints = new ArrayList(); + private int energy = 0; + private int networkLimit = 1000; + + public TRPowerNet() { + MinecraftForge.EVENT_BUS.register(this); + } + + public int getIOLimit() { + return networkLimit; + } + + public void setIOLimit(int limit) { + if (networkLimit != limit) { + networkLimit = limit; + for (int i = 0; i < cables.size(); i++) { + CableMultipart cable = cables.get(i); + if (cable.getCableType().transferRate!= networkLimit) { + networkLimit = cable.getCableType().transferRate; + } + } + } + } + + @SubscribeEvent + public void tick(PowerTickEvent evt) { +// if (i > 10) { +// for (CableMultipart modCablePart : ModCablePart.partsInWorld) { +// if (!ModPartUtils.hasCable(modCablePart.world, modCablePart.location)) { +// ModCablePart.partsInWorld.remove(modCablePart); +// } +// } +// } + + if (!cables.isEmpty()) { + ArrayList collectibles = new ArrayList(); + ArrayList insertibles = new ArrayList(); + int maxCanPush = energy; + for (int i = 0; i < endpoints.size(); i++) { + EnergyHandler ei = endpoints.get(i); + maxCanPush += ei.getTotalInsertible(); + if (ei.isCollectible()) { + collectibles.add(ei); + } + if (ei.isInsertible()) { + insertibles.add(ei); + } + } + + maxCanPush = Math.min(this.getIOLimit(), maxCanPush); + + for(EnergyHandler handler : collectibles){ + int space = maxCanPush - energy; + energy += handler.collectEnergy(space); + } + + for(EnergyHandler handler : insertibles){ + int add = Math.min(energy, 1 + energy / insertibles.size()); + energy -= handler.addEnergy(add); + } + System.out.println(energy); + } + } + + public void addElement(CableMultipart te) { + if (!cables.contains(te)) { + cables.add(te); + if (te.getCableType().transferRate > 0 && te.getCableType().transferRate != networkLimit) { + this.setIOLimit(Math.min(te.getCableType().transferRate, this.getIOLimit())); + } + } + } + + public void removeElement(CableMultipart te) { + cables.remove(te); + this.rebuild(); + } + + private void rebuild() { + System.out.println("Remapping RF network " + this); + for (int i = 0; i < cables.size(); i++) { + CableMultipart te = cables.get(i); + te.findAndJoinNetwork(te.getWorld(), te.getPos()); + } + this.clear(true); + } + + public void addConnection(IEnergyInterfaceTile ih, EnumFacing dir) { + if (ih instanceof CableMultipart) + return; + EnergyHandler has = this.getHandleFrom(ih); + if (has == null) { + endpoints.add(new EnergyHandler(ih, dir)); + } else { + has.addSide(dir); + } + } + + public void merge(TRPowerNet n) { + if (n != this) { + ArrayList li = new ArrayList(); + for (int i = 0; i < n.cables.size(); i++) { + CableMultipart wire = n.cables.get(i); + li.add(wire); + } + for (int i = 0; i < n.endpoints.size(); i++) { + EnergyHandler ei = n.endpoints.get(i); + EnergyHandler has = this.getHandleFrom(ei.tile); + if (has == null) { + endpoints.add(ei); + } else { + has.merge(ei); + } + } + n.clear(false); + for (int i = 0; i < li.size(); i++) { + CableMultipart wire = li.get(i); + wire.setNetwork(this); + } + if (n.getIOLimit() != 0 && n.networkLimit != networkLimit) + this.setIOLimit(Math.min(n.getIOLimit(), this.getIOLimit())); + } + } + + private EnergyHandler getHandleFrom(IEnergyInterfaceTile tile) { + for (int i = 0; i < endpoints.size(); i++) { + EnergyHandler ei = endpoints.get(i); + if (ei.contains(tile)) + return ei; + } + return null; + } + + private void clear(boolean clearTiles) { + if (clearTiles) { + for (int i = 0; i < cables.size(); i++) { + cables.get(i).resetNetwork(); + } + } + + cables.clear(); + endpoints.clear(); + energy = 0; + + try { + MinecraftForge.EVENT_BUS.unregister(this); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public String toString() { + return cables.size() + ": " + endpoints.toString(); + } + + public int drainEnergy(int maxReceive, boolean simulate) { + maxReceive = Math.min(maxReceive, this.getIOLimit()); + int drain = Math.min(maxReceive, energy); + if (!simulate) + energy -= drain; + return drain; + } + + public int addEnergy(int maxAdd, boolean simulate) { + if (energy >= this.getIOLimit()) + return 0; + maxAdd = Math.min(this.getIOLimit(), maxAdd); + if (!simulate) + energy += maxAdd; + return maxAdd; + } + + private static class EnergyHandler { + private final IEnergyInterfaceTile tile; + private final ArrayList sides = new ArrayList(); + + private EnergyHandler(IEnergyInterfaceTile ih, EnumFacing... dirs) { + tile = ih; + for (int i = 0; i < dirs.length; i++) { + this.addSide(dirs[i]); + } + } + + public boolean isInsertible() { + return this.getTotalInsertible() > 0; + } + + public boolean isCollectible() { + return this.getTotalCollectible() > 0; + } + + public boolean contains(IEnergyInterfaceTile tile) { + return tile == this.tile; + } + + public void addSide(EnumFacing dir) { + if (!sides.contains(dir)) + sides.add(dir); + } + + public void merge(EnergyHandler ei) { + for (int i = 0; i < ei.sides.size(); i++) { + this.addSide(ei.sides.get(i)); + } + } + + public int collectEnergy(int max) { + int total = 0; + for (int i = 0; i < sides.size(); i++) { + EnumFacing dir = sides.get(i); + if (tile.canProvideEnergy(dir)) { + int collect = max - total; + total += tile.useEnergy(collect, false); + } + } + return total; + } + + public int addEnergy(int max) { + int total = 0; + for (int i = 0; i < sides.size(); i++) { + EnumFacing dir = sides.get(i); + if (tile.canAcceptEnergy(dir)) { + int add = max - total; + total += tile.addEnergy(add, false); + } + } + return total; + } + + public int getTotalCollectible() { + int total = 0; + for (int i = 0; i < sides.size(); i++) { + EnumFacing dir = sides.get(i); + if (tile.canProvideEnergy(dir)) { + total += tile.useEnergy(Integer.MAX_VALUE, true); + } + } + return total; + } + + public int getTotalInsertible() { + int total = 0; + for (int i = 0; i < sides.size(); i++) { + EnumFacing dir = sides.get(i); + if (tile.canAcceptEnergy(dir)) { + total += tile.addEnergy(Integer.MAX_VALUE, true); + } + } + return total; + } + + @Override + public String toString() { + return tile + " @ " + sides; + } + } +}