Package micdoodle8.mods.galacticraft.core.energy.grid

Source Code of micdoodle8.mods.galacticraft.core.energy.grid.EnergyNetwork

package micdoodle8.mods.galacticraft.core.energy.grid;

import buildcraft.api.mj.MjAPI;
import buildcraft.api.power.IPowerEmitter;
import buildcraft.api.power.IPowerReceptor;
import buildcraft.api.power.PowerHandler.PowerReceiver;
import cpw.mods.fml.common.FMLLog;
import ic2.api.energy.tile.IEnergyAcceptor;
import ic2.api.energy.tile.IEnergySink;
import mekanism.api.energy.IStrictEnergyAcceptor;
import micdoodle8.mods.galacticraft.api.transmission.NetworkType;
import micdoodle8.mods.galacticraft.api.transmission.grid.IElectricityNetwork;
import micdoodle8.mods.galacticraft.api.transmission.tile.IConductor;
import micdoodle8.mods.galacticraft.api.transmission.tile.IElectrical;
import micdoodle8.mods.galacticraft.api.vector.BlockVec3;
import micdoodle8.mods.galacticraft.core.energy.EnergyConfigHandler;
import micdoodle8.mods.galacticraft.core.energy.EnergyUtil;
import micdoodle8.mods.galacticraft.core.energy.tile.TileBaseUniversalConductor;
import micdoodle8.mods.galacticraft.core.util.ConfigManagerCore;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;

import java.util.*;

//import buildcraft.api.power.PowerHandler.Type;
//import cofh.api.energy.IEnergyHandler;


/**
* A universal network that works with multiple energy systems.
*
* @author radfast, micdoodle8, Calclavia, Aidancbrady
*/
public class EnergyNetwork implements IElectricityNetwork
{
    /* Re-written by radfast for better performance
     *
     * Imagine a 30 producer, 80 acceptor network...
     *
     *   Before: it would have called the inner loop in produce() 2400 times each tick.  Not good!
     *
     *   After: the inner loop runs 80 times - part of it is in doTickStartCalc() at/near the tick start, and part of it is in doProduce() at the end of the tick
     */
    public static int tickCount = 0;
    private int tickDone = -1;
    private float totalRequested = 0F;
    private float totalStorageExcess = 0F;
    private float totalEnergy = 0F;
    private float totalSent = 0F;
    private boolean doneScheduled = false;
    private boolean spamstop = false;
    private boolean loopPrevention = false;
    public int networkTierGC = 1;
    private int producersTierGC = 1;

    /*
     * connectedAcceptors is all the acceptors connected to this network
     * connectedDirections is the directions of those connections (from the point of view of the acceptor tile)
     *   Note: each position in those two linked lists matches
     *         so, an acceptor connected on two sides will be in connectedAcceptors twice
     */
    private List<TileEntity> connectedAcceptors = new LinkedList<TileEntity>();
    private List<ForgeDirection> connectedDirections = new LinkedList<ForgeDirection>();

    /*
     *  availableAcceptors is the acceptors which can receive energy (this tick)
     *  availableconnectedDirections is a map of those acceptors and the directions they will receive from (from the point of view of the acceptor tile)
     *    Note: each acceptor will only be included once in these collections
     *          (there is no point trying to put power into a machine twice from two different sides)
     */
    private Set<TileEntity> availableAcceptors = new HashSet<TileEntity>();
    private Map<TileEntity, ForgeDirection> availableconnectedDirections = new HashMap<TileEntity, ForgeDirection>();

    private Map<TileEntity, Float> energyRequests = new HashMap<TileEntity, Float>();
    private List<TileEntity> ignoreAcceptors = new LinkedList<TileEntity>();

    private final Set<IConductor> conductors = new HashSet<IConductor>();

    //This is an energy per tick which exceeds what any normal machine will request, so the requester must be an energy storage - for example, a battery or an energy cube
    private final static float ENERGY_STORAGE_LEVEL = 200F;

    @Override
    public Set<IConductor> getTransmitters()
    {
        return this.conductors;
    }

    /**
     * Get the total energy request in this network
     *
     * @param ignoreTiles Tiles to ignore in the request calculations (NOTE: only used in initial (internal) check.
     * @return Amount of energy requested in this network
     */
    @Override
    public float getRequest(TileEntity... ignoreTiles)
    {
        if (EnergyNetwork.tickCount != this.tickDone)
        {
            this.tickDone = EnergyNetwork.tickCount;
            //Start the new tick - initialise everything
            this.ignoreAcceptors.clear();
            this.ignoreAcceptors.addAll(Arrays.asList(ignoreTiles));
            this.doTickStartCalc();

            if (EnergyConfigHandler.isBuildcraftLoaded())
            {
                for (IConductor wire : this.getTransmitters())
                {
                    if (wire instanceof TileBaseUniversalConductor)
                    {
                        //This will call getRequest() but that's no problem, on the second call it will just return the totalRequested
                        ((TileBaseUniversalConductor) wire).reconfigureBC();
                    }
                }
            }
        }
        return this.totalRequested - this.totalEnergy - this.totalSent;
    }

    /**
     * Produce energy into the network
     *
     * @param energy      Amount of energy to send into the network
     * @param doReceive   Whether to put energy into the network (true) or just simulate (false)
     * @param ignoreTiles TileEntities to ignore for energy transfers.
     * @return Amount of energy REMAINING from the passed energy parameter
     */
    @Override
    public float produce(float energy, boolean doReceive, int producerTier, TileEntity... ignoreTiles)
    {
        if (this.loopPrevention)
        {
            return energy;
        }

        if (energy > 0F)
        {
            if (EnergyNetwork.tickCount != this.tickDone)
            {
                this.tickDone = EnergyNetwork.tickCount;
                //Start the new tick - initialise everything
                this.ignoreAcceptors.clear();
                this.ignoreAcceptors.addAll(Arrays.asList(ignoreTiles));
                this.producersTierGC = 1;
                this.doTickStartCalc();
            }
            else
            {
                this.ignoreAcceptors.addAll(Arrays.asList(ignoreTiles));
            }

            if (!this.doneScheduled && this.totalRequested > 0.0F)
            {
                try
                {
                    Class<?> clazz = Class.forName("micdoodle8.mods.galacticraft.core.tick.TickHandlerServer");
                    clazz.getMethod("scheduleNetworkTick", this.getClass()).invoke(null, this);
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }

                this.doneScheduled = true;
            }

            //On a regular mid-tick produce(), just figure out how much is totalEnergy this tick and return the used amount
            //This will return 0 if totalRequested is 0 - for example a network with no acceptors
            float totalEnergyLast = this.totalEnergy;

            //Add the energy for distribution by this grid later this tick
            //Note: totalEnergy cannot exceed totalRequested
            if (doReceive)
            {
                this.totalEnergy += Math.min(energy, this.totalRequested - totalEnergyLast);
                if (producerTier > 1)
                {
                    this.producersTierGC = 2;
                }
            }

            if (this.totalRequested >= totalEnergyLast + energy)
            {
                return 0F; //All the electricity will be used
            }
            if (totalEnergyLast >= this.totalRequested)
            {
                return energy; //None of the electricity will be used
            }
            return totalEnergyLast + energy - this.totalRequested; //Some of the electricity will be used
        }
        return energy;
    }

    /**
     * Called on server tick end, from the Galacticraft Core tick handler.
     */
    public void tickEnd()
    {
        this.doneScheduled = false;
        this.loopPrevention = true;

        //Finish the last tick if there was some to send and something to receive it
        if (this.totalEnergy > 0F)
        {
            //Call doTickStartCalc a second time in case anything has updated meanwhile
            this.doTickStartCalc();

            if (this.totalRequested > 0F)
            {
                this.totalSent = this.doProduce();
                if (this.totalSent < this.totalEnergy)
                {
                    //Any spare energy left is retained for the next tick
                    this.totalEnergy -= this.totalSent;
                }
                else
                {
                    this.totalEnergy = 0F;
                }
            } else
              this.totalEnergy = 0F;
        }
        else
        {
            this.totalEnergy = 0F;
        }

        this.loopPrevention = false;
    }

