more work on charger block; redid global power state synchronization for networks, now sending general state every 5% changes (for distributor block rendering e.g.) and sending more frequently only when necessary (e.g. gui of robots); removed the testing power generation from robots, they have to be charged at chargers now

This commit is contained in:
Florian Nücke 2013-11-26 20:55:22 +01:00
parent c52e18a87b
commit 643a25fc53
18 changed files with 69 additions and 30 deletions

View File

@ -13,6 +13,7 @@ object Blocks {
var adapter: Adapter = null var adapter: Adapter = null
var cable: Cable = null var cable: Cable = null
var capacitor: Capacitor = null var capacitor: Capacitor = null
var charger: Charger = null
var computerCase: Case = null var computerCase: Case = null
var diskDrive: DiskDrive = null var diskDrive: DiskDrive = null
var keyboard: Keyboard = null var keyboard: Keyboard = null
@ -38,6 +39,7 @@ object Blocks {
GameRegistry.registerTileEntity(classOf[tileentity.Cable], Settings.namespace + "cable") GameRegistry.registerTileEntity(classOf[tileentity.Cable], Settings.namespace + "cable")
GameRegistry.registerTileEntity(classOf[tileentity.Capacitor], Settings.namespace + "capacitor") GameRegistry.registerTileEntity(classOf[tileentity.Capacitor], Settings.namespace + "capacitor")
GameRegistry.registerTileEntity(classOf[tileentity.Case], Settings.namespace + "case") GameRegistry.registerTileEntity(classOf[tileentity.Case], Settings.namespace + "case")
GameRegistry.registerTileEntity(classOf[tileentity.Charger], Settings.namespace + "charger")
GameRegistry.registerTileEntity(classOf[tileentity.DiskDrive], Settings.namespace + "disk_drive") GameRegistry.registerTileEntity(classOf[tileentity.DiskDrive], Settings.namespace + "disk_drive")
GameRegistry.registerTileEntity(classOf[tileentity.Keyboard], Settings.namespace + "keyboard") GameRegistry.registerTileEntity(classOf[tileentity.Keyboard], Settings.namespace + "keyboard")
GameRegistry.registerTileEntity(classOf[tileentity.PowerConverter], Settings.namespace + "power_converter") GameRegistry.registerTileEntity(classOf[tileentity.PowerConverter], Settings.namespace + "power_converter")
@ -64,5 +66,6 @@ object Blocks {
screen3 = new Screen.Tier3(blockSimple) screen3 = new Screen.Tier3(blockSimple)
router = new Router(blockSimple) router = new Router(blockSimple)
charger = new Charger(blockSimpleWithRedstone)
} }
} }

View File

