Package universalelectricity.core.net

Source Code of universalelectricity.core.net.EnergyNetwork

package universalelectricity.core.net;

import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map.Entry;

import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.common.MinecraftForge;
import universalelectricity.api.CompatibilityModule;
import universalelectricity.api.UniversalElectricity;
import universalelectricity.api.energy.EnergyNetworkLoader;
import universalelectricity.api.energy.IConductor;
import universalelectricity.api.energy.IEnergyNetwork;
import universalelectricity.api.net.NetworkEvent.EnergyProduceEvent;

/** Basic energy network that moves energy from point A to point B. If you implement this in your own
* conductor code you will need to save the energy yourself. To do this have each conductor save its
* buffer from conductorBuffer map. When loading from the map make sure to also load up the buffer
* into the network as well.
*
* @author Calclavia, Darkguardsman */
public class EnergyNetwork extends NodeNetwork<IEnergyNetwork, IConductor, Object> implements IEnergyNetwork
{
    /** The energy to be distributed on the next update. */
    protected long energyBuffer;

    /** The individual buffer from each conductor. Used to limit the amount of buffer that can be
     * stored. */
    protected final HashMap<IConductor, Long> conductorBuffers = new HashMap<IConductor, Long>();

    /** Resistance of the network to flow of energy, is based on total resistance of each conductor */
    protected float resistance;

    /** The total energy buffer in the last tick. */
    protected long lastEnergyBuffer;

    /** Last cached value for network demand energy */
    protected long lastNetworkRequest = -1;

    /** Temporary variable */
    private long energyPerWire;

    /** The direction in which a conductor is placed relative to a specific conductor. */
    protected final HashMap<Object, EnumSet<ForgeDirection>> handlerDirectionMap = new LinkedHashMap<Object, EnumSet<ForgeDirection>>();

    public EnergyNetwork()
    {
        super(IConductor.class);
        NetworkTickHandler.addNetwork(this);
    }

    @Override
    public void addConnector(IConductor connector)
    {
        connector.setNetwork(this);
        super.addConnector(connector);
    }

    @Override
    public void update()
    {
        /** Energy we have to move after loss has been removed */
        long usableEnergy = Math.max(energyBuffer - getEnergyLoss(), 0);
        /** Energy currently left after we have moved some */
        long currentEnergy = usableEnergy;
        /** Energy per handler */
        long perHandler = 0;
        /** Energy per side of a handler */
        long perSide = 0;
        /** Number of handlers */
        int handlers = handlerDirectionMap.size();

        if (handlers > 0)
        {
            /** For each conductor, output the energy into the handlers. */
            for (Entry<Object, EnumSet<ForgeDirection>> entry : handlerDirectionMap.entrySet())
            {
                /** Energy to give to each handler */
                perHandler = (usableEnergy / handlers) + (usableEnergy % handlers);

                for (ForgeDirection direction : entry.getValue())
                {
                    /** Energy per to give per side */
                    perSide = (perHandler / entry.getValue().size()) + (perHandler % entry.getValue().size());
                    currentEnergy -= addEnergyToHandler(entry.getKey(), direction, perSide, true);
                }
                if (handlers > 1)
                {
                    handlers--;
                }
            }
            this.lastEnergyBuffer = this.energyBuffer;
            /** Don't set energy if none was sent to prevent energy loss */
            if (usableEnergy != currentEnergy)
                energyBuffer = Math.max(currentEnergy, 0);
        }
       
        // Check if there are any conductors to loop through before starting.
        long remainingBufferPerConductor = 0;
        if (getConnectors().size() > 0)
        {
            remainingBufferPerConductor = energyBuffer / getConnectors().size();
        }
       
        // Ensure that the iterator for the conductors is not null.
        Iterator<IConductor> it = getConnectors().iterator();
        if (it != null)
        {
            while (it.hasNext())
            {
                conductorBuffers.put(it.next(), remainingBufferPerConductor);
            }
        }

        // Clear the network request cache.
        lastNetworkRequest = -1;
    }

    /** Applies power to the machine */
    public long addEnergyToHandler(Object handler, ForgeDirection side, long energy, boolean doApply)
    {
        return CompatibilityModule.receiveEnergy(handler, side, energy, doApply);
    }

    @Override
    public boolean canUpdate()
    {
        return true;
    }

    @Override
    public boolean continueUpdate()
    {
        return getConnectors().size() > 0 && energyBuffer > 0;
    }

    @Override
    public long getRequest()
    {
        if (lastNetworkRequest == -1)
        {
            lastNetworkRequest = 0;

            if (getNodes().size() > 0)
            {
                for (Entry<Object, EnumSet<ForgeDirection>> entry : handlerDirectionMap.entrySet())
                {
                    if (entry.getValue() != null && !(entry.getValue() instanceof IConductor))
                    {
                        for (ForgeDirection direction : entry.getValue())
                        {
                            lastNetworkRequest += Math.max(CompatibilityModule.receiveEnergy(entry.getKey(), direction, Long.MAX_VALUE, false), 0);
                        }
                    }
                }
            }
        }
        return lastNetworkRequest;
    }

    @Override
    public boolean isValidConnector(Object node)
    {
        return node instanceof IConductor;
    }

    @Override
    public float getResistance()
    {
        return resistance;
    }

    /** Clears all cache and reconstruct the network. */
    @Override
    public void reconstruct()
    {
        if (getConnectors().size() > 0)
        {
            // Reset all values related to wires
            getNodes().clear();
            handlerDirectionMap.clear();
            resistance = 0;

            // Iterate threw list of wires
            Iterator<IConductor> it = getConnectors().iterator();

            while (it.hasNext())
            {
                IConductor conductor = it.next();

                if (conductor != null)
                {
                    reconstructConnector(conductor);
                }
                else
                {
                    it.remove();
                }
            }

            if (getNodes().size() > 0)
            {
                NetworkTickHandler.addNetwork(this);
            }
        }
    }

    @Override
    protected void reconstructConnector(IConductor conductor)
    {
        conductor.setNetwork(this);

        if (conductor.getConnections() != null)
        {
            for (int i = 0; i < conductor.getConnections().length; i++)
            {
                reconstructHandler(conductor, conductor.getConnections()[i], ForgeDirection.getOrientation(i).getOpposite());
            }
        }

        resistance += conductor.getResistance();
    }

    /** Segmented out call so overriding can be done when machines are reconstructed. */
    protected void reconstructHandler(IConductor conductor, Object obj, ForgeDirection side)
    {
        if (obj != null && !(obj instanceof IConductor))
        {
            if (CompatibilityModule.canConnect(obj, side, conductor))
            {
                EnumSet<ForgeDirection> set = handlerDirectionMap.get(obj);
                if (set == null)
                {
                    set = EnumSet.noneOf(ForgeDirection.class);
                }
                getNodes().add(obj);
                set.add(side);
                handlerDirectionMap.put(obj, set);
            }
        }
    }

    @Override
    public IEnergyNetwork merge(IEnergyNetwork network)
    {
        IEnergyNetwork newNetwork = super.merge(network);

        if (newNetwork != null)
        {
            long newBuffer = getBuffer() + ((EnergyNetwork) network).getBuffer();
            newNetwork.setBuffer(newBuffer);
            return newNetwork;
        }

        return null;
    }

    @Override
    public void split(IConductor splitPoint)
    {
        energyPerWire = energyBuffer / Math.max(getConnectors().size() - 1, 1);
        super.split(splitPoint);
    }

    @Override
    public void onSplit(IEnergyNetwork newNetwork)
    {
        newNetwork.setBuffer(newNetwork.getBuffer() + energyPerWire);
        energyBuffer -= energyPerWire;
    }

    @Override
    public Class getConnectorClass()
    {
        return IConductor.class;
    }

    @Override
    public IEnergyNetwork newInstance()
    {
        return EnergyNetworkLoader.getNewNetwork();
    }

    @Override
    public long produce(IConductor conductor, ForgeDirection from, long amount, boolean doReceive)
    {
        long energyReceived = 0;
        long conductorBuffer = 0;
        //No energy nothing should happen
        if (amount > 0)
        {
            //Fire event giving other mods a change to interact with this network
            EnergyProduceEvent evt = new EnergyProduceEvent(this, conductor, amount, doReceive);
            MinecraftForge.EVENT_BUS.post(evt);

            if (!evt.isCanceled())
            {
                if (conductorBuffers.containsKey(conductor))
                {
                    conductorBuffer = conductorBuffers.get(conductor);
                }

                energyReceived = Math.min(Math.max(((conductor.getCurrentCapacity() * getVoltage()) - conductorBuffer), 0), amount);

                if (doReceive && energyReceived > 0)
                {
                    energyBuffer += energyReceived;
                    conductorBuffer += energyReceived;
                    conductorBuffers.put(conductor, conductorBuffer);
                }
            }
        }

        if (this.energyBuffer > 0)
            NetworkTickHandler.addNetwork(this);
        return energyReceived;
    }

    /** Assume voltage to be the default voltage for the energy network to calculate energy loss.
     * Energy Loss Forumla: Delta V = I x R; P = I x V; Therefore: P = I^2 x R */
    protected long getEnergyLoss()
    {
        long amperage = getBuffer() / getVoltage();
        return (long) ((amperage * amperage) * resistance);
    }

    public long getVoltage()
    {
        return UniversalElectricity.DEFAULT_VOLTAGE;
    }

    @Override
    public long getBuffer()
    {
        return energyBuffer;
    }

    @Override
    public void setBuffer(long newBuffer)
    {
        energyBuffer = newBuffer;
    }

    @Override
    public long getLastBuffer()
    {
        return lastEnergyBuffer;
    }

    @Override
    public long getBufferOf(IConductor conductor)
    {
        if (conductorBuffers != null && conductorBuffers.containsKey(conductor))
        {
            if (conductorBuffers.get(conductor) != null)
            {
                return conductorBuffers.get(conductor);
            }
        }

        return 0;
    }

    @Override
    public void setBufferFor(IConductor conductor, long buffer)
    {
        conductorBuffers.put(conductor, buffer);
        energyBuffer += buffer;
    }

}
TOP

Related Classes of universalelectricity.core.net.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.