    /**
     * Refreshes all tiles in network, and updates requested energy
     *
     * @param ignoreTiles TileEntities to ignore for energy calculations.
     */
    private void doTickStartCalc()
    {
        this.totalSent = 0F;
        this.refreshAcceptors();

        if (!EnergyUtil.initialisedIC2Methods)
        {
            EnergyUtil.initialiseIC2Methods();
        }

        if (this.getTransmitters().size() == 0)
        {
            return;
        }

        this.loopPrevention = true;

        this.availableAcceptors.clear();
        this.availableconnectedDirections.clear();
        this.energyRequests.clear();
        this.totalRequested = 0.0F;
        this.totalStorageExcess = 0F;

        //boolean isTELoaded = EnergyConfigHandler.isThermalExpansionLoaded();
        boolean isIC2Loaded = EnergyConfigHandler.isIndustrialCraft2Loaded();
        boolean isBCLoaded = EnergyConfigHandler.isBuildcraftLoaded();
        boolean isMekLoaded = EnergyConfigHandler.isMekanismLoaded();

        if (!this.connectedAcceptors.isEmpty())
        {
            float e;
            final Iterator<ForgeDirection> acceptorDirection = this.connectedDirections.iterator();
            for (TileEntity acceptor : this.connectedAcceptors)
            {
                //This tries all sides of the acceptor which are connected (see refreshAcceptors())
                ForgeDirection sideFrom = acceptorDirection.next();

                //But the grid will only put energy into the acceptor from one side - once it's in availableAcceptors
                if (!this.ignoreAcceptors.contains(acceptor) && !this.availableAcceptors.contains(acceptor))
                {
                    e = 0.0F;

                    if (acceptor instanceof IElectrical)
                    {
                        e = ((IElectrical) acceptor).getRequest(sideFrom);
                    }
                    else if (isMekLoaded && acceptor instanceof IStrictEnergyAcceptor)
                    {
                        e = (float) ((((IStrictEnergyAcceptor) acceptor).getMaxEnergy() - ((IStrictEnergyAcceptor) acceptor).getEnergy()) * EnergyConfigHandler.MEKANISM_RATIO);
                    }
                    /*else if (isTELoaded && acceptor instanceof IEnergyHandler)
          {
            e = ((IEnergyHandler) acceptor).receiveEnergy(sideFrom, Integer.MAX_VALUE, true) * EnergyConfigHandler.TE_RATIO;
          }*/
                    else if (isIC2Loaded && acceptor instanceof IEnergySink)
                    {
                        double result = 0;
                        try
                        {
                            result = (Double) EnergyUtil.demandedEnergyIC2.invoke(acceptor);
                        }
                        catch (Exception ex)
                        {
                            if (ConfigManagerCore.enableDebug)
                            {
                                ex.printStackTrace();
                            }
                        }
                        //Cap IC2 power transfer at 128EU/t for standard Alu wire, 256EU/t for heavy Alu wire
                        result = Math.max(result, (this.networkTierGC == 2) ? 256D : 128D);
                        e = (float) result * EnergyConfigHandler.IC2_RATIO;
                    }
                    else if (isBCLoaded && EnergyConfigHandler.getBuildcraftVersion() == 6 && MjAPI.getMjBattery(acceptor, MjAPI.DEFAULT_POWER_FRAMEWORK, sideFrom) != null)
                    //New BC API
                    {
                        e = (float) MjAPI.getMjBattery(acceptor, MjAPI.DEFAULT_POWER_FRAMEWORK, sideFrom).getEnergyRequested() * EnergyConfigHandler.BC3_RATIO;
                    }
                    else if (isBCLoaded && acceptor instanceof IPowerReceptor)
                    //Legacy BC API
                    {
                        PowerReceiver BCreceiver = ((IPowerReceptor) acceptor).getPowerReceiver(sideFrom);
                        if (BCreceiver != null)
                        {
                            e = (float) BCreceiver.powerRequest() * EnergyConfigHandler.BC3_RATIO;
                        }
                    }

                    if (e > 0.0F)
                    {
                        this.availableAcceptors.add(acceptor);
                        this.availableconnectedDirections.put(acceptor, sideFrom);
                        this.energyRequests.put(acceptor, Float.valueOf(e));
                        this.totalRequested += e;
                        if (e > EnergyNetwork.ENERGY_STORAGE_LEVEL)
                        {
                            this.totalStorageExcess += e - EnergyNetwork.ENERGY_STORAGE_LEVEL;
                        }
                    }
                }
            }
        }

        this.loopPrevention = false;
    }