@ -23,6 +23,7 @@ object Items {
def init() { def init() {
multi = new item.Delegator(Settings.get.itemId) multi = new item.Delegator(Settings.get.itemId)
GameRegistry.registerItem(multi, Settings.namespace + "item") GameRegistry.registerItem(multi, Settings.namespace + "item")
analyzer = new item.Analyzer(multi) analyzer = new item.Analyzer(multi)

View File

@ -69,7 +69,9 @@ class PacketHandler extends CommonPacketHandler {
def onPowerStateResponse(p: PacketParser) = def onPowerStateResponse(p: PacketParser) =
p.readTileEntity[PowerInformation]() match { p.readTileEntity[PowerInformation]() match {
case Some(t) => t.globalPower = p.readDouble() case Some(t) =>
t.globalBuffer = p.readDouble()
t.globalBufferSize = p.readDouble()
case _ => // Invalid packet. case _ => // Invalid packet.
} }

View File

@ -13,7 +13,7 @@ object PacketSender {
pb.sendToServer() pb.sendToServer()
} }
def sendPowerStateRequest(t: PowerDistributor) { def sendPowerStateRequest(t: PowerInformation) {
val pb = new PacketBuilder(PacketType.PowerStateRequest) val pb = new PacketBuilder(PacketType.PowerStateRequest)
pb.writeTileEntity(t) pb.writeTileEntity(t)

View File

@ -60,9 +60,9 @@ class Robot(playerInventory: InventoryPlayer, val robot: tileentity.Robot) exten
val tooltip = new java.util.ArrayList[String] val tooltip = new java.util.ArrayList[String]
val format = StatCollector.translateToLocal(Settings.namespace + "text.Robot.Power") + ": %d%% (%d/%d)" val format = StatCollector.translateToLocal(Settings.namespace + "text.Robot.Power") + ": %d%% (%d/%d)"
tooltip.add(format.format( tooltip.add(format.format(
(robot.globalPower * 100).toInt, ((robot.globalBuffer / robot.globalBufferSize) * 100).toInt,
(robot.globalPower * Settings.get.bufferRobot).toInt, robot.globalBuffer.toInt,
Settings.get.bufferRobot.toInt)) robot.globalBufferSize.toInt))
drawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer) drawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
GL11.glPopAttrib() GL11.glPopAttrib()
} }
@ -107,7 +107,7 @@ class Robot(playerInventory: InventoryPlayer, val robot: tileentity.Robot) exten
} }
private def drawPowerLevel() { private def drawPowerLevel() {
val level = robot.globalPower val level = robot.globalBuffer / robot.globalBufferSize
val u0 = 0 val u0 = 0
val u1 = powerWidth / 256.0 * level val u1 = powerWidth / 256.0 * level

View File

@ -14,12 +14,12 @@ object PowerDistributorRenderer extends TileEntitySpecialRenderer {
override def renderTileEntityAt(tileEntity: TileEntity, x: Double, y: Double, z: Double, f: Float) = { override def renderTileEntityAt(tileEntity: TileEntity, x: Double, y: Double, z: Double, f: Float) = {
val distributor = tileEntity.asInstanceOf[tileentity.PowerDistributor] val distributor = tileEntity.asInstanceOf[tileentity.PowerDistributor]
if (distributor.globalPower > 0) { if (distributor.globalBuffer > 0) {
GL11.glPushAttrib(0xFFFFFF) GL11.glPushAttrib(0xFFFFFF)
RenderState.disableLighting() RenderState.disableLighting()
RenderState.makeItBlend() RenderState.makeItBlend()
RenderState.setBlendAlpha(distributor.globalPower.toFloat) RenderState.setBlendAlpha((distributor.globalBuffer / distributor.globalBufferSize).toFloat)
GL11.glPushMatrix() GL11.glPushMatrix()

View File

@ -7,7 +7,7 @@ import li.cil.oc.util.Tooltip
import net.minecraft.client.renderer.texture.IconRegister import net.minecraft.client.renderer.texture.IconRegister
import net.minecraft.entity.player.EntityPlayer import net.minecraft.entity.player.EntityPlayer
import net.minecraft.util.Icon import net.minecraft.util.Icon
import net.minecraft.world.World import net.minecraft.world.{IBlockAccess, World}
import net.minecraftforge.common.ForgeDirection import net.minecraftforge.common.ForgeDirection
class Charger(val parent: SimpleDelegator) extends SimpleDelegate { class Charger(val parent: SimpleDelegator) extends SimpleDelegate {
@ -29,6 +29,8 @@ class Charger(val parent: SimpleDelegator) extends SimpleDelegate {
override def createTileEntity(world: World) = Some(new tileentity.Charger()) override def createTileEntity(world: World) = Some(new tileentity.Charger())
override def canConnectRedstone(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = true
override def onNeighborBlockChange(world: World, x: Int, y: Int, z: Int, blockId: Int) = override def onNeighborBlockChange(world: World, x: Int, y: Int, z: Int, blockId: Int) =
world.getBlockTileEntity(x, y, z) match { world.getBlockTileEntity(x, y, z) match {
case charger: tileentity.Charger => charger.onNeighborChanged() case charger: tileentity.Charger => charger.onNeighborChanged()

View File

@ -2,6 +2,7 @@ package li.cil.oc.common.container
import li.cil.oc.api import li.cil.oc.api
import li.cil.oc.common.tileentity import li.cil.oc.common.tileentity
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import net.minecraft.entity.player.{EntityPlayer, InventoryPlayer} import net.minecraft.entity.player.{EntityPlayer, InventoryPlayer}
class Robot(playerInventory: InventoryPlayer, robot: tileentity.Robot) extends Player(playerInventory, robot) { class Robot(playerInventory: InventoryPlayer, robot: tileentity.Robot) extends Player(playerInventory, robot) {
@ -19,6 +20,14 @@ class Robot(playerInventory: InventoryPlayer, robot: tileentity.Robot) extends P
addPlayerInventorySlots(8, 160) addPlayerInventorySlots(8, 160)
var lastSentBuffer = -1
override def detectAndSendChanges() {
if ((robot.globalBuffer - lastSentBuffer).abs > 1) {
ServerPacketSender.sendPowerState(robot)
}
}
override def canInteractWith(player: EntityPlayer) = override def canInteractWith(player: EntityPlayer) =
super.canInteractWith(player) && robot.computer.canInteract(player.getCommandSenderName) super.canInteractWith(player) && robot.computer.canInteract(player.getCommandSenderName)
} }

View File

@ -46,6 +46,7 @@ class Charger extends Environment with Redstone {
} }
def onNeighborChanged() { def onNeighborChanged() {
checkRedstoneInputChanged()
ForgeDirection.VALID_DIRECTIONS.map(side => (side.ordinal(), world.getBlockTileEntity(x + side.offsetX, y + side.offsetY, z + side.offsetZ))).collect { ForgeDirection.VALID_DIRECTIONS.map(side => (side.ordinal(), world.getBlockTileEntity(x + side.offsetX, y + side.offsetY, z + side.offsetZ))).collect {
case (side, proxy: RobotProxy) => robots(side) = Some(proxy) case (side, proxy: RobotProxy) => robots(side) = Some(proxy)
} }

View File

@ -11,6 +11,10 @@ import net.minecraft.nbt.NBTTagCompound
class PowerDistributor extends Environment with PowerInformation with Analyzable { class PowerDistributor extends Environment with PowerInformation with Analyzable {
val distributor = new component.PowerDistributor(this) val distributor = new component.PowerDistributor(this)
var globalBuffer = 0.0
var globalBufferSize = 0.0
def node = distributor.node def node = distributor.node
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //

View File

@ -1,5 +1,11 @@
package li.cil.oc.common.tileentity package li.cil.oc.common.tileentity
trait PowerInformation extends TileEntity { trait PowerInformation extends TileEntity {
var globalPower = 0.0 def globalBuffer: Double
def globalBuffer_=(value: Double)
def globalBufferSize: Double
def globalBufferSize_=(value: Double)
} }

View File

@ -57,6 +57,10 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
var owner = "OpenComputers" var owner = "OpenComputers"
var globalBuffer = 0.0
var globalBufferSize = 0.0
var selectedSlot = 0 var selectedSlot = 0
var equippedItem: Option[ItemStack] = None var equippedItem: Option[ItemStack] = None
@ -204,11 +208,6 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
} }
super.updateEntity() super.updateEntity()
if (isServer) { if (isServer) {
if (computer.isRunning && !computer.isPaused) {
// TODO just for testing... until we have charging stations
battery.changeBuffer(Settings.get.robotCost + 0.1)
battery.changeBuffer(Settings.get.computerCost - Settings.get.robotCost)
}
distributor.update() distributor.update()
gpu.update() gpu.update()
} }
@ -223,8 +222,9 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
} }
} }
else { else {
ClientPacketSender.sendScreenBufferRequest(this) ClientPacketSender.sendPowerStateRequest(this)
ClientPacketSender.sendRobotStateRequest(this) ClientPacketSender.sendRobotStateRequest(this)
ClientPacketSender.sendScreenBufferRequest(this)
} }
} }
@ -259,7 +259,6 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
} }
override def writeToNBT(nbt: NBTTagCompound) { override def writeToNBT(nbt: NBTTagCompound) {
assert(isServer)
nbt.setNewCompoundTag(Settings.namespace + "battery", battery.save) nbt.setNewCompoundTag(Settings.namespace + "battery", battery.save)
nbt.setNewCompoundTag(Settings.namespace + "buffer", buffer.save) nbt.setNewCompoundTag(Settings.namespace + "buffer", buffer.save)
nbt.setNewCompoundTag(Settings.namespace + "distributor", distributor.save) nbt.setNewCompoundTag(Settings.namespace + "distributor", distributor.save)

View File

@ -42,9 +42,6 @@ class RobotProxy(val robot: Robot) extends Computer(robot.isClient) with ISidedI
if (node != null && node.network == null) { if (node != null && node.network == null) {
Network.joinOrCreateNetwork(this) Network.joinOrCreateNetwork(this)
} }
if (isClient) {
robot.globalPower = globalPower
}
robot.updateEntity() robot.updateEntity()
} }
@ -241,4 +238,14 @@ class RobotProxy(val robot: Robot) extends Computer(robot.isClient) with ISidedI
override def currentGui_=(value: Option[gui.Buffer]) = robot.currentGui = value override def currentGui_=(value: Option[gui.Buffer]) = robot.currentGui = value
def tier = robot.tier def tier = robot.tier
// ----------------------------------------------------------------------- //
def globalBuffer = robot.globalBuffer
def globalBuffer_=(value: Double) = robot.globalBuffer = value
def globalBufferSize = robot.globalBufferSize
def globalBufferSize_=(value: Double) = robot.globalBufferSize = value
} }

View File

@ -32,7 +32,7 @@ class PacketHandler extends CommonPacketHandler {
} }
def onPowerStateRequest(p: PacketParser) = def onPowerStateRequest(p: PacketParser) =
p.readTileEntity[PowerDistributor]() match { p.readTileEntity[PowerInformation]() match {
case Some(t) => PacketSender.sendPowerState(t, Option(p.player)) case Some(t) => PacketSender.sendPowerState(t, Option(p.player))
case _ => // Invalid packet. case _ => // Invalid packet.
} }

View File

@ -37,7 +37,8 @@ object PacketSender {
val pb = new PacketBuilder(PacketType.PowerStateResponse) val pb = new PacketBuilder(PacketType.PowerStateResponse)
pb.writeTileEntity(t) pb.writeTileEntity(t)
pb.writeDouble(t.globalPower) pb.writeDouble(t.globalBuffer)
pb.writeDouble(t.globalBufferSize)
player match { player match {
case Some(p) => pb.sendToPlayer(p) case Some(p) => pb.sendToPlayer(p)

View File

@ -214,17 +214,18 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
callCounts.synchronized(callCounts.clear()) callCounts.synchronized(callCounts.clear())
// Make sure we have enough power. // Make sure we have enough power.
val cost = if (isRobot) Settings.get.robotCost else Settings.get.computerCost
state.synchronized(state.top match { state.synchronized(state.top match {
case Computer.State.Paused | case Computer.State.Paused |
Computer.State.Restarting | Computer.State.Restarting |
Computer.State.Stopping | Computer.State.Stopping |
Computer.State.Stopped => // No power consumption. Computer.State.Stopped => // No power consumption.
case Computer.State.Sleeping if lastUpdate < sleepUntil && signals.isEmpty => case Computer.State.Sleeping if lastUpdate < sleepUntil && signals.isEmpty =>
if (!node.tryChangeBuffer(-Settings.get.computerCost * Settings.get.sleepCostFactor)) { if (!node.tryChangeBuffer(-cost * Settings.get.sleepCostFactor)) {
crash("not enough energy") crash("not enough energy")
} }
case _ => case _ =>
if (!node.tryChangeBuffer(-Settings.get.computerCost)) { if (!node.tryChangeBuffer(-cost)) {
crash("not enough energy") crash("not enough energy")
} }
}) })

View File

@ -18,7 +18,7 @@ class PowerDistributor(val owner: PowerInformation) extends ManagedComponent {
var globalBufferSize = 0.0 var globalBufferSize = 0.0
private var lastSentState = 0.0 private var lastSentBuffer = 0.0
private val buffers = mutable.Set.empty[Connector] private val buffers = mutable.Set.empty[Connector]
@ -167,15 +167,18 @@ class PowerDistributor(val owner: PowerInformation) extends ManagedComponent {
c.dirty = false // clear dirty flag for all connectors c.dirty = false // clear dirty flag for all connectors
(acc._1 + c.localBuffer, acc._2 + c.localBufferSize) (acc._1 + c.localBuffer, acc._2 + c.localBufferSize)
}) })
val globalPower = if (globalBufferSize > 0) globalBuffer / globalBufferSize else 0 // Only send updates if the state changed by more than 5%, more won't be
val shouldSend = (lastSentState - globalPower).abs * globalBufferSize > 1 // noticeable "from the outside" anyway. We send more frequent updates in
// the gui/container of a block that needs it (like robots).
val shouldSend = (lastSentBuffer - sumBuffer).abs > globalBufferSize * (5.0 / 100.0)
for (distributor <- distributors) distributor.synchronized { for (distributor <- distributors) distributor.synchronized {
distributor.dirty = false distributor.dirty = false
distributor.globalBuffer = sumBuffer distributor.globalBuffer = sumBuffer
distributor.globalBufferSize = sumBufferSize distributor.globalBufferSize = sumBufferSize
distributor.owner.globalPower = globalPower distributor.owner.globalBuffer = sumBuffer
distributor.owner.globalBufferSize = sumBufferSize
if (shouldSend) { if (shouldSend) {
distributor.lastSentState = lastSentState distributor.lastSentBuffer = sumBuffer
ServerPacketSender.sendPowerState(owner) ServerPacketSender.sendPowerState(owner)
} }
} }

View File

@ -280,7 +280,7 @@ opencomputers {
# enter this state either by calling `os.sleep()` or by pulling # enter this state either by calling `os.sleep()` or by pulling
# signals. Note that this does not apply in the tick they resume, so # signals. Note that this does not apply in the tick they resume, so
# you can't fake sleep by calling `os.sleep(0)`. # you can't fake sleep by calling `os.sleep(0)`.
sleepFactor: 0.25 sleepFactor: 0.1
# The amount of energy a screen consumes per displayed character per # The amount of energy a screen consumes per displayed character per
# tick. If a screen cannot consume the defined amount of energy it # tick. If a screen cannot consume the defined amount of energy it