From 4e7bc78836dd4195fe0053314c3cadc46fffb426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 18 Mar 2014 19:00:57 +0100 Subject: [PATCH] cleaned up redstone logic a bit and enforcing a short delay after synchronized calls to avoid tick times for computers going through the roof due to spammy synchronized calls (e.g. redstone.setOutput every frame). this is more of a workaround, i'll have to see if i can find a cleaner solution for this. --- .../tileentity/BundledRedstoneAware.scala | 74 +++++++++---------- .../li/cil/oc/common/tileentity/Charger.scala | 2 - .../cil/oc/common/tileentity/Computer.scala | 1 - .../li/cil/oc/common/tileentity/Rack.scala | 1 - .../cil/oc/common/tileentity/Redstone.scala | 7 -- .../oc/common/tileentity/RedstoneAware.scala | 56 ++++++++------ .../cil/oc/common/tileentity/RobotProxy.scala | 2 - .../li/cil/oc/common/tileentity/Screen.scala | 3 - .../oc/server/component/machine/Machine.scala | 5 ++ 9 files changed, 72 insertions(+), 79 deletions(-) diff --git a/src/main/scala/li/cil/oc/common/tileentity/BundledRedstoneAware.scala b/src/main/scala/li/cil/oc/common/tileentity/BundledRedstoneAware.scala index 52e5de0ad..274780121 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/BundledRedstoneAware.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/BundledRedstoneAware.scala @@ -57,31 +57,38 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledEmitter with IBund def bundledOutput(side: ForgeDirection, color: Int, value: Int): Unit = if (value != bundledOutput(side, color)) { _bundledOutput(toLocal(side).ordinal())(color) = value - onRedstoneOutputChanged(side) + + if (Loader.isModLoaded("MineFactoryReloaded")) { + val nx = x + side.offsetX + val ny = y + side.offsetY + val nz = z + side.offsetZ + Block.blocksList(world.getBlockId(nx, ny, nz)) match { + case block: IRedNetNetworkContainer => block.updateNetwork(world, nx, ny, nz) + case _ => + } + } + + onRedstoneOutputChanged() } // ----------------------------------------------------------------------- // - override def updateRedstoneInput() { - if (shouldUpdateInput) { - for (side <- ForgeDirection.VALID_DIRECTIONS) { - val oldBundledInput = _bundledInput(side.ordinal()) - val newBundledInput = computeBundledInput(side) - var changed = false - if (newBundledInput != null) for (color <- 0 until 16) { - changed = changed || (oldBundledInput(color) >= 0 && oldBundledInput(color) != newBundledInput(color)) - oldBundledInput(color) = newBundledInput(color) - } - else for (color <- 0 until 16) { - changed = changed || oldBundledInput(color) > 0 - oldBundledInput(color) = 0 - } - if (changed) { - onRedstoneInputChanged(side) - } - } + override protected def updateRedstoneInput(side: ForgeDirection) { + super.updateRedstoneInput(side) + val oldBundledInput = _bundledInput(side.ordinal()) + val newBundledInput = computeBundledInput(side) + var changed = false + if (newBundledInput != null) for (color <- 0 until 16) { + changed = changed || (oldBundledInput(color) >= 0 && oldBundledInput(color) != newBundledInput(color)) + oldBundledInput(color) = newBundledInput(color) + } + else for (color <- 0 until 16) { + changed = changed || oldBundledInput(color) > 0 + oldBundledInput(color) = 0 + } + if (changed) { + onRedstoneInputChanged(side) } - super.updateRedstoneInput() } override def readFromNBT(nbt: NBTTagCompound) { @@ -149,32 +156,19 @@ trait BundledRedstoneAware extends RedstoneAware with IBundledEmitter with IBund } } - override protected def onRedstoneOutputChanged(side: ForgeDirection) { - if (side == ForgeDirection.UNKNOWN) { - if (Loader.isModLoaded("MineFactoryReloaded")) { - for (side <- ForgeDirection.VALID_DIRECTIONS) { - val nx = x + side.offsetX - val ny = y + side.offsetY - val nz = z + side.offsetZ - Block.blocksList(world.getBlockId(nx, ny, nz)) match { - case block: IRedNetNetworkContainer => block.updateNetwork(world, x, y, z) - case _ => - } - } - } - } - else { - val nx = x + side.offsetX - val ny = y + side.offsetY - val nz = z + side.offsetZ - if (Loader.isModLoaded("MineFactoryReloaded")) { + override protected def onRedstoneOutputEnabledChanged() { + if (Loader.isModLoaded("MineFactoryReloaded")) { + for (side <- ForgeDirection.VALID_DIRECTIONS) { + val nx = x + side.offsetX + val ny = y + side.offsetY + val nz = z + side.offsetZ Block.blocksList(world.getBlockId(nx, ny, nz)) match { case block: IRedNetNetworkContainer => block.updateNetwork(world, x, y, z) case _ => } } } - super.onRedstoneOutputChanged(side) + super.onRedstoneOutputEnabledChanged() } // ----------------------------------------------------------------------- // diff --git a/src/main/scala/li/cil/oc/common/tileentity/Charger.scala b/src/main/scala/li/cil/oc/common/tileentity/Charger.scala index f173bedfc..32a300ec7 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Charger.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Charger.scala @@ -30,8 +30,6 @@ class Charger extends Environment with RedstoneAware with Analyzable { override def updateEntity() { super.updateEntity() if (isServer) { - updateRedstoneInput() - val charge = Settings.get.chargeRate * chargeSpeed robots.collect { case Some(proxy) => node.changeBuffer(proxy.robot.bot.node.changeBuffer(charge + node.changeBuffer(-charge))) diff --git a/src/main/scala/li/cil/oc/common/tileentity/Computer.scala b/src/main/scala/li/cil/oc/common/tileentity/Computer.scala index cd66a50e8..46d3ec392 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Computer.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Computer.scala @@ -124,7 +124,6 @@ trait Computer extends Environment with ComponentInventory with Rotatable with B ServerPacketSender.sendComputerState(this) } - updateRedstoneInput() updateComponents() } } diff --git a/src/main/scala/li/cil/oc/common/tileentity/Rack.scala b/src/main/scala/li/cil/oc/common/tileentity/Rack.scala index 428ad8385..c54cd2a9e 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Rack.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Rack.scala @@ -217,7 +217,6 @@ class Rack extends PowerAcceptor with Hub with PowerBalancer with Inventory with isOutputEnabled = hasRedstoneCard isAbstractBusAvailable = hasAbstractBusCard - updateRedstoneInput() servers collect { case Some(server) => server.inventory.updateComponents() } diff --git a/src/main/scala/li/cil/oc/common/tileentity/Redstone.scala b/src/main/scala/li/cil/oc/common/tileentity/Redstone.scala index 680ecf927..7638933ba 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Redstone.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Redstone.scala @@ -16,13 +16,6 @@ class Redstone extends Environment with BundledRedstoneAware { _isOutputEnabled = true } - override def updateEntity() { - super.updateEntity() - if (isServer) { - updateRedstoneInput() - } - } - override def readFromNBT(nbt: NBTTagCompound) { super.readFromNBT(nbt) instance.load(nbt.getCompoundTag(Settings.namespace + "redstone")) diff --git a/src/main/scala/li/cil/oc/common/tileentity/RedstoneAware.scala b/src/main/scala/li/cil/oc/common/tileentity/RedstoneAware.scala index 16d070142..3b5b99ca4 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/RedstoneAware.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/RedstoneAware.scala @@ -33,7 +33,7 @@ trait RedstoneAware extends RotationAware with IConnectable with IRedstoneEmitte _output(i) = 0 } } - onRedstoneOutputChanged(ForgeDirection.UNKNOWN) + onRedstoneOutputEnabledChanged() } this } @@ -44,9 +44,16 @@ trait RedstoneAware extends RotationAware with IConnectable with IRedstoneEmitte def output(side: ForgeDirection) = _output(toLocal(side).ordinal()) - def output(side: ForgeDirection, value: Int): Unit = if (value != output(side)) { + def output(side: ForgeDirection, value: Int): Unit = if (value != output(side)) this.synchronized { _output(toLocal(side).ordinal()) = value - onRedstoneOutputChanged(side) + + val nx = x + side.offsetX + val ny = y + side.offsetY + val nz = z + side.offsetZ + world.notifyBlockOfNeighborChange(nx, ny, nz, block.blockID) + world.notifyBlocksOfNeighborChange(nx, ny, nz, world.getBlockId(nx, ny, nz), side.getOpposite.ordinal) + + onRedstoneOutputChanged() } def checkRedstoneInputChanged() { @@ -55,20 +62,27 @@ trait RedstoneAware extends RotationAware with IConnectable with IRedstoneEmitte // ----------------------------------------------------------------------- // - def updateRedstoneInput() { - if (shouldUpdateInput) { - shouldUpdateInput = false - for (side <- ForgeDirection.VALID_DIRECTIONS) { - val oldInput = _input(side.ordinal()) - val newInput = computeInput(side) - _input(side.ordinal()) = newInput - if (oldInput >= 0 && input(side) != oldInput) { - onRedstoneInputChanged(side) + override def updateEntity() { + super.updateEntity() + if (isServer) { + if (shouldUpdateInput) { + shouldUpdateInput = false + for (side <- ForgeDirection.VALID_DIRECTIONS) { + updateRedstoneInput(side) } } } } + protected def updateRedstoneInput(side: ForgeDirection) { + val oldInput = _input(side.ordinal()) + val newInput = computeInput(side) + _input(side.ordinal()) = newInput + if (oldInput >= 0 && input(side) != oldInput) { + onRedstoneInputChanged(side) + } + } + // ----------------------------------------------------------------------- // override def readFromNBT(nbt: NBTTagCompound) = { @@ -124,17 +138,13 @@ trait RedstoneAware extends RotationAware with IConnectable with IRedstoneEmitte protected def onRedstoneInputChanged(side: ForgeDirection) {} - protected def onRedstoneOutputChanged(side: ForgeDirection) { - if (side == ForgeDirection.UNKNOWN) { - world.notifyBlocksOfNeighborChange(x, y, z, block.blockID) - } - else { - val nx = x + side.offsetX - val ny = y + side.offsetY - val nz = z + side.offsetZ - world.notifyBlockOfNeighborChange(nx, ny, nz, block.blockID) - world.notifyBlocksOfNeighborChange(nx, ny, nz, world.getBlockId(nx, ny, nz)) - } + protected def onRedstoneOutputEnabledChanged() = this.synchronized { + world.notifyBlocksOfNeighborChange(x, y, z, block.blockID) + if (isServer) ServerPacketSender.sendRedstoneState(this) + else world.markBlockForRenderUpdate(x, y, z) + } + + protected def onRedstoneOutputChanged() { if (isServer) ServerPacketSender.sendRedstoneState(this) else world.markBlockForRenderUpdate(x, y, z) } diff --git a/src/main/scala/li/cil/oc/common/tileentity/RobotProxy.scala b/src/main/scala/li/cil/oc/common/tileentity/RobotProxy.scala index 5b1b946a2..526613d47 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/RobotProxy.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/RobotProxy.scala @@ -154,8 +154,6 @@ class RobotProxy(val robot: Robot) extends Computer with ISidedInventory with Bu override def checkRedstoneInputChanged() = robot.checkRedstoneInputChanged() - override def updateRedstoneInput() = robot.updateRedstoneInput() - @Optional.Method(modid = "RedLogic") override def connects(wire: IWire, blockFace: Int, fromDirection: Int) = robot.connects(wire, blockFace, fromDirection) diff --git a/src/main/scala/li/cil/oc/common/tileentity/Screen.scala b/src/main/scala/li/cil/oc/common/tileentity/Screen.scala index ad0892b77..6bac036f7 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Screen.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Screen.scala @@ -201,9 +201,6 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable override def updateEntity() { super.updateEntity() - if (isServer) { - updateRedstoneInput() - } if (isServer && isOn && isOrigin && world.getWorldTime % Settings.get.tickFrequency == 0) { if (relativeLitArea < 0) { // The relative lit area is the number of pixels that are not blank diff --git a/src/main/scala/li/cil/oc/server/component/machine/Machine.scala b/src/main/scala/li/cil/oc/server/component/machine/Machine.scala index 6dec14ad2..155a7bb1c 100644 --- a/src/main/scala/li/cil/oc/server/component/machine/Machine.scala +++ b/src/main/scala/li/cil/oc/server/component/machine/Machine.scala @@ -380,6 +380,11 @@ class Machine(val owner: Owner, val rom: Option[ManagedEnvironment], constructor switchTo(Machine.State.Running) try { architecture.runSynchronized() + // This sleep is used to avoid spammy synchronized calls to increase + // the tick time the computer eats unduly. This is a very... rough + // workaround for that problem, and may have to be addressed with + // more care at some point... aka when I have more time. + pause(0.1) // Check if the callback called pause() or stop(). state.top match { case Machine.State.Running =>