    /**
     * Complete the energy transfer. Called internally on server tick end.
     *
     * @return Amount of energy SENT to all acceptors
     */
    private float doProduce()
    {
        float sent = 0.0F;

        if (!this.availableAcceptors.isEmpty())
        {
            //boolean isTELoaded = EnergyConfigHandler.isThermalExpansionLoaded();
            boolean isIC2Loaded = EnergyConfigHandler.isIndustrialCraft2Loaded();
            boolean isBCLoaded = EnergyConfigHandler.isBuildcraftLoaded();
            boolean isMekLoaded = EnergyConfigHandler.isMekanismLoaded();

            float energyNeeded = this.totalRequested;
            float energyAvailable = this.totalEnergy;
            float reducor = 1.0F;
            float energyStorageReducor = 1.0F;

            if (energyNeeded > energyAvailable)
            {
                //If not enough energy, try reducing what goes into energy storage (if any)
                energyNeeded -= this.totalStorageExcess;
                //If there's still not enough, put the minimum into energy storage (if any) and, anyhow, reduce everything proportionately
                if (energyNeeded > energyAvailable)
                {
                    energyStorageReducor = 0F;
                    reducor = energyAvailable / energyNeeded;
                }
                else
                {
                    //Energyavailable exceeds the total needed but only if storage does not fill all in one go - this is a common situation
                    energyStorageReducor = (energyAvailable - energyNeeded) / this.totalStorageExcess;
                }
            }

            float currentSending;
            float sentToAcceptor;
            int tierProduced = Math.min(this.producersTierGC, this.networkTierGC);

            for (TileEntity tileEntity : this.availableAcceptors)
            {
                //Exit the loop if there is no energy left at all (should normally not happen, should be some even for the last acceptor)
                if (sent >= energyAvailable)
                {
                    break;
                }

                //The base case is to give each acceptor what it is requesting
                currentSending = this.energyRequests.get(tileEntity);

                //If it's an energy store, we may need to damp it down if energyStorageReducor is less than 1
                if (currentSending > EnergyNetwork.ENERGY_STORAGE_LEVEL)
                {
                    currentSending = EnergyNetwork.ENERGY_STORAGE_LEVEL + (currentSending - EnergyNetwork.ENERGY_STORAGE_LEVEL) * energyStorageReducor;
                }

                //Reduce everything proportionately if there is not enough energy for all needs
                currentSending *= reducor;

                if (currentSending > energyAvailable - sent)
                {
                    currentSending = energyAvailable - sent;
                }

                ForgeDirection sideFrom = this.availableconnectedDirections.get(tileEntity);

                if (tileEntity instanceof IElectrical)
                {
                    sentToAcceptor = ((IElectrical) tileEntity).receiveElectricity(sideFrom, currentSending, tierProduced, true);
                }
                else if (isMekLoaded && tileEntity instanceof IStrictEnergyAcceptor)
                {
                    sentToAcceptor = (float) ((IStrictEnergyAcceptor) tileEntity).transferEnergyToAcceptor(sideFrom, currentSending * EnergyConfigHandler.TO_MEKANISM_RATIO) * EnergyConfigHandler.MEKANISM_RATIO;
                }
//        else if (isTELoaded && tileEntity instanceof IEnergyHandler)
//        {
//        IEnergyHandler handler = (IEnergyHandler) tileEntity;
//        int currentSendinginRF = (currentSending >= Integer.MAX_VALUE / EnergyConfigHandler.TO_TE_RATIO) ? Integer.MAX_VALUE : (int) (currentSending * EnergyConfigHandler.TO_TE_RATIO);
//        sentToAcceptor = handler.receiveEnergy(sideFrom, currentSendinginRF, false) * EnergyConfigHandler.TE_RATIO;
//        }
                else if (isIC2Loaded && tileEntity instanceof IEnergySink)
                {
                    double energySendingIC2 = currentSending * EnergyConfigHandler.TO_IC2_RATIO;
                    if (energySendingIC2 >= 1D)
                    {
                        double result = 0;
                        try
                        {
                            if (EnergyUtil.voltageParameterIC2)
                            {
                                result = (Double) EnergyUtil.injectEnergyIC2.invoke(tileEntity, sideFrom, energySendingIC2, 120D);
                            }
                            else
                            {
                                result = (Double) EnergyUtil.injectEnergyIC2.invoke(tileEntity, sideFrom, energySendingIC2);
                            }
                        }
                        catch (Exception ex)
                        {
                            if (ConfigManagerCore.enableDebug)
                            {
                                ex.printStackTrace();
                            }
                        }
                        sentToAcceptor = currentSending - (float) result * EnergyConfigHandler.IC2_RATIO;
                        if (sentToAcceptor < 0F)
                        {
                            sentToAcceptor = 0F;
                        }
                    }
                    else
                    {
                        sentToAcceptor = 0F;
                    }
                }
                else if (isBCLoaded && EnergyConfigHandler.getBuildcraftVersion() == 6 && MjAPI.getMjBattery(tileEntity, MjAPI.DEFAULT_POWER_FRAMEWORK, sideFrom) != null)
                //New BC API
                {
                    sentToAcceptor = (float) MjAPI.getMjBattery(tileEntity, MjAPI.DEFAULT_POWER_FRAMEWORK, sideFrom).addEnergy(currentSending * EnergyConfigHandler.TO_BC_RATIO) * EnergyConfigHandler.BC3_RATIO;
                }
                else if (isBCLoaded && tileEntity instanceof IPowerReceptor)
                //Legacy BC API
                {
                    PowerReceiver receiver = ((IPowerReceptor) tileEntity).getPowerReceiver(sideFrom);

                    if (receiver != null)
                    {
                        double toSendBC = Math.min(currentSending * EnergyConfigHandler.TO_BC_RATIO, receiver.powerRequest());
                        sentToAcceptor = (float) receiver.receiveEnergy(buildcraft.api.power.PowerHandler.Type.PIPE, toSendBC, sideFrom) * EnergyConfigHandler.BC3_RATIO;
                    }
                    else
                    {
                        sentToAcceptor = 0F;
                    }
                }
                else
                {
                    sentToAcceptor = 0F;
                }

                if (sentToAcceptor / currentSending > 1.002F && sentToAcceptor > 0.01F)
                {
                    if (!this.spamstop)
                    {
                        FMLLog.info("Energy network: acceptor took too much energy, offered " + currentSending + ", took " + sentToAcceptor + ". " + tileEntity.toString());
                        this.spamstop = true;
                    }
                    sentToAcceptor = currentSending;
                }

                sent += sentToAcceptor;
            }
        }

        if (EnergyNetwork.tickCount % 200 == 0)
        {
            this.spamstop = false;
        }

        float returnvalue = sent;
        if (returnvalue > this.totalEnergy)
        {
            returnvalue = this.totalEnergy;
        }
        if (returnvalue < 0F)
        {
            returnvalue = 0F;
        }
        return returnvalue;
    }

