made the node factory stuff nicer to use. the backing code has become somewhat ugly, but that's just java's fault so whatever. it is now possible to write something along the lines of api.Network.newNode(host, name, visibility).withComponent().withConnector(bufferSize).create(), which reads pretty nicely; power is back, but with a few changes. for one, the "running cost" is gone, since that was really just confusing, and would have resulted in frequent updates once the buffers are full/empty anyway (once because we'd have to check whether to fill up or not, once to check if we have enough power or not). it's just much more intuitive to just have a buffer per powered entity that can be filled/emptied as needed. also, there's no differentiation between consumers and producers anymore. producers just fill up their buffers, while consumers empty their buffers. the power distributor now simply takes care of balancing the amount of energy in all buffers connected to the same network it is connected to. multiple distributors don't need any special logic this way, either, since the first one to update simply marks all processed buffers as clean (if they were dirty due to changes); renamed PowerSupply to PowerConverter

This commit is contained in:
Florian Nücke 2013-11-04 00:26:56 +01:00
parent f9e6439704
commit 734b1bd43f
18 changed files with 357 additions and 600 deletions

View File

@ -2,6 +2,8 @@ oc.block.Adapter.name=Adapter
oc.block.Computer.name=Computer
oc.block.DiskDrive.name=Diskettenlaufwerk
oc.block.Keyboard.name=Tastatur
oc.block.PowerConverter.name=Leistungswandler
oc.block.PowerDistributor.name=Stromverteiler
oc.block.ScreenAdvanced.name=Hochwertiger Bildschirm
oc.block.ScreenBasic.name=Einfacher Bildschirm
oc.block.ScreenProfessional.name=Professioneller Bildschirm

View File

@ -2,6 +2,8 @@ oc.block.Adapter.name=Adapter
oc.block.Computer.name=Computer
oc.block.DiskDrive.name=Disk Drive
oc.block.Keyboard.name=Keyboard
oc.block.PowerConverter.name=Power Converter
oc.block.PowerDistributor.name=Power Distributor
oc.block.ScreenAdvanced.name=Advanced Screen
oc.block.ScreenBasic.name=Basic Screen
oc.block.ScreenProfessional.name=Professional Screen

View File

@ -0,0 +1,27 @@
package li.cil.oc.api.detail;
import li.cil.oc.api.network.Component;
import li.cil.oc.api.network.ComponentConnector;
import li.cil.oc.api.network.Connector;
import li.cil.oc.api.network.Node;
public interface Builder<T extends Node> {
T create();
public static interface NodeBuilder extends Builder<Node> {
ComponentBuilder withComponent();
ConnectorBuilder withConnector(double bufferSize);
}
static interface ComponentBuilder extends Builder<Component> {
ComponentConnectorBuilder withConnector(double bufferSize);
}
static interface ConnectorBuilder extends Builder<Connector> {
ComponentConnectorBuilder withComponent();
}
static interface ComponentConnectorBuilder extends Builder<ComponentConnector> {
}
}

View File

@ -0,0 +1,7 @@
package li.cil.oc.api.network;
/**
* For nodes that are both component and connector.
*/
public interface ComponentConnector extends Component, Connector {
}

View File

@ -0,0 +1,59 @@
package li.cil.oc.api.network;
/**
* Interface for nodes that act as power connectors between their network and
* some power producer or consumer.
* <p/>
* For each connector a buffer is managed. Its size is initialized via the
* factory function in the network API, but can also be configured later on.
* Its current fill level can be queried and manipulated as desired.
* <p/>
* Each connector can take two roles: it can be a <em>producer</em>, feeding
* power into the network, or it can be a <em>consumer</em>, requiring power
* from the network to power something (or it can be both). This depends
* entirely on how you call {@link #changeBuffer}, i.e. on whether you
* fill up the connectors buffer or drain it.
* <p/>
* To feed power into the network, simply fill up the buffer, to consume power
* take power from the buffer. The network will balance the power between all
* buffers connected to it. The algorithm goes as follows: if there was a change
* to some buffer, computer the average power available in all buffers. Build
* two sets: those of buffers with above-average level, and those with below-
* average fill. From all above-average buffers take so much energy that they
* remain just above average fill (but only take integral values - this is to
* avoid floating point errors causing trouble). Distribute the collected energy
* equally among the below-average buffers (as good as possible).
*/
public interface Connector extends Node {
/**
* The size of the buffer.
*/
double bufferSize();
/**
* The power stored in the buffer.
*/
double buffer();
/**
* Try to apply the specified delta to the buffer.
* <p/>
* This can be used to apply reactionary power changes. For example, a
* screen may require a certain amount of power to refresh its display when
* a program tries to display text on it. For running costs just apply the
* same delta each tick.
* <p/>
* For negative values, if there is not enough power stored in the buffer
* this will return <tt>false</tt>, and the operation depending on the power
* should fail.
* <p/>
* For positive values, if there is a buffer overflow due to the added power
* the surplus will be lost and this will return <tt>false</tt>.
* <p/>
* If there is enough power or no overflow this will return <tt>true</tt>.
*
* @param delta the amount of power to consume or make available.
* @return whether the power could be consumed or stored.
*/
boolean changeBuffer(double delta);
}

View File

@ -1,7 +0,0 @@
package li.cil.oc.api.network;
/**
* Node type used by by power consumers.
*/
public interface Consumer {
}

View File

@ -1,7 +0,0 @@
package li.cil.oc.api.network;
/**
* Node type used by power producers.
*/
public interface Producer {
}

View File

@ -1,20 +0,0 @@
package li.cil.oc.api.power
trait Producer extends Receiver {
// demand = 0
//
// def powerDemand: Double = provider match {
// case Some(p) => p.getDemand
// case _ => 0
// }
//
// def maxEnergy: Double = provider match {
// case Some(p) => p.MAXENERGY
// case _ => 0
// }
//
// def addEnergy(amount: Double) = provider match {
// case Some(p) => p.addEnergy(amount)
// case _ =>
// }
}

View File

@ -1,179 +0,0 @@
package li.cil.oc.api.power
import li.cil.oc.api.network.{Message, Node}
import net.minecraft.nbt.NBTTagCompound
import scala.collection.mutable
trait Provider {
//
// var isActive = false
// var updateNodes = false
// var energyDemand = 0.0
// var storedEnergy = 0.0
// var MAXENERGY: Double = 2000.0
//
// var energyStorageList = mutable.Set[EnergyStorage]()
//
// override def receive(message: Message): Array[AnyRef] = Option(super.receive(message)).orElse {
// if (message.source != this) {
// message.name match {
// case "system.connect" => {
// message.source match {
// case distributor: Provider =>
// //if other powerDistributor connected and is active set inactive
// if (distributor.isActive) {
// isActive = false
// println("demand now (disabled) " + 0)
// }
// case _ =>
// }
// }
// case "power.find" => {
// message.source match {
// case distributor: Provider =>
// if (isActive) {
// message.cancel()
// return Array(this)
// }
// case _ =>
// }
// }
// case "system.disconnect" => {
// message.source match {
// case distributor: Provider =>
// println("distri disc recieved")
// if (distributor.isActive) {
// searchMain()
// }
// case _ =>
// }
// }
// case _ => // Ignore.
// }
// }
// None
// }.orNull
//
// override protected def onConnect() {
// //check if other distributors already are in the network
// searchMain()
// super.onConnect()
// }
//
// override abstract def readFromNBT(nbt: NBTTagCompound) = {
// super.load(nbt)
// storedEnergy = nbt.getDouble("storedEnergy")
// }
//
// override abstract def writeToNBT(nbt: NBTTagCompound) = {
// super.save(nbt)
// nbt.setDouble("storedEnergy", storedEnergy)
// }
//
// /**
// * Connect a reciever to the provider
// * @param receiver
// * @param amount
// */
// def connectNode(receiver: Receiver, amount: Double) {
// if (!energyStorageList.exists(_.node == receiver)) {
// energyStorageList += new EnergyStorage(receiver, amount)
// energyDemand += amount
// updateNodes = true
// }
//
// if (isActive)
// println("demand now (connect)" + energyDemand)
// }
//
// /**
// * Updates the demand of the node to the given value
// * @param receiver
// * @param demand
// */
// def updateDemand(receiver: Receiver, demand: Double) {
// energyStorageList.filter(n => n.node == receiver).foreach(n => {
// energyDemand -= n.amount
// energyDemand += demand
// n.amount = demand
// })
// if (isActive)
// println("demand now (update)" + energyDemand)
// }
//
// def disconnectNode(receiver: Receiver) {
// energyStorageList.clone().foreach(e => {
// if (e == null || receiver == null) {
// println("something null")
//
// }
// else if (e.node == receiver) {
// energyStorageList -= e
// energyDemand -= e.amount
// if (isActive) {
// receiver.isReceivingPower = false
// updateNodes = true
// }
// }
//
// })
// if (isActive)
// println("demand now (disc) " + energyDemand)
// }
//
// private var hasEnergy = false
// override def update() {
// super.update()
// //check if is main
// if (isActive) {
// //if enough energy is available to supply all receivers
// if (storedEnergy > energyDemand) {
// storedEnergy -= energyDemand
// if (!hasEnergy)
// updateNodes = true
// hasEnergy = true
// println("energy level now " + storedEnergy)
// }
// else {
// if (hasEnergy)
// updateNodes = true
// hasEnergy = false
// }
// //if nodes must be updated send message to them
// if (updateNodes) {
// if (hasEnergy)
// energyStorageList.foreach(storage => storage.node.isReceivingPower = true)
// else
// energyStorageList.foreach(storage => storage.node.isReceivingPower = false)
// updateNodes = false
// }
// }
// }
//
// def getDemand = {
// MAXENERGY - storedEnergy max 0.0
// }
//
// def addEnergy(amount: Double) {
// storedEnergy += amount
// }
//
// def searchMain() {
// network.foreach(_.sendToReachable(this, "power.find") match {
// case Array(powerDistributor: Provider) => {
// println("found other distri")
// isActive = false
// }
// case _ => {
// println("no other")
// isActive = true
// updateNodes = true
// println("demand now (new main) " + energyDemand)
// }
// })
// }
//
// class EnergyStorage(var node: Receiver, var amount: Double)
//
}

View File

@ -1,114 +0,0 @@
package li.cil.oc.api.power
import li.cil.oc.api.network.{Message, Node}
import net.minecraft.nbt.NBTTagCompound
import scala.collection.mutable
trait Receiver {
// def demand = _demand
//
// def demand_=(value: Double) = if (value != _demand) {
// providers.foreach(_.updateDemand(this, value))
// _demand = value
// }
//
// def provider: Option[Provider] = providers.find(_.isActive)
//
// /**
// * Called when the receiver has enough power to operate.
// */
// def onPowerAvailable() {
// println("received energy")
// }
//
// /**
// * Called when the receiver has no power to operate. This can happen at a later time
// * then unConnect was called, because of the internal capacity
// */
// def onPowerUnavailable() {
// println("no more energy")
// }
//
// // ----------------------------------------------------------------------- //
//
// override def receive(message: Message) = Option(super.receive(message)).orElse {
// message.name match {
// case "system.connect" => {
// message.source match {
// case p: Provider => {
// if (providers.add(p)) {
// p.connectNode(this, _demand)
// }
// }
// case _ =>
// }
// }
// case "system.disconnect" => {
// message.source match {
// case p: Provider => {
// if (providers.remove(p)) {
// p.disconnectNode(this)
// }
// }
// case _ =>
// }
// }
// case _ =>
// }
// None
// }.orNull
//
// override protected def onDisconnect() {
// super.onDisconnect()
// providers.foreach(_.disconnectNode(this))
// }
//
// // ----------------------------------------------------------------------- //
//
// override abstract def readFromNBT(nbt: NBTTagCompound) {
// super.load(nbt)
// buffer = nbt.getDouble("buffer")
// }
//
// override abstract def writeToNBT(nbt: NBTTagCompound) {
// super.save(nbt)
// nbt.setDouble("buffer", buffer)
// }
//
// // ----------------------------------------------------------------------- //
//
// private var _demand = 2.0
// private val providers = mutable.Set.empty[Provider]
// private var buffer = 0.0
// private val maxBuffer = 100.0
// private var isPowerAvailable = false
//
// /** Set from the provider whenever its power state changes. */
// private[power] var isReceivingPower = false
//
// override def update() {
// super.update()
// //if has enough energy to operate
// if (isReceivingPower) {
// //increase buffer
// // TODO maybe make the speed of the "cooldown" dependent on the demand?
// // TODO another possibility: increase the demand dynamically while charging?
// if (maxBuffer > buffer + 1)
// buffer += 1
// //notify if energy wasn't available before
// if (!isPowerAvailable) {
// isPowerAvailable = true
// onPowerAvailable()
// }
// }
// //continue running until we are out of energy
// else if (buffer >= demand) {
// buffer -= demand
// }
// else if (isPowerAvailable) {
// isPowerAvailable = false
// onPowerUnavailable()
// }
// }
}

View File

@ -2,23 +2,24 @@ package li.cil.oc.client.renderer.tileentity
import li.cil.oc.Config
import li.cil.oc.common.tileentity
import li.cil.oc.util.RenderState
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer
import net.minecraft.tileentity.TileEntity
import net.minecraft.util.ResourceLocation
import org.lwjgl.opengl.GL11
import li.cil.oc.util.RenderState
object PowerDistributorRenderer extends TileEntitySpecialRenderer {
private val sideOn = new ResourceLocation(Config.resourceDomain, "textures/blocks/power_distributor_on.png")
override def renderTileEntityAt(tileEntity: TileEntity, x: Double, y: Double, z: Double, f: Float) = {
val distributor = tileEntity.asInstanceOf[tileentity.PowerDistributor]
if (false /*distributor.isActive*/) {
val balancer = tileEntity.asInstanceOf[tileentity.PowerDistributor]
if (balancer.average > 0) {
GL11.glPushAttrib(0xFFFFFF)
RenderState.disableLighting()
RenderState.makeItBlend()
RenderState.setBlendAlpha(balancer.average.toFloat)
GL11.glPushMatrix()

View File

@ -8,13 +8,12 @@ import net.minecraft.util.Icon
import net.minecraft.world.World
import net.minecraftforge.common.ForgeDirection
class PowerSupply(val parent: SimpleDelegator) extends SimpleDelegate {
GameRegistry.registerTileEntity(classOf[tileentity.PowerSupply], "oc.powersupply")
val unlocalizedName = "PowerSupply"
class PowerConverter(val parent: SimpleDelegator) extends SimpleDelegate {
GameRegistry.registerTileEntity(classOf[tileentity.PowerConverter], "oc.power_converter")
val unlocalizedName = "PowerConverter"
override def breakBlock(world: World, x: Int, y: Int, z: Int, blockId: Int) = {
world.getBlockTileEntity(x, y, z).asInstanceOf[tileentity.PowerSupply].onUnload()
}
override def breakBlock(world: World, x: Int, y: Int, z: Int, blockId: Int) =
world.getBlockTileEntity(x, y, z).asInstanceOf[tileentity.PowerConverter].unload()
// ----------------------------------------------------------------------- //
@ -38,5 +37,5 @@ class PowerSupply(val parent: SimpleDelegator) extends SimpleDelegate {
override def hasTileEntity = true
override def createTileEntity(world: World) = Some(new tileentity.PowerSupply)
override def createTileEntity(world: World) = Some(new tileentity.PowerConverter)
}

View File

@ -9,8 +9,7 @@ import net.minecraft.world.{IBlockAccess, World}
import net.minecraftforge.common.ForgeDirection
class PowerDistributor(val parent: SimpleDelegator) extends SimpleDelegate {
GameRegistry.registerTileEntity(classOf[tileentity.PowerDistributor], "oc.powerdistributor")
GameRegistry.registerTileEntity(classOf[tileentity.PowerDistributor], "oc.power_distributor")
val unlocalizedName = "PowerDistributor"
// ----------------------------------------------------------------------- //

View File

@ -0,0 +1,140 @@
package li.cil.oc.common.tileentity
import buildcraft.api.power.{PowerHandler, IPowerReceptor}
import ic2.api.energy.event.{EnergyTileLoadEvent, EnergyTileUnloadEvent}
import ic2.api.energy.tile.IEnergySink
import li.cil.oc.api
import li.cil.oc.api.network._
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.tileentity.TileEntity
import net.minecraftforge.common.{ForgeDirection, MinecraftForge}
import universalelectricity.core.block.IElectrical
import universalelectricity.core.electricity.ElectricityPack
class PowerConverter extends Rotatable with Environment with IEnergySink with IPowerReceptor with IElectrical {
val node = api.Network.newNode(this, "power_converter", Visibility.Network).
withConnector(128).
create()
private var addedToEnet = false
private var lastPacketSize = 0.0
private var powerHandler: PowerHandler = null
private def demand = node.bufferSize - node.buffer
// ----------------------------------------------------------------------- //
// Energy conversion ratios, Mode -> Internal
val ratioIndustrialCraft = 2
val ratioBuildCraft = 5
val ratioUniversalElectricity = 5
// ----------------------------------------------------------------------- //
override def updateEntity() {
super.updateEntity()
if (!worldObj.isRemote) {
if (!addedToEnet) {
MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this))
addedToEnet = true
}
if (demand > 0) {
node.changeBuffer(getPowerProvider.useEnergy(1, demand.toFloat / ratioBuildCraft, true) * ratioBuildCraft)
}
}
}
override def onChunkUnload() {
super.onChunkUnload()
unload()
}
def unload() {
if (addedToEnet) {
MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this))
addedToEnet = false
}
}
// ----------------------------------------------------------------------- //
override def readFromNBT(nbt: NBTTagCompound) = {
super.readFromNBT(nbt)
node.load(nbt)
getPowerProvider.readFromNBT(nbt)
}
override def writeToNBT(nbt: NBTTagCompound) = {
super.writeToNBT(nbt)
node.save(nbt)
getPowerProvider.writeToNBT(nbt)
}
// ----------------------------------------------------------------------- //
// IndustrialCraft
override def acceptsEnergyFrom(emitter: TileEntity, direction: ForgeDirection) = true
override def getMaxSafeInput = Integer.MAX_VALUE
override def demandedEnergyUnits = {
// We try to avoid requesting energy when we need less than what we get with
// a single packet. However, if our buffer gets dangerously low we will ask
// for energy even if there's the danger of wasting some energy.
if (demand >= lastPacketSize * ratioIndustrialCraft || demand > node.bufferSize * 0.5) {
demand
} else 0
}
override def injectEnergyUnits(directionFrom: ForgeDirection, amount: Double) = {
lastPacketSize = amount
node.changeBuffer(amount * ratioIndustrialCraft)
0
}
// ----------------------------------------------------------------------- //
// BuildCraft
def getPowerProvider = {
if (powerHandler == null) {
powerHandler = new PowerHandler(this, PowerHandler.Type.STORAGE)
if (powerHandler != null) {
powerHandler.configure(1, 320, Float.MaxValue, node.bufferSize.toFloat / ratioBuildCraft)
}
}
powerHandler
}
def getPowerReceiver(side: ForgeDirection) = getPowerProvider.getPowerReceiver
def getWorld = worldObj
def doWork(workProvider: PowerHandler) {}
// ----------------------------------------------------------------------- //
// Universal Electricity
def canConnect(direction: ForgeDirection) = true
def getVoltage = 120f
def getRequest(direction: ForgeDirection) = demand.toFloat / ratioUniversalElectricity
def receiveElectricity(from: ForgeDirection, receive: ElectricityPack, doReceive: Boolean) = {
if (receive != null) {
if (doReceive) {
node.changeBuffer(receive.getWatts * ratioUniversalElectricity)
}
receive.getWatts
} else 0
}
def getProvide(direction: ForgeDirection) = 0f
def provideElectricity(from: ForgeDirection, request: ElectricityPack, doProvide: Boolean) = null
}

View File

@ -1,50 +1,88 @@
package li.cil.oc.common.tileentity
import li.cil.oc.api
import li.cil.oc.api.network._
import li.cil.oc.api.power.Provider
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.server.network.Connector
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import net.minecraft.nbt.NBTTagCompound
import scala.collection.convert.WrapAsScala._
import scala.collection.mutable
class PowerDistributor extends Rotatable with Provider {
class PowerDistributor extends Rotatable with Environment {
val node = api.Network.newNode(this, "power_distributor", Visibility.Network).
create()
//MAXENERGY = 2000.0.toDouble
val connectors = mutable.Set.empty[Connector]
// override val name = "powerdistributor"
var average = 0.0
// override val visibility = Visibility.Network
// ----------------------------------------------------------------------- //
override def updateEntity() {
super.updateEntity()
update()
if (!worldObj.isRemote && connectors.exists(_.dirty)) {
computeAverage()
// Adjust buffer fill ratio for all buffers to average.
connectors.foreach(c => c.buffer = c.bufferSize * average)
}
}
override def validate() {
super.validate()
if (worldObj.isRemote) ClientPacketSender.sendPowerStateRequest(this)
}
// ----------------------------------------------------------------------- //
override def onDisconnect(node: Node) {
super.onDisconnect(node)
if (node == this.node) {
connectors.clear()
average = -1
}
else node match {
case connector: Connector =>
connectors -= connector
computeAverage()
case _ =>
}
}
override def onConnect(node: Node) {
super.onConnect(node)
if (node == this.node) {
for (node <- node.network.nodes) node match {
case connector: Connector => connectors += connector
case _ =>
}
computeAverage()
}
else node match {
case connector: Connector => connectors += connector
case _ =>
}
}
// ----------------------------------------------------------------------- //
override def readFromNBT(nbt: NBTTagCompound) {
super[Rotatable].readFromNBT(nbt)
// super.readFromNBT(nbt)
node.load(nbt)
}
override def writeToNBT(nbt: NBTTagCompound) {
super[Rotatable].writeToNBT(nbt)
// super.save(nbt)
node.save(nbt)
}
// ----------------------------------------------------------------------- //
def receive(message: Message) = null
def update() {}
def save(nbt: NBTTagCompound) {}
def load(nbt: NBTTagCompound) {}
def address() = null
def host() = null
def network() = null
def reachability() = Visibility.None
private def computeAverage() {
// Computer average fill ratio of all buffers.
average = connectors.foldRight(0.0)((c, acc) => {
c.dirty = false // clear dirty flag for all connectors
acc + (c.buffer / c.bufferSize)
}) / (connectors.size max 1) // avoid NaNs
ServerPacketSender.sendPowerState(this)
}
}

View File

@ -1,232 +0,0 @@
package li.cil.oc.common.tileentity
import buildcraft.api.power.{PowerHandler, IPowerReceptor}
import cpw.mods.fml.common.FMLCommonHandler
import ic2.api.energy.event.{EnergyTileLoadEvent, EnergyTileUnloadEvent}
import ic2.api.energy.tile.IEnergySink
import li.cil.oc.api.network._
import li.cil.oc.api.power.Producer
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.tileentity.TileEntity
import net.minecraft.world.World
import net.minecraftforge.common.{ForgeDirection, MinecraftForge}
import universalelectricity.core.block.IElectrical
import universalelectricity.core.electricity.ElectricityPack
class PowerSupply extends Rotatable with Producer with IEnergySink with IPowerReceptor with IElectrical {
var addedToEnet = false
var powerHandler: PowerHandler = null
// override val name = "powersupply"
// override val visibility = Visibility.Network
override def onChunkUnload() {
super.onChunkUnload()
onUnload()
}
def onUnload() {
if (addedToEnet) {
MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this))
addedToEnet = false
}
}
override def updateEntity() {
super.updateEntity()
// update()
if (!addedToEnet) {
onLoaded()
}
if (!FMLCommonHandler.instance.getEffectiveSide.isClient) {
// addEnergy((getPowerProvider().useEnergy(1, powerDemand.toFloat / 5.0f, true) * 5).toDouble)
}
}
override def readFromNBT(nbt: NBTTagCompound) = {
super[Rotatable].readFromNBT(nbt)
// super.load(nbt)
getPowerProvider().readFromNBT(nbt)
}
override def writeToNBT(nbt: NBTTagCompound) = {
super[Rotatable].writeToNBT(nbt)
// super.save(nbt)
getPowerProvider().writeToNBT(nbt)
}
/**
* Notification that the TileEntity finished loaded, for advanced uses.
* Either onUpdateEntity or onLoaded have to be used.
*/
def onLoaded() {
if (!addedToEnet && !FMLCommonHandler.instance.getEffectiveSide.isClient) {
MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this))
addedToEnet = true
}
}
var lastInjectedEnergy = 0.0
//IC2 stuff
/**
* Determine how much energy the sink accepts.
*
* This value is unrelated to getMaxSafeInput().
*
* Make sure that injectEnergy() does accepts energy if demandsEnergy() returns anything > 0.
*
* @return max accepted input in eu
*/
override def demandedEnergyUnits: Double = {
//
// val needed = powerDemand
// if (needed > lastInjectedEnergy || needed > (maxEnergy / 2.0)) {
// return needed / 2
// }
0.0
}
/**
* Transfer energy to the sink.
*
* It's highly recommended to accept all energy by letting the internal buffer overflow to
* increase the performance and accuracy of the distribution simulation.
*
* @param directionFrom direction from which the energy comes from
* @param amount energy to be transferred
* @return Energy not consumed (leftover)
*/
override def injectEnergyUnits(directionFrom: ForgeDirection, amount: Double): Double = {
lastInjectedEnergy = amount * 2.0
// addEnergy(amount * 2.0)
0
}
/**
* Determine the amount of eu which can be safely injected into the specific energy sink without exploding.
*
* Typical values are 32 for LV, 128 for MV, 512 for HV and 2048 for EV. A value of Integer.MAX_VALUE indicates no
* limit.
*
* This value is unrelated to demandsEnergy().
*
* @return max safe input in eu
*/
override def getMaxSafeInput: Int = Integer.MAX_VALUE
/**
* Determine if this acceptor can accept current from an adjacent emitter in a direction.
*
* The TileEntity in the emitter parameter is what was originally added to the energy net,
* which may be normal in-world TileEntity, a delegate or an IMetaDelegate.
*
* @param emitter energy emitter
* @param direction direction the energy is being received from
*/
override def acceptsEnergyFrom(emitter: TileEntity, direction: ForgeDirection): Boolean = true
//*******************BUILDCRAFT**********************************//
/**
* Get the PowerReceiver for this side of the block. You can return the same PowerReceiver for
* all sides or one for each side.
*
* You should NOT return null to this method unless you mean to NEVER receive power from that
* side. Returning null, after previous returning a PowerReceiver, will most likely cause pipe
* connections to derp out and engines to eventually explode.
*
* @param side
* @return
*/
def getPowerReceiver(side: ForgeDirection): PowerHandler#PowerReceiver = {
getPowerProvider().getPowerReceiver
}
def getPowerProvider(): PowerHandler = {
if (powerHandler == null) {
powerHandler = new PowerHandler(this, PowerHandler.Type.STORAGE);
if (powerHandler != null) {
powerHandler.configure(1.0F, 320.0F, 800.0F, 640.0F);
}
}
powerHandler;
}
/**
* Call back from the PowerHandler that is called when the stored power exceeds the activation
* power.
*
* It can be triggered by update() calls or power modification calls.
*
* @param workProvider
*/
def doWork(workProvider: PowerHandler) {
}
def getWorld: World = worldObj
/** * UE*************************
*
*/
/**
* Adds electricity to an block. Returns the quantity of electricity that was accepted. This
* should always return 0 if the block cannot be externally charged.
*
* @param from Orientation the electricity is sent in from.
* @param receive Maximum amount of electricity to be sent into the block.
* @param doReceive If false, the charge will only be simulated.
* @return Amount of energy that was accepted by the block.
*/
def receiveElectricity(from: ForgeDirection, receive: ElectricityPack, doReceive: Boolean): Float = {
if (receive == null) return 0.0F
if (doReceive) {
val energy = receive.getWatts / 0.2F
// addEnergy(energy.toDouble)
}
receive.getWatts
}
/**
* Adds electricity to an block. Returns the ElectricityPack, the electricity provided. This
* should always return null if the block cannot be externally discharged.
*
* @param from Orientation the electricity is requested from.
* @param request Maximum amount of energy to be sent into the block.
* @param doProvide If false, the charge will only be simulated.
* @return Amount of energy that was given out by the block.
*/
def provideElectricity(from: ForgeDirection, request: ElectricityPack, doProvide: Boolean): ElectricityPack = null
/**
* @return How much energy does this TileEntity want?
*/
def getRequest(direction: ForgeDirection): Float = {
// val diff = Math.floor(powerDemand * 0.2F)
// diff.toFloat max 0
0
}
/**
* @return How much energy does this TileEntity want to provide?
*/
def getProvide(direction: ForgeDirection): Float = 0.0F
/**
* Gets the voltage of this TileEntity.
*
* @return The amount of volts. E.g 120v or 240v
*/
def getVoltage: Float = 120.0F
def canConnect(direction: ForgeDirection): Boolean = true
}

View File

@ -0,0 +1,42 @@
package li.cil.oc.server.network
import li.cil.oc.api.network
import li.cil.oc.util.Persistable
import net.minecraft.nbt.NBTTagCompound
trait Connector extends network.Connector with Persistable {
val bufferSize: Double
var dirty = true
var buffer = 0.0
def changeBuffer(delta: Double) = {
val oldBuffer = buffer
buffer = buffer + delta
val ok = if (buffer < 0) {
buffer = 0
false
}
else if (buffer > bufferSize) {
buffer = bufferSize
false
}
else true
if (buffer != oldBuffer) dirty = true
ok
}
override def load(nbt: NBTTagCompound) {
super.load(nbt)
if (nbt.hasKey("oc.connector.buffer")) {
buffer = nbt.getDouble("oc.connector.buffer") max 0 min bufferSize
dirty = true
}
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
nbt.setDouble("oc.connector.buffer", buffer)
}
}

View File

@ -1,4 +1,4 @@
package li.cil.oc.common.tileentity
package li.cil.oc.util
import li.cil.oc.api
import net.minecraft.nbt.NBTTagCompound