mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-16 10:51:55 -04:00
changed the way screen power consumption is computed. it's no only computed by the origin and no longer the actual number of pixels, but the relative number of pixels (based on the current resolution), with the cost being scaled based on the maximum resolution versus the resolution of the basic screen; screens can now be turned off to conserve power. turning them back on consumes as much energy as one cycle with a fully lit screen would, to avoid people trying to avoid the cost by turning screens off and on again at the right time (when the screen cost is actually computed, which doesn't happen every tick unless so configured - see power.tickFrequency)
This commit is contained in:
parent
cce2d4fa6e
commit
cf70a33ea4
@ -2,9 +2,10 @@ package li.cil.oc.common.tileentity
|
|||||||
|
|
||||||
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
import cpw.mods.fml.relauncher.{Side, SideOnly}
|
||||||
import li.cil.oc.Settings
|
import li.cil.oc.Settings
|
||||||
import li.cil.oc.api.network.{SidedEnvironment, Analyzable, Visibility}
|
import li.cil.oc.api.network._
|
||||||
import li.cil.oc.client.renderer.MonospaceFontRenderer
|
import li.cil.oc.client.renderer.MonospaceFontRenderer
|
||||||
import li.cil.oc.client.{PacketSender => ClientPacketSender}
|
import li.cil.oc.client.{PacketSender => ClientPacketSender}
|
||||||
|
import li.cil.oc.common.component
|
||||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||||
import net.minecraft.client.Minecraft
|
import net.minecraft.client.Minecraft
|
||||||
import net.minecraft.entity.Entity
|
import net.minecraft.entity.Entity
|
||||||
@ -13,6 +14,7 @@ import net.minecraft.entity.projectile.EntityArrow
|
|||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
import net.minecraft.util.AxisAlignedBB
|
import net.minecraft.util.AxisAlignedBB
|
||||||
import net.minecraftforge.common.ForgeDirection
|
import net.minecraftforge.common.ForgeDirection
|
||||||
|
import scala.Some
|
||||||
import scala.collection.mutable
|
import scala.collection.mutable
|
||||||
|
|
||||||
class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable with Analyzable with Ordered[Screen] {
|
class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable with Analyzable with Ordered[Screen] {
|
||||||
@ -20,9 +22,41 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
|
|
||||||
val pixelCost = {
|
override protected val _buffer = new component.Buffer(this) {
|
||||||
|
@LuaCallback("isOn")
|
||||||
|
def isOn(computer: Context, args: Arguments): Array[AnyRef] = result(origin.isOn)
|
||||||
|
|
||||||
|
@LuaCallback("turnOn")
|
||||||
|
def turnOn(computer: Context, args: Arguments): Array[AnyRef] = {
|
||||||
|
if (!origin.isOn) {
|
||||||
|
origin.isOn = true
|
||||||
|
val neededPower = width * height * Settings.get.screenCost * Settings.get.tickFrequency
|
||||||
|
origin.hasPower = node.changeBuffer(-neededPower) == 0
|
||||||
|
ServerPacketSender.sendScreenPowerChange(origin, origin.isOn && origin.hasPower)
|
||||||
|
result(true, origin.isOn)
|
||||||
|
}
|
||||||
|
else result(false, origin.isOn)
|
||||||
|
}
|
||||||
|
|
||||||
|
@LuaCallback("turnOff")
|
||||||
|
def turnOff(computer: Context, args: Arguments): Array[AnyRef] = {
|
||||||
|
if (origin.isOn) {
|
||||||
|
origin.isOn = false
|
||||||
|
ServerPacketSender.sendScreenPowerChange(origin, origin.isOn && origin.hasPower)
|
||||||
|
result(true, origin.isOn)
|
||||||
|
}
|
||||||
|
else result(false, origin.isOn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the energy cost (per tick) to keep the screen running if every
|
||||||
|
// single "pixel" is lit. This cost increases with higher tiers as their
|
||||||
|
// maximum resolution (pixel density) increases. For a basic screen this is
|
||||||
|
// simply the configured cost.
|
||||||
|
val fullyLitCost = {
|
||||||
val (w, h) = Settings.screenResolutionsByTier(0)
|
val (w, h) = Settings.screenResolutionsByTier(0)
|
||||||
Settings.get.screenCost / (w * h)
|
val (mw, mh) = buffer.maxResolution
|
||||||
|
Settings.get.screenCost * (mw * mh) / (w * h)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,10 +71,12 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
|
|||||||
|
|
||||||
val screens = mutable.Set(this)
|
val screens = mutable.Set(this)
|
||||||
|
|
||||||
var litPixels = -1
|
var relativeLitArea = -1.0
|
||||||
|
|
||||||
var hasPower = true
|
var hasPower = true
|
||||||
|
|
||||||
|
var isOn = true
|
||||||
|
|
||||||
var cachedBounds: Option[AxisAlignedBB] = None
|
var cachedBounds: Option[AxisAlignedBB] = None
|
||||||
|
|
||||||
private val arrows = mutable.Set.empty[EntityArrow]
|
private val arrows = mutable.Set.empty[EntityArrow]
|
||||||
@ -153,18 +189,20 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
|
|||||||
|
|
||||||
override def updateEntity() {
|
override def updateEntity() {
|
||||||
super.updateEntity()
|
super.updateEntity()
|
||||||
if (isServer && world.getWorldTime % Settings.get.tickFrequency == 0) {
|
if (isServer && isOn && isOrigin && world.getWorldTime % Settings.get.tickFrequency == 0) {
|
||||||
if (litPixels < 0) {
|
if (relativeLitArea < 0) {
|
||||||
litPixels = 0
|
// The relative lit area is the number of pixels that are not blank
|
||||||
for (line <- buffer.lines) for (c <- line) {
|
// versus the number of pixels in the *current* resolution. This is
|
||||||
if (c != ' ') litPixels += 1
|
// scaled to multi-block screens, since we only compute this for the
|
||||||
}
|
// origin. We add 1 to make sure we at least consume `screenCost`.
|
||||||
|
val (w, h) = buffer.resolution
|
||||||
|
relativeLitArea = 1 + width * height * buffer.lines.foldLeft(0) { (acc, line) => acc + line.count(' ' !=) } / (w * h).toDouble
|
||||||
}
|
}
|
||||||
val hadPower = hasPower
|
val hadPower = hasPower
|
||||||
val neededPower = (Settings.get.screenCost + pixelCost * litPixels) * Settings.get.tickFrequency
|
val neededPower = relativeLitArea * fullyLitCost * Settings.get.tickFrequency
|
||||||
hasPower = buffer.node.tryChangeBuffer(-neededPower)
|
hasPower = buffer.node.tryChangeBuffer(-neededPower)
|
||||||
if (hasPower != hadPower) {
|
if (hasPower != hadPower) {
|
||||||
ServerPacketSender.sendScreenPowerChange(this, hasPower)
|
ServerPacketSender.sendScreenPowerChange(this, isOn && hasPower)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (shouldCheckForMultiBlock) {
|
if (shouldCheckForMultiBlock) {
|
||||||
@ -260,11 +298,32 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
|
|||||||
override def readFromNBT(nbt: NBTTagCompound) {
|
override def readFromNBT(nbt: NBTTagCompound) {
|
||||||
tier = nbt.getByte(Settings.namespace + "tier") max 0 min 2
|
tier = nbt.getByte(Settings.namespace + "tier") max 0 min 2
|
||||||
super.readFromNBT(nbt)
|
super.readFromNBT(nbt)
|
||||||
|
// This check is just to avoid powering off any screens that have been
|
||||||
|
// placed before this was introduced.
|
||||||
|
if (nbt.hasKey(Settings.namespace + "isOn")) {
|
||||||
|
isOn = nbt.getBoolean(Settings.namespace + "isOn")
|
||||||
|
}
|
||||||
|
if (nbt.hasKey(Settings.namespace + "isOn")) {
|
||||||
|
hasPower = nbt.getBoolean(Settings.namespace + "hasPower")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override def writeToNBT(nbt: NBTTagCompound) {
|
override def writeToNBT(nbt: NBTTagCompound) {
|
||||||
nbt.setByte(Settings.namespace + "tier", tier.toByte)
|
nbt.setByte(Settings.namespace + "tier", tier.toByte)
|
||||||
super.writeToNBT(nbt)
|
super.writeToNBT(nbt)
|
||||||
|
nbt.setBoolean(Settings.namespace + "isOn", isOn)
|
||||||
|
nbt.setBoolean(Settings.namespace + "hasPower", hasPower)
|
||||||
|
}
|
||||||
|
|
||||||
|
@SideOnly(Side.CLIENT)
|
||||||
|
override def readFromNBTForClient(nbt: NBTTagCompound) {
|
||||||
|
super.readFromNBTForClient(nbt)
|
||||||
|
hasPower = nbt.getBoolean("hasPower")
|
||||||
|
}
|
||||||
|
|
||||||
|
override def writeToNBTForClient(nbt: NBTTagCompound) {
|
||||||
|
super.writeToNBTForClient(nbt)
|
||||||
|
nbt.setBoolean("hasPower", isOn && hasPower)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------- //
|
// ----------------------------------------------------------------------- //
|
||||||
@ -300,22 +359,22 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
|
|||||||
|
|
||||||
override def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
|
override def onScreenCopy(col: Int, row: Int, w: Int, h: Int, tx: Int, ty: Int) {
|
||||||
super.onScreenCopy(col, row, w, h, tx, ty)
|
super.onScreenCopy(col, row, w, h, tx, ty)
|
||||||
litPixels = -1
|
relativeLitArea = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
|
override def onScreenFill(col: Int, row: Int, w: Int, h: Int, c: Char) {
|
||||||
super.onScreenFill(col, row, w, h, c)
|
super.onScreenFill(col, row, w, h, c)
|
||||||
litPixels = -1
|
relativeLitArea = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onScreenResolutionChange(w: Int, h: Int) {
|
override def onScreenResolutionChange(w: Int, h: Int) {
|
||||||
super.onScreenResolutionChange(w, h)
|
super.onScreenResolutionChange(w, h)
|
||||||
litPixels = -1
|
relativeLitArea = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
override def onScreenSet(col: Int, row: Int, s: String) {
|
override def onScreenSet(col: Int, row: Int, s: String) {
|
||||||
super.onScreenSet(col, row, s)
|
super.onScreenSet(col, row, s)
|
||||||
litPixels = -1
|
relativeLitArea = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
@SideOnly(Side.CLIENT)
|
@SideOnly(Side.CLIENT)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user