    /**
     * Refresh validity of each conductor in the network
     */
    public void refreshWithChecks()
    {
        int tierfound = 2;
        Iterator<IConductor> it = this.getTransmitters().iterator();
        while (it.hasNext())
        {
            IConductor conductor = it.next();

            if (conductor == null)
            {
                it.remove();
                continue;
            }

            TileEntity tile = (TileEntity) conductor;
            World world = tile.getWorldObj();
            //Remove any conductors in unloaded chunks
            if (tile.isInvalid() || world == null || !world.blockExists(tile.xCoord, tile.yCoord, tile.zCoord))
            {
                it.remove();
                continue;
            }

            if (conductor != world.getTileEntity(tile.xCoord, tile.yCoord, tile.zCoord))
            {
                it.remove();
                continue;
            }

            if (conductor.getTierGC() < 2)
            {
                tierfound = 1;
            }

            if (conductor.getNetwork() != this)
            {
                conductor.setNetwork(this);
                conductor.onNetworkChanged();
            }
        }

        //This will set the network tier to 2 if all the conductors are tier 2
        this.networkTierGC = tierfound;
    }

    @Override
    public void refresh()
    {
        int tierfound = 2;
        Iterator<IConductor> it = this.getTransmitters().iterator();
        while (it.hasNext())
        {
            IConductor conductor = it.next();

            if (conductor == null)
            {
                it.remove();
                continue;
            }

            TileEntity tile = (TileEntity) conductor;
            World world = tile.getWorldObj();
            //Remove any conductors in unloaded chunks
            if (tile.isInvalid() || world == null)
            {
                it.remove();
                continue;
            }

            if (conductor.getTierGC() < 2)
            {
                tierfound = 1;
            }

            if (conductor.getNetwork() != this)
            {
                conductor.setNetwork(this);
                conductor.onNetworkChanged();
            }
        }

        //This will set the network tier to 2 if all the conductors are tier 2
        this.networkTierGC = tierfound;
    }

    /**
     * Refresh all energy acceptors in the network
     */
    private void refreshAcceptors()
    {
        this.connectedAcceptors.clear();
        this.connectedDirections.clear();

        this.refreshWithChecks();

        try
        {
            //boolean isTELoaded = EnergyConfigHandler.isThermalExpansionLoaded();
            boolean isIC2Loaded = EnergyConfigHandler.isIndustrialCraft2Loaded();
            boolean isBCLoaded = EnergyConfigHandler.isBuildcraftLoaded();
            boolean isMekLoaded = EnergyConfigHandler.isMekanismLoaded();

            LinkedList<IConductor> conductors = new LinkedList();
            conductors.addAll(this.getTransmitters());
            //This prevents concurrent modifications if something in the loop causes chunk loading
            //(Chunk loading can change the network if new conductors are found)
            for (IConductor conductor : conductors)
            {
                TileEntity[] adjacentConnections = conductor.getAdjacentConnections();
                for (int i = 0; i < adjacentConnections.length; i++)
                {
                    TileEntity acceptor = adjacentConnections[i];

                    if (acceptor != null && !(acceptor instanceof IConductor) && !acceptor.isInvalid())
                    {
                        // The direction 'sideFrom' is from the perspective of the acceptor, that's more useful than the conductor's perspective
                        ForgeDirection sideFrom = ForgeDirection.getOrientation(i).getOpposite();

                        if (acceptor instanceof IElectrical)
                        {
                            if (((IElectrical) acceptor).canConnect(sideFrom, NetworkType.POWER))
                            {
                                this.connectedAcceptors.add(acceptor);
                                this.connectedDirections.add(sideFrom);
                            }
                        }
                        else if (isMekLoaded && acceptor instanceof IStrictEnergyAcceptor)
                        {
                            if (((IStrictEnergyAcceptor) acceptor).canReceiveEnergy(sideFrom))
                            {
                                this.connectedAcceptors.add(acceptor);
                                this.connectedDirections.add(sideFrom);
                            }
                        }
            /*else if (isTELoaded && acceptor instanceof IEnergyHandler)
            {
              if (((IEnergyHandler) acceptor).canInterface(sideFrom))
              {
                this.connectedAcceptors.add(acceptor);
                this.connectedDirections.add(sideFrom);
              }
            }*/
                        else if (isIC2Loaded && acceptor instanceof IEnergyAcceptor)
                        {
                            if (((IEnergyAcceptor) acceptor).acceptsEnergyFrom((TileEntity) conductor, sideFrom))
                            {
                                this.connectedAcceptors.add(acceptor);
                                this.connectedDirections.add(sideFrom);
                            }
                        }
                        else if (isBCLoaded && EnergyConfigHandler.getBuildcraftVersion() == 6 && MjAPI.getMjBattery(acceptor, MjAPI.DEFAULT_POWER_FRAMEWORK, sideFrom) != null)
                        {
                            this.connectedAcceptors.add(acceptor);
                            this.connectedDirections.add(sideFrom);
                        }
                        else if (isBCLoaded && acceptor instanceof IPowerReceptor)
                        {
                            if (((IPowerReceptor) acceptor).getPowerReceiver(sideFrom) != null && (!(acceptor instanceof IPowerEmitter) || !((IPowerEmitter)acceptor).canEmitPowerFrom(sideFrom)))
                            {
                                this.connectedAcceptors.add(acceptor);
                                this.connectedDirections.add(sideFrom);
                            }
                        }
                    }
                }
            }
        }
        catch (Exception e)
        {
            FMLLog.severe("Energy Network: Error when trying to refresh list of power acceptors.");
            e.printStackTrace();
        }
    }

    /**
     * Combine this network with another electricitynetwork
     *
     * @param network Network to merge with
     * @return The final, joined network
     */
    @Override
    public IElectricityNetwork merge(IElectricityNetwork network)
    {
        if (network != null && network != this)
        {
            Set<IConductor> thisNetwork = this.getTransmitters();
            Set<IConductor> thatNetwork = network.getTransmitters();
            if (thisNetwork.size() >= thatNetwork.size())
            {
                thisNetwork.addAll(thatNetwork);
                this.refresh();
                if (network instanceof EnergyNetwork)
                {
                    ((EnergyNetwork) network).destroy();
                }
                return this;
            }
            else
            {
                thatNetwork.addAll(thisNetwork);
                network.refresh();
                this.destroy();
                return network;
            }
        }

        return this;
    }

    private void destroy()
    {
        this.getTransmitters().clear();
        this.connectedAcceptors.clear();
        this.availableAcceptors.clear();
        this.totalEnergy = 0F;
        this.totalRequested = 0F;
        try
        {
            Class<?> clazz = Class.forName("micdoodle8.mods.galacticraft.core.tick.TickHandlerServer");
            clazz.getMethod("removeNetworkTick", this.getClass()).invoke(null, this);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

    }

  public void split(IConductor splitPoint)
  {
        if (splitPoint instanceof TileEntity)
        {
            this.getTransmitters().remove(splitPoint);
        splitPoint.setNetwork(null);

            //If the size of the residual network is 1, it should simply be preserved
            if (this.getTransmitters().size() > 1)
            {
              World world = ((TileEntity) splitPoint).getWorldObj();
             
        if (this.getTransmitters().size() > 0)
        { 
          TileEntity[] nextToSplit = new TileEntity[6];
          boolean[] toDo = {true,true,true,true,true,true};
          TileEntity tileEntity;
         
          int xCoord = ((TileEntity)splitPoint).xCoord;
          int yCoord = ((TileEntity)splitPoint).yCoord;
          int zCoord = ((TileEntity)splitPoint).zCoord;
 
          for(int j = 0; j < 6; j++)
          {
            switch (j)
            {
              case 0:  tileEntity = world.getTileEntity(xCoord, yCoord - 1, zCoord);
                break;
              case 1:  tileEntity = world.getTileEntity(xCoord, yCoord + 1, zCoord);
                break;
              case 2:  tileEntity = world.getTileEntity(xCoord, yCoord, zCoord - 1);
                break;
              case 3:  tileEntity = world.getTileEntity(xCoord, yCoord, zCoord + 1);
                break;
              case 4:  tileEntity = world.getTileEntity(xCoord - 1, yCoord, zCoord);
                break;
              case 5:  tileEntity = world.getTileEntity(xCoord + 1, yCoord, zCoord);
                break;
              default:
                //Not reachable, only to prevent uninitiated compile errors
                tileEntity = null;
                break;
              }
                   
            if (tileEntity instanceof IConductor)
            {
              nextToSplit[j]=tileEntity;
            }
            else toDo[j]=false;
          }
   
          for(int i1 = 0; i1 < 6; i1++)
          {
            if(toDo[i1])
            {
              TileEntity connectedBlockA = nextToSplit[i1];
              NetworkFinder finder = new NetworkFinder(world, new BlockVec3(connectedBlockA), new BlockVec3((TileEntity)splitPoint));
              List<IConductor> partNetwork = finder.exploreNetwork();
             
              //Mark any others still to do in the nextToSplit array which are connected to this, as dealt with
              for(int i2 = i1 + 1; i2 < 6; i2++)
              {
                TileEntity connectedBlockB = nextToSplit[i2];
               
                if(toDo[i2])
                {
                  if(partNetwork.contains(connectedBlockB))
                  {
                    toDo[i2] = false;
                  }
                }
              }
         
              //Now make the new network from partNetwork
              EnergyNetwork newNetwork = new EnergyNetwork();
              newNetwork.getTransmitters().addAll(partNetwork);
              newNetwork.refreshWithChecks();
            }
          }
         
          this.destroy();
        }
            }
            //Splitting a 1-block network leaves nothing
            else if (this.getTransmitters().size() == 0)
            {
              this.destroy();
            }
        }
  }
   
    @Override
    public String toString()
    {
        return "EnergyNetwork[" + this.hashCode() + "|Wires:" + this.getTransmitters().size() + "|Acceptors:" + this.connectedAcceptors.size() + "]";
    }
}
TOP

Related Classes of micdoodle8.mods.galacticraft.core.energy.grid.EnergyNetwork

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.