private PowerReceiver getReceiverOnSide(ForgeDirection side) { TileEntity tile = tiles[side.ordinal()]; if (!(tile instanceof IPowerReceptor)) return null; IPowerReceptor receptor = (IPowerReceptor) tile; PowerReceiver receiver = receptor.getPowerReceiver(side.getOpposite()); if (receiver == null) return null; if (!receiver.getType().canReceiveFromPipes()) return null; return receiver; }
private void sendPower() { for (ForgeDirection s : ForgeDirection.VALID_DIRECTIONS) { TileEntity tile = getTileBuffer(s).getTile(); if (tile instanceof IPowerReceptor) { PowerReceiver receptor = ((IPowerReceptor) tile).getPowerReceiver(s.getOpposite()); if (receptor != null) { receptor.receiveEnergy(PowerHandler.Type.ENGINE, energyStored / 10.0, s.getOpposite()); energyStored = 0; } } else if (tile instanceof IEnergyHandler) { int energyUsed = ((IEnergyHandler) tile).receiveEnergy(s.getOpposite(), energyStored, false); energyStored -= energyUsed; } } }
@Override public boolean canPipeConnect(TileEntity tile, ForgeDirection side) { if (tile instanceof TileGenericPipe) { Pipe pipe2 = ((TileGenericPipe) tile).pipe; if (BlockGenericPipe.isValid(pipe2) && !(pipe2.transport instanceof PipeTransportPower)) return false; return true; } if (tile instanceof IPowerReceptor) { IPowerReceptor receptor = (IPowerReceptor) tile; PowerReceiver receiver = receptor.getPowerReceiver(side.getOpposite()); if (receiver != null && receiver.getType().canReceiveFromPipes()) return true; } if (container.pipe instanceof PipePowerWood && tile instanceof IPowerEmitter) { IPowerEmitter emitter = (IPowerEmitter) tile; if (emitter.canEmitPowerFrom(side.getOpposite())) return true; } return false; }
public boolean produceBuildCraft(ForgeDirection outputDirection) { if (!this.worldObj.isRemote && outputDirection != null && outputDirection != ForgeDirection.UNKNOWN) { float provide = this.getProvide(outputDirection); if (this.getEnergyStored() >= provide && provide > 0) { if (Compatibility.isBuildcraftLoaded()) { TileEntity tileEntity = new Vector3(this) .modifyPositionFromSide(outputDirection) .getTileEntity(this.worldObj); if (tileEntity instanceof IPowerReceptor) { PowerReceiver receiver = ((IPowerReceptor) tileEntity).getPowerReceiver(outputDirection.getOpposite()); if (receiver != null) { if (receiver.powerRequest() > 0) { float bc3Provide = provide * Compatibility.TO_BC_RATIO; float energyUsed = Math.min( receiver.receiveEnergy( Type.MACHINE, bc3Provide, outputDirection.getOpposite()), bc3Provide); this.provideElectricity(energyUsed * Compatibility.TO_BC_RATIO, true); } } return true; } } } } return false; }
@Override public void updateEntity() { if (CoreProxy.proxy.isRenderWorld(container.worldObj)) return; step(); init(); // Send the power to nearby pipes who requested it System.arraycopy(displayPower, 0, prevDisplayPower, 0, 6); Arrays.fill(displayPower, 0.0F); for (int i = 0; i < 6; ++i) { if (internalPower[i] > 0) { float totalPowerQuery = 0; for (int j = 0; j < 6; ++j) { if (j != i && powerQuery[j] > 0) if (tiles[j] instanceof TileGenericPipe || tiles[j] instanceof IPowerReceptor) { totalPowerQuery += powerQuery[j]; } } for (int j = 0; j < 6; ++j) { if (j != i && powerQuery[j] > 0) { float watts = 0.0F; PowerReceiver prov = getReceiverOnSide(ForgeDirection.VALID_DIRECTIONS[j]); if (prov != null && prov.powerRequest() > 0) { watts = (internalPower[i] / totalPowerQuery) * powerQuery[j]; watts = prov.receiveEnergy( Type.PIPE, watts, ForgeDirection.VALID_DIRECTIONS[j].getOpposite()); internalPower[i] -= watts; } else if (tiles[j] instanceof TileGenericPipe) { watts = (internalPower[i] / totalPowerQuery) * powerQuery[j]; TileGenericPipe nearbyTile = (TileGenericPipe) tiles[j]; PipeTransportPower nearbyTransport = (PipeTransportPower) nearbyTile.pipe.transport; watts = nearbyTransport.receiveEnergy( ForgeDirection.VALID_DIRECTIONS[j].getOpposite(), watts); internalPower[i] -= watts; } displayPower[j] += watts; displayPower[i] += watts; } } } } double highestPower = 0; for (int i = 0; i < 6; i++) { displayPower[i] = (prevDisplayPower[i] * (DISPLAY_SMOOTHING - 1.0F) + displayPower[i]) / DISPLAY_SMOOTHING; if (displayPower[i] > highestPower) { highestPower = displayPower[i]; } } overload += highestPower > maxPower * 0.95 ? 1 : -1; if (overload < 0) { overload = 0; } if (overload > OVERLOAD_TICKS) { overload = OVERLOAD_TICKS; } // Compute the tiles requesting energy that are not power pipes for (int i = 0; i < 6; ++i) { PowerReceiver prov = getReceiverOnSide(ForgeDirection.VALID_DIRECTIONS[i]); if (prov != null) { float request = prov.powerRequest(); if (request > 0) { requestEnergy(ForgeDirection.VALID_DIRECTIONS[i], request); } } } // Sum the amount of energy requested on each side int[] transferQuery = new int[6]; for (int i = 0; i < 6; ++i) { transferQuery[i] = 0; for (int j = 0; j < 6; ++j) { if (j != i) { transferQuery[i] += powerQuery[j]; } } transferQuery[i] = Math.min(transferQuery[i], maxPower); } // Transfer the requested energy to nearby pipes for (int i = 0; i < 6; ++i) { if (transferQuery[i] != 0) { if (tiles[i] != null) { TileEntity entity = tiles[i]; if (entity instanceof TileGenericPipe) { TileGenericPipe nearbyTile = (TileGenericPipe) entity; if (nearbyTile.pipe == null) { continue; } PipeTransportPower nearbyTransport = (PipeTransportPower) nearbyTile.pipe.transport; nearbyTransport.requestEnergy( ForgeDirection.VALID_DIRECTIONS[i].getOpposite(), transferQuery[i]); } } } } if (tracker.markTimeIfDelay(container.worldObj, 2 * BuildCraftCore.updateFactor)) { PacketPowerUpdate packet = new PacketPowerUpdate(container.xCoord, container.yCoord, container.zCoord); double displayFactor = MAX_DISPLAY / 1024.0; for (int i = 0; i < clientDisplayPower.length; i++) { clientDisplayPower[i] = (short) (displayPower[i] * displayFactor + .9999); } packet.displayPower = clientDisplayPower; packet.overload = isOverloaded(); CoreProxy.proxy.sendToPlayers( packet.getPacket(), container.worldObj, container.xCoord, container.yCoord, container.zCoord, DefaultProps.PIPE_CONTENTS_RENDER_DIST); } }
/** * 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; }