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

View File

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

View File

@ -69,7 +69,9 @@ class PacketHandler extends CommonPacketHandler {
def onPowerStateResponse(p: PacketParser) =
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.
}

View File

@ -13,7 +13,7 @@ object PacketSender {
pb.sendToServer()
}
def sendPowerStateRequest(t: PowerDistributor) {
def sendPowerStateRequest(t: PowerInformation) {
val pb = new PacketBuilder(PacketType.PowerStateRequest)
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 format = StatCollector.translateToLocal(Settings.namespace + "text.Robot.Power") + ": %d%% (%d/%d)"
tooltip.add(format.format(
(robot.globalPower * 100).toInt,
(robot.globalPower * Settings.get.bufferRobot).toInt,
Settings.get.bufferRobot.toInt))
((robot.globalBuffer / robot.globalBufferSize) * 100).toInt,
robot.globalBuffer.toInt,
robot.globalBufferSize.toInt))
drawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRenderer)
GL11.glPopAttrib()
}
@ -107,7 +107,7 @@ class Robot(playerInventory: InventoryPlayer, val robot: tileentity.Robot) exten
}
private def drawPowerLevel() {
val level = robot.globalPower
val level = robot.globalBuffer / robot.globalBufferSize
val u0 = 0
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) = {
val distributor = tileEntity.asInstanceOf[tileentity.PowerDistributor]
if (distributor.globalPower > 0) {
if (distributor.globalBuffer > 0) {
GL11.glPushAttrib(0xFFFFFF)
RenderState.disableLighting()
RenderState.makeItBlend()
RenderState.setBlendAlpha(distributor.globalPower.toFloat)
RenderState.setBlendAlpha((distributor.globalBuffer / distributor.globalBufferSize).toFloat)
GL11.glPushMatrix()

View File

@ -7,7 +7,7 @@ import li.cil.oc.util.Tooltip
import net.minecraft.client.renderer.texture.IconRegister
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.util.Icon
import net.minecraft.world.World
import net.minecraft.world.{IBlockAccess, World}
import net.minecraftforge.common.ForgeDirection
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 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) =
world.getBlockTileEntity(x, y, z) match {
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.common.tileentity
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import net.minecraft.entity.player.{EntityPlayer, InventoryPlayer}
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)
var lastSentBuffer = -1
override def detectAndSendChanges() {
if ((robot.globalBuffer - lastSentBuffer).abs > 1) {
ServerPacketSender.sendPowerState(robot)
}
}
override def canInteractWith(player: EntityPlayer) =
super.canInteractWith(player) && robot.computer.canInteract(player.getCommandSenderName)
}

View File

@ -46,6 +46,7 @@ class Charger extends Environment with Redstone {
}
def onNeighborChanged() {
checkRedstoneInputChanged()
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)
}

View File

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

View File

@ -1,5 +1,11 @@
package li.cil.oc.common.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 globalBuffer = 0.0
var globalBufferSize = 0.0
var selectedSlot = 0
var equippedItem: Option[ItemStack] = None
@ -204,11 +208,6 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
}
super.updateEntity()
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()
gpu.update()
}
@ -223,8 +222,9 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
}
}
else {
ClientPacketSender.sendScreenBufferRequest(this)
ClientPacketSender.sendPowerStateRequest(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) {
assert(isServer)
nbt.setNewCompoundTag(Settings.namespace + "battery", battery.save)
nbt.setNewCompoundTag(Settings.namespace + "buffer", buffer.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) {
Network.joinOrCreateNetwork(this)
}
if (isClient) {
robot.globalPower = globalPower
}
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
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) =
p.readTileEntity[PowerDistributor]() match {
p.readTileEntity[PowerInformation]() match {
case Some(t) => PacketSender.sendPowerState(t, Option(p.player))
case _ => // Invalid packet.
}

View File

@ -37,7 +37,8 @@ object PacketSender {
val pb = new PacketBuilder(PacketType.PowerStateResponse)
pb.writeTileEntity(t)
pb.writeDouble(t.globalPower)
pb.writeDouble(t.globalBuffer)
pb.writeDouble(t.globalBufferSize)
player match {
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())
// Make sure we have enough power.
val cost = if (isRobot) Settings.get.robotCost else Settings.get.computerCost
state.synchronized(state.top match {
case Computer.State.Paused |
Computer.State.Restarting |
Computer.State.Stopping |
Computer.State.Stopped => // No power consumption.
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")
}
case _ =>
if (!node.tryChangeBuffer(-Settings.get.computerCost)) {
if (!node.tryChangeBuffer(-cost)) {
crash("not enough energy")
}
})

View File

@ -18,7 +18,7 @@ class PowerDistributor(val owner: PowerInformation) extends ManagedComponent {
var globalBufferSize = 0.0
private var lastSentState = 0.0
private var lastSentBuffer = 0.0
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
(acc._1 + c.localBuffer, acc._2 + c.localBufferSize)
})
val globalPower = if (globalBufferSize > 0) globalBuffer / globalBufferSize else 0
val shouldSend = (lastSentState - globalPower).abs * globalBufferSize > 1
// Only send updates if the state changed by more than 5%, more won't be
// 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 {
distributor.dirty = false
distributor.globalBuffer = sumBuffer
distributor.globalBufferSize = sumBufferSize
distributor.owner.globalPower = globalPower
distributor.owner.globalBuffer = sumBuffer
distributor.owner.globalBufferSize = sumBufferSize
if (shouldSend) {
distributor.lastSentState = lastSentState
distributor.lastSentBuffer = sumBuffer
ServerPacketSender.sendPowerState(owner)
}
}

View File

@ -280,7 +280,7 @@ opencomputers {
# enter this state either by calling `os.sleep()` or by pulling
# signals. Note that this does not apply in the tick they resume, so
# 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
# tick. If a screen cannot consume the defined amount of energy it