Advertisement
znix

EnetBridge

Dec 4th, 2016
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 13.75 KB | None | 0 0
  1. public class TrackingList<T> extends AbstractList<T> {
  2.     public TrackingList(List<T> parent) {
  3.         this.parent = parent;
  4.  
  5.         added.addAll(parent);
  6.     }
  7.  
  8.     @Override
  9.     public T get(int index) {
  10.         return parent.get(index);
  11.     }
  12.  
  13.     @Override
  14.     public int size() {
  15.         return parent.size();
  16.     }
  17.  
  18.     @Override
  19.     public T set(int index, T element) {
  20.         added.add(element);
  21.         T ret = parent.set(index, element);
  22.         if (ret != null) removed.add(ret);
  23.  
  24.         return ret;
  25.     }
  26.  
  27.     @Override
  28.     public void add(int index, T element) {
  29.         parent.add(index, element);
  30.         added.add(element);
  31.     }
  32.  
  33.     @Override
  34.     public T remove(int index) {
  35.         T ret = parent.remove(index);
  36.         if (ret != null) removed.add(ret);
  37.  
  38.         return ret;
  39.     }
  40.  
  41.     public List<T> getAdded() {
  42.         return added;
  43.     }
  44.  
  45.     public List<T> getRemoved() {
  46.         return removed;
  47.     }
  48.  
  49.     private final List<T> parent;
  50.     private final List<T> added = new ArrayList<T>();
  51.     private final List<T> removed = new ArrayList<T>();
  52. }
  53.  
  54.  
  55.  
  56. public class MainLogic {
  57.     public static void onWorldTickEnd(World world) {
  58.         if (world == null) throw new NullPointerException("tick for null world");
  59.  
  60.         WorldData worldData = getWorldData(world);
  61.  
  62.         // remove delegates for removed tes
  63.         for (TileEntity te : worldData.trackingList.getRemoved()) {
  64.             TileEntityDelegate delegate = worldData.enetDelegates.remove(te);
  65.  
  66.             if (delegate != null) {
  67.                 MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(delegate));
  68.             }
  69.         }
  70.  
  71.         worldData.trackingList.getRemoved().clear();
  72.  
  73.         // create new delegates from pending tes
  74.         for (TileEntity te : worldData.pendingEnetDelegates) {
  75.             if (te.getWorldObj() == world &&
  76.                     EnergyNet.instance.getTileEntity(world, te.xCoord, te.yCoord, te.zCoord) == null) {
  77.                 TileEntityDelegate enetDelegate = RfBlockDelegate.create(te);
  78.  
  79.                 if (enetDelegate == null) enetDelegate = ChargeBlockDelegate.create(te);
  80.  
  81.                 if (enetDelegate != null) {
  82.                     TileEntityDelegate prev = worldData.enetDelegates.put(te, enetDelegate);
  83.                     assert prev == null;
  84.                     MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(enetDelegate));
  85.                 }
  86.             }
  87.         }
  88.  
  89.         worldData.pendingEnetDelegates.clear();
  90.  
  91.         // fill pending tes from added tes
  92.         for (TileEntity te : worldData.trackingList.getAdded()) {
  93.             if (RfBlockDelegate.isApplicable(te) ||
  94.                     ChargeBlockDelegate.isApplicable(te)) {
  95.                 if (EnergyNet.instance.getTileEntity(world, te.xCoord, te.yCoord, te.zCoord) == null) {
  96.                     worldData.pendingEnetDelegates.add(te);
  97.                 }
  98.             }
  99.         }
  100.  
  101.         worldData.trackingList.getAdded().clear();
  102.  
  103.         // tick delegates
  104.         for (TileEntityDelegate delegate : worldData.enetDelegates.values()) {
  105.             delegate.tick();
  106.         }
  107.     }
  108.  
  109.     protected static void setTrackingList(World world, TrackingList<TileEntity> tl) {
  110.         getWorldData(world).trackingList = tl;
  111.     }
  112.  
  113.     protected static void onWorldUnload(World world) {
  114.         worldData.remove(world);
  115.     }
  116.  
  117.  
  118.     private static WorldData getWorldData(World world) {
  119.         WorldData ret = worldData.get(world);
  120.  
  121.         if (ret == null) {
  122.             ret = new WorldData();
  123.             worldData.put(world, ret);
  124.         }
  125.  
  126.         return ret;
  127.     }
  128.  
  129.  
  130.     private static class WorldData {
  131.         final Map<TileEntity, TileEntityDelegate> enetDelegates = new HashMap<TileEntity, TileEntityDelegate>();
  132.         final List<TileEntity> pendingEnetDelegates = new ArrayList<TileEntity>();
  133.         TrackingList<TileEntity> trackingList;
  134.     }
  135.  
  136.     private static final Map<World, WorldData> worldData = new WeakHashMap<World, WorldData>();
  137. }
  138.  
  139.  
  140.  
  141. public class EventCallback {
  142.     public static void load() {
  143.         if (EnetBridge.getEnableTileEntityAdaption() &&
  144.                 (EnetBridge.hasRf() || EnetBridge.hasCharge())) {
  145.             EventCallback cb = new EventCallback();
  146.  
  147.             FMLCommonHandler.instance().bus().register(cb);
  148.             MinecraftForge.EVENT_BUS.register(cb);
  149.         }
  150.     }
  151.  
  152.     private EventCallback() {
  153.     }
  154.  
  155.     @SubscribeEvent(priority = EventPriority.HIGH)
  156.     public void onWorldTick(TickEvent.WorldTickEvent event) {
  157.         if (event.phase != Phase.END) return;
  158.  
  159.         MainLogic.onWorldTickEnd(event.world);
  160.     }
  161.  
  162.     @SubscribeEvent
  163.     public void onWorldLoad(WorldEvent.Load event) {
  164.         if (FMLCommonHandler.instance().getEffectiveSide().isServer()) {
  165.             @SuppressWarnings("unchecked")
  166.             TrackingList<TileEntity> tl = new TrackingList<TileEntity>(event.world.loadedTileEntityList);
  167.             event.world.loadedTileEntityList = tl;
  168.             MainLogic.setTrackingList(event.world, tl);
  169.         }
  170.     }
  171.  
  172.     @SubscribeEvent
  173.     public void onWorldUnload(WorldEvent.Unload event) {
  174.         MainLogic.onWorldUnload(event.world);
  175.     }
  176. }
  177.  
  178.  
  179. public abstract class TileEntityDelegate extends TileEntity  implements IEnergySink, IEnergySource {
  180.     public TileEntityDelegate(TileEntity parent) {
  181.         worldObj = parent.getWorldObj();
  182.         xCoord = parent.xCoord;
  183.         yCoord = parent.yCoord;
  184.         zCoord = parent.zCoord;
  185.     }
  186.  
  187.     public abstract void tick();
  188.  
  189.     @Override
  190.     public int getSinkTier() {
  191.         return Integer.MAX_VALUE;
  192.     }
  193.  
  194.     @Override
  195.     public int getSourceTier() {
  196.         double energy = getOfferedEnergy();
  197.  
  198.         return energy > 0 ? EnergyNet.instance.getTierFromPower(energy) : 1;
  199.     }
  200. }
  201.  
  202.  
  203. public class RfItemHandler implements IBackupElectricItemManager {
  204.     public static boolean load() {
  205.         try {
  206.             ElectricItem.registerBackupManager(new RfItemHandler());
  207.             return true;
  208.         } catch (Exception e) {
  209.             EnetBridge.log.warn("RF item handler init error: {}.", e.getMessage());
  210.             return false;
  211.         }
  212.     }
  213.  
  214.  
  215.     private RfItemHandler() {
  216.     }
  217.  
  218.     @Override
  219.     public boolean use(ItemStack stack, double amount, EntityLivingBase entity) {
  220.         return ElectricItem.rawManager.use(stack, amount, entity);
  221.     }
  222.  
  223.     @Override
  224.     public String getToolTip(ItemStack stack) {
  225.         return null;
  226.     }
  227.  
  228.     @Override
  229.     public double getCharge(ItemStack stack) {
  230.         IEnergyContainerItem item = (IEnergyContainerItem) stack.getItem();
  231.         return item.getEnergyStored(stack) / EnetBridge.getEuPerRf();
  232.     }
  233.  
  234.     @Override
  235.     public double discharge(ItemStack stack, double amount, int tier, boolean ignoreTransferLimit, boolean externally, boolean simulate) {
  236.         int rf = (int) (amount / EnetBridge.getEuPerRf());
  237.         if (rf <= 0) return 0;
  238.  
  239.         IEnergyContainerItem item = (IEnergyContainerItem) stack.getItem();
  240.         int ret = item.extractEnergy(stack, rf, simulate);
  241.  
  242.         return Math.min(ret * EnetBridge.getEuPerRf(), amount);
  243.     }
  244.  
  245.     @Override
  246.     public void chargeFromArmor(ItemStack stack, EntityLivingBase entity) {
  247.         ElectricItem.rawManager.chargeFromArmor(stack, entity);
  248.     }
  249.  
  250.     @Override
  251.     public double charge(ItemStack stack, double amount, int tier, boolean ignoreTransferLimit, boolean simulate) {
  252.         int rf = (int) (amount * EnetBridge.getRfPerEu());
  253.         if (rf <= 0) return 0;
  254.  
  255.         IEnergyContainerItem item = (IEnergyContainerItem) stack.getItem();
  256.         double ret = item.receiveEnergy(stack, rf, simulate);
  257.  
  258.         return Math.min(ret / EnetBridge.getRfPerEu(), amount);
  259.     }
  260.  
  261.     @Override
  262.     public boolean canUse(ItemStack stack, double amount) {
  263.         return ElectricItem.rawManager.canUse(stack, amount);
  264.     }
  265.  
  266.     @Override
  267.     public boolean handles(ItemStack stack) {
  268.         return stack.getItem() instanceof IEnergyContainerItem;
  269.     }
  270. }
  271.  
  272.  
  273. public class RfBlockDelegate extends TileEntityDelegate {
  274.     public static TileEntityDelegate create(TileEntity te) {
  275.         if (!isApplicable(te)) return null;
  276.  
  277.         try {
  278.             return new RfBlockDelegate(te);
  279.         } catch (Exception e) {
  280.             EnetBridge.log.warn("RF delegate init error: {}.", e.getMessage());
  281.             return null;
  282.         }
  283.     }
  284.  
  285.     public static boolean isApplicable(TileEntity te) {
  286.         return EnetBridge.hasRf() && (te instanceof IEnergyProvider || te instanceof IEnergyReceiver);
  287.     }
  288.  
  289.     private RfBlockDelegate(TileEntity base) {
  290.         super(base);
  291.  
  292.         this.base = (IEnergyConnection) base;
  293.  
  294.         if (base instanceof IEnergyProvider) {
  295.             this.provider = (IEnergyProvider) base;
  296.         } else {
  297.             this.provider = null;
  298.         }
  299.  
  300.         if (base instanceof IEnergyReceiver) {
  301.             this.receiver = (IEnergyReceiver) base;
  302.         } else {
  303.             this.receiver = null;
  304.         }
  305.  
  306.         updateDirs(false);
  307.     }
  308.  
  309.     @Override
  310.     public void tick() {
  311.         if (!faulty && updateDirs(true)) {
  312.             // refresh connectivity
  313.             MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this));
  314.             updateDirs(false);
  315.             MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this));
  316.         }
  317.     }
  318.  
  319.     @Override
  320.     public boolean acceptsEnergyFrom(TileEntity emitter, ForgeDirection direction) {
  321.         return !faulty && receiver != null && sinkDirs.contains(direction);
  322.     }
  323.  
  324.     @Override
  325.     public boolean emitsEnergyTo(TileEntity receiver, ForgeDirection direction) {
  326.         return !faulty && provider != null && sourceDirs.contains(direction);
  327.     }
  328.  
  329.     @Override
  330.     public double getDemandedEnergy() {
  331.         if (faulty) return 0;
  332.         if (receiver == null) return 0;
  333.  
  334.         int max = 0;
  335.  
  336.         for (ForgeDirection dir : sinkDirs) {
  337.             int amount = receiver.receiveEnergy(dir, Integer.MAX_VALUE, true);
  338.             if (amount > max) max = amount;
  339.         }
  340.  
  341.         return max * 1. / EnetBridge.getRfPerEu();
  342.     }
  343.  
  344.     @Override
  345.     public double getOfferedEnergy() {
  346.         if (faulty) return 0;
  347.         if (provider == null) return 0;
  348.  
  349.         int max = 0;
  350.  
  351.         for (ForgeDirection dir : sourceDirs) {
  352.             int amount = provider.extractEnergy(dir, Integer.MAX_VALUE, true);
  353.             if (amount > max) max = amount;
  354.         }
  355.  
  356.         return max * EnetBridge.getEuPerRf();
  357.     }
  358.  
  359.     @Override
  360.     public double injectEnergy(ForgeDirection directionFrom, double amount, double voltage) {
  361.         if (receiver == null) return amount;
  362.  
  363.         amount *= EnetBridge.getRfPerEu();
  364.         int iAmount = (int) amount;
  365.         if (iAmount <= 0) return amount;
  366.  
  367.         amount -= iAmount;
  368.  
  369.         if (directionFrom != ForgeDirection.UNKNOWN) {
  370.             iAmount -= receiver.receiveEnergy(directionFrom, iAmount, false);
  371.         }
  372.  
  373.         for (ForgeDirection dir : sinkDirs) {
  374.             if (iAmount <= 0) break;
  375.             iAmount -= receiver.receiveEnergy(dir, iAmount, false);
  376.         }
  377.  
  378.         return (amount + iAmount) * 1. / EnetBridge.getRfPerEu();
  379.     }
  380.  
  381.     @Override
  382.     public void drawEnergy(double amount) {
  383.         if (provider != null) {
  384.             for (ForgeDirection dir : sourceDirs) {
  385.                 amount -= provider.extractEnergy(dir, (int) Math.ceil(amount / EnetBridge.getEuPerRf()), false) * EnetBridge.getEuPerRf();
  386.                 if (amount <= 0) break;
  387.             }
  388.         }
  389.  
  390.         if (amount > 0) {
  391.             EnetBridge.log.warn("Can't draw the full amount from {}, {} left over, disabling the delegate.", base, amount);
  392.             faulty = true;
  393.         }
  394.     }
  395.  
  396.     private boolean updateDirs(boolean simulate) {
  397.         EnumSet<ForgeDirection> newSinkdirs = EnumSet.noneOf(ForgeDirection.class);
  398.         EnumSet<ForgeDirection> newSourcedirs = EnumSet.noneOf(ForgeDirection.class);
  399.  
  400.         // probe directions if they are connectable and can source or sink energy
  401.         for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
  402.             if (!base.canConnectEnergy(dir)) continue;
  403.  
  404.             if (receiver != null && EnetBridge.getRfPerEu() > 0) { // sink
  405.                 if (receiver.getEnergyStored(dir) >= receiver.getMaxEnergyStored(dir) || // be optimistic if we can't check
  406.                         receiver.receiveEnergy(dir, Integer.MAX_VALUE, true) > 0) {
  407.                     newSinkdirs.add(dir);
  408.                 }
  409.             }
  410.  
  411.             if (provider != null && EnetBridge.getEuPerRf() > 0) { // source
  412.                 if (provider.getEnergyStored(dir) <= 0 ||  // be optimistic if we can't check
  413.                         provider.extractEnergy(dir, Integer.MAX_VALUE, true) > 0) {
  414.                     newSourcedirs.add(dir);
  415.                 }
  416.             }
  417.         }
  418.  
  419.         if (sinkDirs.equals(newSinkdirs) && sourceDirs.equals(newSourcedirs)) {
  420.             return false;
  421.         } else {
  422.             if (!simulate) {
  423.                 sinkDirs.clear();
  424.                 sinkDirs.addAll(newSinkdirs);
  425.  
  426.                 sourceDirs.clear();
  427.                 sourceDirs.addAll(newSourcedirs);
  428.             }
  429.  
  430.             //EnetBridge.log.debug("Detected new dirs for {}: {}, {}.", base, sinkDirs, sourceDirs);
  431.  
  432.             return true;
  433.         }
  434.     }
  435.  
  436.  
  437.     private final IEnergyConnection base;
  438.     private final IEnergyProvider provider;
  439.     private final IEnergyReceiver receiver;
  440.     protected boolean faulty = false;
  441.     protected final Set<ForgeDirection> sinkDirs = EnumSet.noneOf(ForgeDirection.class);
  442.     protected final Set<ForgeDirection> sourceDirs = EnumSet.noneOf(ForgeDirection.class);
  443. }
  444.  
  445.  
  446.  
  447. public class ChargeBlockDelegate extends TileEntityDelegate {
  448.     public static TileEntityDelegate create(TileEntity te) {
  449.         if (!isApplicable(te)) return null;
  450.  
  451.         try {
  452.             return new ChargeBlockDelegate(te);
  453.         } catch (Exception e) {
  454.             EnetBridge.log.warn("Charge delegate init error: {}.", e.getMessage());
  455.             return null;
  456.         }
  457.     }
  458.  
  459.     public static boolean isApplicable(TileEntity te) {
  460.         return EnetBridge.hasCharge() && te instanceof IChargeConductor;
  461.     }
  462.  
  463.  
  464.     private ChargeBlockDelegate(TileEntity te) {
  465.         super(te);
  466.  
  467.         this.base = (IChargeConductor) te;
  468.     }
  469.  
  470.     @Override
  471.     public void tick() {
  472.     }
  473.  
  474.     @Override
  475.     public boolean acceptsEnergyFrom(TileEntity emitter, ForgeDirection direction) {
  476.         return !faulty;
  477.     }
  478.  
  479.     @Override
  480.     public boolean emitsEnergyTo(TileEntity receiver, ForgeDirection direction) {
  481.         return !faulty;
  482.     }
  483.  
  484.     @Override
  485.     public double getDemandedEnergy() {
  486.         if (faulty) return 0;
  487.  
  488.         return Math.max(0, EnetBridge.getTargetCharge() - base.getCharge().getValue()) * 1. / EnetBridge.getChargePerEu();
  489.     }
  490.  
  491.     @Override
  492.     public double getOfferedEnergy() {
  493.         if (faulty) return 0;
  494.  
  495.         return Math.max(0, base.getCharge().getValue() - EnetBridge.getTargetCharge()) * EnetBridge.getEuPerCharge();
  496.     }
  497.  
  498.     @Override
  499.     public double injectEnergy(ForgeDirection directionFrom, double amount, double voltage) {
  500.         amount *= EnetBridge.getChargePerEu();
  501.         int iAmount = (int) amount;
  502.         if (iAmount <= 0) return amount;
  503.  
  504.         amount -= iAmount;
  505.  
  506.         base.getCharge().addValue(iAmount);
  507.  
  508.         return amount * 1. / EnetBridge.getChargePerEu();
  509.     }
  510.  
  511.     @Override
  512.     public void drawEnergy(double amount) {
  513.         amount -= base.getCharge().deplete((int) Math.ceil(amount / EnetBridge.getEuPerCharge())) * EnetBridge.getEuPerCharge();
  514.  
  515.         if (amount > 0) {
  516.             EnetBridge.log.warn("Can't draw the full amount from {}, {} left over, disabling the delegate.", base, amount);
  517.             faulty = true;
  518.         }
  519.     }
  520.  
  521.  
  522.     private final IChargeConductor base;
  523.     protected boolean faulty = false;
  524. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement