private static double emit_do_do( TileEntityElectricBlock from, TileEntity tileEntity, ForgeDirection side, double currentSending, boolean tryAgain) { double sent = 0; if (tileEntity instanceof IStrictEnergyAcceptor) { IStrictEnergyAcceptor acceptor = (IStrictEnergyAcceptor) tileEntity; if (acceptor.canReceiveEnergy(side.getOpposite())) { sent += acceptor.transferEnergyToAcceptor(side.getOpposite(), currentSending); } } else if (MekanismUtils.useRF() && tileEntity instanceof IEnergyHandler) { IEnergyHandler handler = (IEnergyHandler) tileEntity; if (handler.canConnectEnergy(side.getOpposite())) { int used = handler.receiveEnergy( side.getOpposite(), (int) Math.round(currentSending * Mekanism.TO_TE), false); sent += used * Mekanism.FROM_TE; } } else if (MekanismUtils.useIC2() && tileEntity instanceof IEnergySink) { if (((IEnergySink) tileEntity).acceptsEnergyFrom(from, side.getOpposite())) { double toSend = Math.min( currentSending, EnergyNet.instance.getPowerFromTier(((IEnergySink) tileEntity).getSinkTier()) * Mekanism.FROM_IC2); toSend = Math.min(toSend, ((IEnergySink) tileEntity).getDemandedEnergy() * Mekanism.FROM_IC2); sent += (toSend - (((IEnergySink) tileEntity) .injectEnergy(side.getOpposite(), toSend * Mekanism.TO_IC2, 0) * Mekanism.FROM_IC2)); } } else if (MekanismUtils.useBuildCraft() && MjAPI.getMjBattery(tileEntity, MjAPI.DEFAULT_POWER_FRAMEWORK, side.getOpposite()) != null && !tryAgain) { IBatteryObject battery = MjAPI.getMjBattery(tileEntity, MjAPI.DEFAULT_POWER_FRAMEWORK, side.getOpposite()); double toSend = battery.addEnergy( Math.min(battery.getEnergyRequested(), currentSending * Mekanism.TO_BC)); sent += toSend * Mekanism.FROM_BC; } return sent; }
public static boolean isConnectable(TileEntity orig, TileEntity tileEntity, ForgeDirection side) { if (tileEntity instanceof IGridTransmitter) { return false; } if (tileEntity instanceof IStrictEnergyAcceptor) { if (((IStrictEnergyAcceptor) tileEntity).canReceiveEnergy(side.getOpposite())) { return true; } } else if (MekanismUtils.useIC2() && tileEntity instanceof IEnergyAcceptor) { if (((IEnergyAcceptor) tileEntity).acceptsEnergyFrom(orig, side.getOpposite())) { return true; } } else if (tileEntity instanceof ICableOutputter) { if (((ICableOutputter) tileEntity).canOutputTo(side.getOpposite())) { return true; } } else if (MekanismUtils.useRF() && tileEntity instanceof IEnergyHandler) { if (((IEnergyHandler) tileEntity).canConnectEnergy(side.getOpposite())) { return true; } } else if (MekanismUtils.useBuildCraft()) { if (MjAPI.getMjBattery(tileEntity, MjAPI.DEFAULT_POWER_FRAMEWORK, side.getOpposite()) != null) { return true; } } return false; }
public static boolean isEnergyAcceptor(TileEntity tileEntity) { return (tileEntity instanceof IStrictEnergyAcceptor || (MekanismUtils.useIC2() && tileEntity instanceof IEnergySink) || (MekanismUtils.useBuildCraft() && MjAPI.getMjBattery(tileEntity) != null && !(tileEntity instanceof IGridTransmitter)) || (MekanismUtils.useRF() && tileEntity instanceof IEnergyHandler)); }
/** Refresh all energy acceptors in the network */ private void refreshAcceptors() { this.connectedAcceptors.clear(); this.connectedDirections.clear(); this.refreshWithChecks(); try { LinkedList<IConductor> conductorsCopy = new LinkedList(); conductorsCopy.addAll(this.conductors); // 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 : conductorsCopy) { final TileEntity[] adjacentConnections = EnergyUtil.getAdjacentPowerConnections((TileEntity) conductor); for (int i = 0; i < 6; i++) { TileEntity acceptor = adjacentConnections[i]; if (!(acceptor instanceof IConductor) && acceptor != null && !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 ^ 1); if (acceptor instanceof IElectrical) { if (((IElectrical) acceptor).canConnect(sideFrom, NetworkType.POWER)) { this.connectedAcceptors.add(acceptor); this.connectedDirections.add(sideFrom); } } else if ((isRF2Loaded && acceptor instanceof IEnergyReceiver) || (isRF1Loaded && acceptor instanceof IEnergyHandler)) { if (((IEnergyConnection) acceptor).canConnectEnergy(sideFrom)) { 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 (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(); } }
/** * 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()) { 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); TileEntity debugTE = null; try { for (TileEntity tileEntity : this.availableAcceptors) { debugTE = tileEntity; // 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 (isRF2Loaded && tileEntity instanceof IEnergyReceiver) { final int currentSendinginRF = (currentSending >= Integer.MAX_VALUE / EnergyConfigHandler.TO_RF_RATIO) ? Integer.MAX_VALUE : (int) (currentSending * EnergyConfigHandler.TO_RF_RATIO); sentToAcceptor = ((IEnergyReceiver) tileEntity).receiveEnergy(sideFrom, currentSendinginRF, false) / EnergyConfigHandler.TO_RF_RATIO; } else if (isMekLoaded && tileEntity instanceof IStrictEnergyAcceptor) { sentToAcceptor = (float) ((IStrictEnergyAcceptor) tileEntity) .transferEnergyToAcceptor( sideFrom, currentSending * EnergyConfigHandler.TO_MEKANISM_RATIO) / EnergyConfigHandler.TO_MEKANISM_RATIO; } else if (isRF1Loaded && tileEntity instanceof IEnergyHandler) { final int currentSendinginRF = (currentSending >= Integer.MAX_VALUE / EnergyConfigHandler.TO_RF_RATIO) ? Integer.MAX_VALUE : (int) (currentSending * EnergyConfigHandler.TO_RF_RATIO); sentToAcceptor = ((IEnergyHandler) tileEntity).receiveEnergy(sideFrom, currentSendinginRF, false) / EnergyConfigHandler.TO_RF_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.TO_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.TO_BC_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.TO_BC_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; } } catch (Exception e) { GCLog.severe("DEBUG Energy network loop issue, please report this"); if (debugTE != null) GCLog.severe( "Problem was likely caused by tile in dim " + debugTE.getWorldObj().provider.dimensionId + " at " + debugTE.xCoord + "," + debugTE.yCoord + "," + debugTE.zCoord + " Type:" + debugTE.getClass().getSimpleName()); } } 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; }
/** * Refreshes all tiles in network, and updates requested energy * * @param ignoreTiles TileEntities to ignore for energy calculations. */ private void doTickStartCalc() { this.tickDone = EnergyNetwork.tickCount; this.totalSent = 0F; this.refreshAcceptors(); if (!EnergyUtil.initialisedIC2Methods) { EnergyUtil.initialiseIC2Methods(); } if (this.conductors.size() == 0) { return; } this.loopPrevention = true; this.availableAcceptors.clear(); this.availableconnectedDirections.clear(); this.energyRequests.clear(); this.totalRequested = 0.0F; this.totalStorageExcess = 0F; 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 (isRF2Loaded && acceptor instanceof IEnergyReceiver) { e = ((IEnergyReceiver) acceptor).receiveEnergy(sideFrom, Integer.MAX_VALUE, true) / EnergyConfigHandler.TO_RF_RATIO; } else if (isMekLoaded && acceptor instanceof IStrictEnergyAcceptor) { e = (float) ((((IStrictEnergyAcceptor) acceptor).getMaxEnergy() - ((IStrictEnergyAcceptor) acceptor).getEnergy()) / EnergyConfigHandler.TO_MEKANISM_RATIO); } else if (isRF1Loaded && acceptor instanceof IEnergyHandler) { e = ((IEnergyHandler) acceptor).receiveEnergy(sideFrom, Integer.MAX_VALUE, true) / EnergyConfigHandler.TO_RF_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.TO_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.TO_BC_RATIO; } else if (isBCLoaded && acceptor instanceof IPowerReceptor) // Legacy BC API { PowerReceiver BCreceiver = ((IPowerReceptor) acceptor).getPowerReceiver(sideFrom); if (BCreceiver != null) { e = (float) BCreceiver.powerRequest() / EnergyConfigHandler.TO_BC_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; }