working on performance, removing implicit conversions to rich number types in frequently called places (i.e. anything somehow called per tick); optimized power distribution a bit; added a tick delay for continuous power consumption stuff (screens, computer); converted some methods to lazy vals and caching multi-screen bounds

This commit is contained in:
Florian Nücke 2013-12-09 01:32:31 +01:00
parent 8c948098d8
commit 407d25131f
44 changed files with 266 additions and 240 deletions

View File

@ -87,6 +87,7 @@ class Settings(config: Config) {
val ratioUniversalElectricity = config.getDouble("power.ratioUniversalElectricity").toFloat val ratioUniversalElectricity = config.getDouble("power.ratioUniversalElectricity").toFloat
val chargeRate = config.getDouble("power.chargerChargeRate") val chargeRate = config.getDouble("power.chargerChargeRate")
val generatorEfficiency = config.getDouble("power.generatorEfficiency") val generatorEfficiency = config.getDouble("power.generatorEfficiency")
val tickFrequency = 20
// power.buffer // power.buffer
val bufferCapacitor = config.getDouble("power.buffer.capacitor") max 0 val bufferCapacitor = config.getDouble("power.buffer.capacitor") max 0

View File

@ -41,7 +41,7 @@ object PacketSender {
val pb = new PacketBuilder(PacketType.Clipboard) val pb = new PacketBuilder(PacketType.Clipboard)
pb.writeTileEntity(t) pb.writeTileEntity(t)
pb.writeUTF(value.substring(0, value.length min 1024)) pb.writeUTF(value.substring(0, math.min(value.length, 1024)))
pb.sendToServer() pb.sendToServer()
} }

View File

@ -116,9 +116,9 @@ class Robot(playerInventory: InventoryPlayer, val robot: tileentity.Robot) exten
protected def changeSize(w: Double, h: Double) = { protected def changeSize(w: Double, h: Double) = {
val bw = w * MonospaceFontRenderer.fontWidth val bw = w * MonospaceFontRenderer.fontWidth
val bh = h * MonospaceFontRenderer.fontHeight val bh = h * MonospaceFontRenderer.fontHeight
val scaleX = (bufferWidth / (bw + bufferMargin * 2.0)) min 1 val scaleX = math.min(bufferWidth / (bw + bufferMargin * 2.0), 1)
val scaleY = (bufferHeight / (bh + bufferMargin * 2.0)) min 1 val scaleY = math.min(bufferHeight / (bh + bufferMargin * 2.0), 1)
scaleX min scaleY math.min(scaleX, scaleY)
} }
private def drawSelection() { private def drawSelection() {

View File

@ -61,9 +61,9 @@ class Screen(val screen: tileentity.Screen) extends Buffer {
protected def changeSize(w: Double, h: Double) = { protected def changeSize(w: Double, h: Double) = {
val bw = w * MonospaceFontRenderer.fontWidth val bw = w * MonospaceFontRenderer.fontWidth
val bh = h * MonospaceFontRenderer.fontHeight val bh = h * MonospaceFontRenderer.fontHeight
val scaleX = (width / (bw + bufferMargin * 2.0)) min 1 val scaleX = math.min(width / (bw + bufferMargin * 2.0), 1)
val scaleY = (height / (bh + bufferMargin * 2.0)) min 1 val scaleY = math.min(height / (bh + bufferMargin * 2.0), 1)
val scale = scaleX min scaleY val scale = math.min(scaleX, scaleY)
val innerWidth = (bw * scale).toInt val innerWidth = (bw * scale).toInt
val innerHeight = (bh * scale).toInt val innerHeight = (bh * scale).toInt
x = (width - (innerWidth + bufferMargin * 2)) / 2 x = (width - (innerWidth + bufferMargin * 2)) / 2

View File

@ -19,7 +19,8 @@ object MonospaceFontRenderer {
def init(textureManager: TextureManager) = this.synchronized( def init(textureManager: TextureManager) = this.synchronized(
instance = instance.orElse(Some(new Renderer(textureManager)))) instance = instance.orElse(Some(new Renderer(textureManager))))
val (fontWidth, fontHeight) = (5, 9) val fontWidth = 5
val fontHeight = 9
def drawString(x: Int, y: Int, value: Array[Char], color: Array[Short], depth: PackedColor.Depth.Value) = instance match { def drawString(x: Int, y: Int, value: Array[Char], color: Array[Short], depth: PackedColor.Depth.Value) = instance match {
case None => OpenComputers.log.warning("Trying to render string with uninitialized MonospaceFontRenderer.") case None => OpenComputers.log.warning("Trying to render string with uninitialized MonospaceFontRenderer.")

View File

@ -96,7 +96,10 @@ object BufferRenderer {
} }
private def drawBorder(x: Double, y: Double, w: Double, h: Double, u1: Int, v1: Int, u2: Int, v2: Int) = { private def drawBorder(x: Double, y: Double, w: Double, h: Double, u1: Int, v1: Int, u2: Int, v2: Int) = {
val (u1d, u2d, v1d, v2d) = (u1 / 16.0, u2 / 16.0, v1 / 16.0, v2 / 16.0) val u1d = u1 / 16.0
val u2d = u2 / 16.0
val v1d = v1 / 16.0
val v2d = v2 / 16.0
val t = Tessellator.instance val t = Tessellator.instance
t.startDrawingQuads() t.startDrawingQuads()
t.addVertexWithUV(x, y + h, 0, u1d, v2d) t.addVertexWithUV(x, y + h, 0, u1d, v2d)

View File

@ -64,7 +64,7 @@ object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with
GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5) GL11.glTranslated(x + 0.5, y + 0.5, z + 0.5)
if (distance > fadeDistanceSq) { if (distance > fadeDistanceSq) {
RenderState.setBlendAlpha(0f max (1 - (distance - fadeDistanceSq) * fadeRatio).toFloat) RenderState.setBlendAlpha(math.max(0, 1 - ((distance - fadeDistanceSq) * fadeRatio).toFloat))
} }
MonospaceFontRenderer.init(tileEntityRenderer.renderEngine) MonospaceFontRenderer.init(tileEntityRenderer.renderEngine)
@ -77,8 +77,10 @@ object ScreenRenderer extends TileEntitySpecialRenderer with Callable[Int] with
private def compileOrDraw(list: Int) = if (screen.bufferIsDirty && !RenderState.compilingDisplayList) { private def compileOrDraw(list: Int) = if (screen.bufferIsDirty && !RenderState.compilingDisplayList) {
screen.bufferIsDirty = false screen.bufferIsDirty = false
val (sx, sy) = (screen.width, screen.height) val sx = screen.width
val (tw, th) = (sx * 16f, sy * 16f) val sy = screen.height
val tw = sx * 16f
val th = sy * 16f
GL11.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE) GL11.glNewList(list, GL11.GL_COMPILE_AND_EXECUTE)

View File

@ -46,7 +46,7 @@ class PacketBuilder(packetType: PacketType.Value, private val stream: ByteArrayO
val manager = server.getConfigurationManager val manager = server.getConfigurationManager
for (player <- manager.playerEntityList.map(_.asInstanceOf[EntityPlayerMP]) if player.dimension == dimension) { for (player <- manager.playerEntityList.map(_.asInstanceOf[EntityPlayerMP]) if player.dimension == dimension) {
val playerRenderDistance = Int.MaxValue // ObfuscationReflectionHelper.getPrivateValue(classOf[EntityPlayerMP], player, "renderDistance").asInstanceOf[Integer] val playerRenderDistance = Int.MaxValue // ObfuscationReflectionHelper.getPrivateValue(classOf[EntityPlayerMP], player, "renderDistance").asInstanceOf[Integer]
val playerSpecificRange = range min ((manager.getViewDistance min playerRenderDistance) * 16) val playerSpecificRange = math.min(range, (manager.getViewDistance min playerRenderDistance) * 16)
if (player.getDistanceSq(x, y, z) < playerSpecificRange * playerSpecificRange) { if (player.getDistanceSq(x, y, z) < playerSpecificRange * playerSpecificRange) {
sendToPlayer(player.asInstanceOf[Player]) sendToPlayer(player.asInstanceOf[Player])
} }

View File

@ -18,7 +18,7 @@ abstract class Computer extends Delegate {
override def isProvidingWeakPower(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) = override def isProvidingWeakPower(world: IBlockAccess, x: Int, y: Int, z: Int, side: ForgeDirection) =
world.getBlockTileEntity(x, y, z) match { world.getBlockTileEntity(x, y, z) match {
case computer: tileentity.Computer => computer.output(side) max 0 min 15 case computer: tileentity.Computer => math.min(math.max(computer.output(side), 0), 15)
case _ => super.isProvidingWeakPower(world, x, y, z, side) case _ => super.isProvidingWeakPower(world, x, y, z, side)
} }

View File

@ -79,8 +79,8 @@ class Keyboard(val parent: SpecialDelegator) extends SpecialDelegate {
val z0 = -up.offsetZ * sizes(1) - side.offsetZ * sizes(2) - forward.offsetZ * sizes(0) val z0 = -up.offsetZ * sizes(1) - side.offsetZ * sizes(2) - forward.offsetZ * sizes(0)
val z1 = up.offsetZ * sizes(1) + side.offsetZ * sizes(2) - forward.offsetZ * 0.5f val z1 = up.offsetZ * sizes(1) + side.offsetZ * sizes(2) - forward.offsetZ * 0.5f
AxisAlignedBB.getBoundingBox( AxisAlignedBB.getBoundingBox(
(x0 min x1) + 0.5f, (y0 min y1) + 0.5f, (z0 min z1) + 0.5f, math.min(x0, x1) + 0.5f, math.min(y0, y1) + 0.5f, math.min(z0, z1) + 0.5f,
(x0 max x1) + 0.5f, (y0 max y1) + 0.5f, (z0 max z1) + 0.5f) math.max(x0, x1) + 0.5f, math.max(y0, y1) + 0.5f, math.max(z0, z1) + 0.5f)
} }
override def neighborBlockChanged(world: World, x: Int, y: Int, z: Int, blockId: Int) = override def neighborBlockChanged(world: World, x: Int, y: Int, z: Int, blockId: Int) =

View File

@ -97,8 +97,7 @@ class RobotAfterimage(val parent: SpecialDelegator) extends SpecialDelegate {
def findMovingRobot(world: IBlockAccess, x: Int, y: Int, z: Int): Option[tileentity.Robot] = { def findMovingRobot(world: IBlockAccess, x: Int, y: Int, z: Int): Option[tileentity.Robot] = {
for (side <- ForgeDirection.VALID_DIRECTIONS) { for (side <- ForgeDirection.VALID_DIRECTIONS) {
val (rx, ry, rz) = (x + side.offsetX, y + side.offsetY, z + side.offsetZ) world.getBlockTileEntity(x + side.offsetX, y + side.offsetY, z + side.offsetZ) match {
world.getBlockTileEntity(rx, ry, rz) match {
case proxy: tileentity.RobotProxy if proxy.robot.moveFromX == x && proxy.robot.moveFromY == y && proxy.robot.moveFromZ == z => return Some(proxy.robot) case proxy: tileentity.RobotProxy if proxy.robot.moveFromX == x && proxy.robot.moveFromY == y && proxy.robot.moveFromZ == z => return Some(proxy.robot)
case _ => case _ =>
} }

View File

@ -32,7 +32,7 @@ class RobotProxy(val parent: SpecialDelegator) extends Computer with SpecialDele
if (stack.hasTagCompound) { if (stack.hasTagCompound) {
if (stack.getTagCompound.hasKey(Settings.namespace + "xp")) { if (stack.getTagCompound.hasKey(Settings.namespace + "xp")) {
val xp = stack.getTagCompound.getDouble(Settings.namespace + "xp") val xp = stack.getTagCompound.getDouble(Settings.namespace + "xp")
val level = (Math.pow(xp - Settings.get.baseXpToLevel, 1 / Settings.get.exponentialXpGrowth) / Settings.get.constantXpGrowth).toInt min 30 val level = math.min((Math.pow(xp - Settings.get.baseXpToLevel, 1 / Settings.get.exponentialXpGrowth) / Settings.get.constantXpGrowth).toInt, 30)
if (level > 0) { if (level > 0) {
tooltip.addAll(Tooltip.get(unlocalizedName + "_Level", level)) tooltip.addAll(Tooltip.get(unlocalizedName + "_Level", level))
} }

View File

@ -77,7 +77,8 @@ abstract class Screen(val parent: SimpleDelegator) extends SimpleDelegate {
override def icon(world: IBlockAccess, x: Int, y: Int, z: Int, worldSide: ForgeDirection, localSide: ForgeDirection) = override def icon(world: IBlockAccess, x: Int, y: Int, z: Int, worldSide: ForgeDirection, localSide: ForgeDirection) =
world.getBlockTileEntity(x, y, z) match { world.getBlockTileEntity(x, y, z) match {
case screen: tileentity.Screen if screen.width > 1 || screen.height > 1 => case screen: tileentity.Screen if screen.width > 1 || screen.height > 1 =>
val (right, bottom) = (screen.width - 1, screen.height - 1) val right = screen.width - 1
val bottom = screen.height - 1
val (px, py) = screen.localPosition val (px, py) = screen.localPosition
val (lx, ly) = screen.pitch match { val (lx, ly) = screen.pitch match {
case ForgeDirection.NORTH => (px, py) case ForgeDirection.NORTH => (px, py)

View File

@ -90,7 +90,7 @@ class Buffer(val owner: tileentity.Buffer) extends api.network.Environment with
// avoid sending too much data to our clients. // avoid sending too much data to our clients.
val (x, truncated) = val (x, truncated) =
if (col < 0) (0, s.substring(-col)) if (col < 0) (0, s.substring(-col))
else (col, s.substring(0, s.length min (buffer.width - col))) else (col, s.substring(0, math.min(s.length, buffer.width - col)))
if (buffer.set(x, row, truncated)) if (buffer.set(x, row, truncated))
owner.onScreenSet(x, row, truncated) owner.onScreenSet(x, row, truncated)
} }

View File

@ -69,10 +69,10 @@ abstract class Player(protected val playerInventory: InventoryPlayer, val otherI
if (intoSlot.getHasStack) { if (intoSlot.getHasStack) {
val intoStack = intoSlot.getStack val intoStack = intoSlot.getStack
val itemsAreEqual = fromStack.isItemEqual(intoStack) && ItemStack.areItemStackTagsEqual(fromStack, intoStack) val itemsAreEqual = fromStack.isItemEqual(intoStack) && ItemStack.areItemStackTagsEqual(fromStack, intoStack)
val maxStackSize = fromStack.getMaxStackSize min intoSlot.getSlotStackLimit val maxStackSize = math.min(fromStack.getMaxStackSize, intoSlot.getSlotStackLimit)
val slotHasCapacity = intoStack.stackSize < maxStackSize val slotHasCapacity = intoStack.stackSize < maxStackSize
if (itemsAreEqual && slotHasCapacity) { if (itemsAreEqual && slotHasCapacity) {
val itemsMoved = (maxStackSize - intoStack.stackSize) min fromStack.stackSize val itemsMoved = math.min(maxStackSize - intoStack.stackSize, fromStack.stackSize)
if (itemsMoved > 0) { if (itemsMoved > 0) {
intoStack.stackSize += from.decrStackSize(itemsMoved).stackSize intoStack.stackSize += from.decrStackSize(itemsMoved).stackSize
intoSlot.onSlotChanged() intoSlot.onSlotChanged()
@ -85,8 +85,8 @@ abstract class Player(protected val playerInventory: InventoryPlayer, val otherI
for (i <- begin until end by step if from.getHasStack && from.getStack.stackSize > 0) { for (i <- begin until end by step if from.getHasStack && from.getStack.stackSize > 0) {
val intoSlot = inventorySlots.get(i).asInstanceOf[Slot] val intoSlot = inventorySlots.get(i).asInstanceOf[Slot]
if (!intoSlot.getHasStack && intoSlot.isItemValid(fromStack)) { if (!intoSlot.getHasStack && intoSlot.isItemValid(fromStack)) {
val maxStackSize = fromStack.getMaxStackSize min intoSlot.getSlotStackLimit val maxStackSize = math.min(fromStack.getMaxStackSize, intoSlot.getSlotStackLimit)
val itemsMoved = maxStackSize min fromStack.stackSize val itemsMoved = math.min(maxStackSize, fromStack.stackSize)
intoSlot.putStack(from.decrStackSize(itemsMoved)) intoSlot.putStack(from.decrStackSize(itemsMoved))
somethingChanged = true somethingChanged = true
} }

View File

@ -25,7 +25,7 @@ class Robot(playerInventory: InventoryPlayer, robot: tileentity.Robot) extends P
override def detectAndSendChanges() { override def detectAndSendChanges() {
super.detectAndSendChanges() super.detectAndSendChanges()
if ((robot.globalBuffer - lastSentBuffer).abs > 1) { if (math.abs(robot.globalBuffer - lastSentBuffer) > 1) {
lastSentBuffer = robot.globalBuffer lastSentBuffer = robot.globalBuffer
ServerPacketSender.sendPowerState(robot) ServerPacketSender.sendPowerState(robot)
} }

View File

@ -39,7 +39,7 @@ trait BundledRedstone extends Redstone with IBundledEmitter with IBundledUpdatab
} }
def bundledInput(side: ForgeDirection, color: Int) = def bundledInput(side: ForgeDirection, color: Int) =
_bundledInput(side.ordinal())(color) max _rednetInput(side.ordinal())(color) math.max(_bundledInput(side.ordinal())(color), _rednetInput(side.ordinal())(color))
def rednetInput(side: ForgeDirection, color: Int, value: Int) = def rednetInput(side: ForgeDirection, color: Int, value: Int) =
if (_rednetInput(side.ordinal())(color) != value) { if (_rednetInput(side.ordinal())(color) != value) {
@ -134,7 +134,9 @@ trait BundledRedstone extends Redstone with IBundledEmitter with IBundledUpdatab
if (side == ForgeDirection.UNKNOWN) { if (side == ForgeDirection.UNKNOWN) {
if (Loader.isModLoaded("MineFactoryReloaded")) { if (Loader.isModLoaded("MineFactoryReloaded")) {
for (side <- ForgeDirection.VALID_DIRECTIONS) { for (side <- ForgeDirection.VALID_DIRECTIONS) {
val (nx, ny, nz) = (x + side.offsetX, y + side.offsetY, z + side.offsetZ) val nx = x + side.offsetX
val ny = y + side.offsetY
val nz = z + side.offsetZ
Block.blocksList(world.getBlockId(nx, ny, nz)) match { Block.blocksList(world.getBlockId(nx, ny, nz)) match {
case block: IRedNetNetworkContainer => block.updateNetwork(world, x, y, z) case block: IRedNetNetworkContainer => block.updateNetwork(world, x, y, z)
case _ => case _ =>
@ -143,7 +145,9 @@ trait BundledRedstone extends Redstone with IBundledEmitter with IBundledUpdatab
} }
} }
else { else {
val (nx, ny, nz) = (x + side.offsetX, y + side.offsetY, z + side.offsetZ) val nx = x + side.offsetX
val ny = y + side.offsetY
val nz = z + side.offsetZ
if (Loader.isModLoaded("MineFactoryReloaded")) { if (Loader.isModLoaded("MineFactoryReloaded")) {
Block.blocksList(world.getBlockId(nx, ny, nz)) match { Block.blocksList(world.getBlockId(nx, ny, nz)) match {
case block: IRedNetNetworkContainer => block.updateNetwork(world, x, y, z) case block: IRedNetNetworkContainer => block.updateNetwork(world, x, y, z)
@ -157,7 +161,7 @@ trait BundledRedstone extends Redstone with IBundledEmitter with IBundledUpdatab
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@Optional.Method(modid = "RedLogic") @Optional.Method(modid = "RedLogic")
def getBundledCableStrength(blockFace: Int, toDirection: Int): Array[Byte] = _bundledOutput(toLocal(ForgeDirection.getOrientation(toDirection)).ordinal()).map(value => (value max 0 min 255).toByte) def getBundledCableStrength(blockFace: Int, toDirection: Int): Array[Byte] = _bundledOutput(toLocal(ForgeDirection.getOrientation(toDirection)).ordinal()).map(value => math.min(math.max(value, 0), 255).toByte)
@Optional.Method(modid = "RedLogic") @Optional.Method(modid = "RedLogic")
def onBundledInputChanged() = checkRedstoneInputChanged() def onBundledInputChanged() = checkRedstoneInputChanged()

View File

@ -76,7 +76,7 @@ class Charger extends Environment with Redstone with Analyzable {
override protected def onRedstoneInputChanged(side: ForgeDirection) { override protected def onRedstoneInputChanged(side: ForgeDirection) {
super.onRedstoneInputChanged(side) super.onRedstoneInputChanged(side)
chargeSpeed = 0.0 max (ForgeDirection.VALID_DIRECTIONS.map(input).max min 15) / 15.0 chargeSpeed = math.max(0, math.min(ForgeDirection.VALID_DIRECTIONS.map(input).max, 15) / 15.0)
if (isServer) { if (isServer) {
ServerPacketSender.sendChargerState(this) ServerPacketSender.sendChargerState(this)
} }

View File

@ -18,7 +18,7 @@ abstract class Computer(isRemote: Boolean) extends Environment with ComponentInv
def node = if (isClient) null else computer.node def node = if (isClient) null else computer.node
override def isClient = computer == null override lazy val isClient = computer == null
private var _isRunning = false private var _isRunning = false

View File

@ -20,11 +20,14 @@ abstract class Environment extends net.minecraft.tileentity.TileEntity with Tile
def block = getBlockType def block = getBlockType
private var addedToNetwork = false
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def updateEntity() { override def updateEntity() {
super.updateEntity() super.updateEntity()
if (node != null && node.network == null) { if (!addedToNetwork) {
addedToNetwork = true
Network.joinOrCreateNetwork(this) Network.joinOrCreateNetwork(this)
} }
} }

View File

@ -15,7 +15,7 @@ class Keyboard(isRemote: Boolean) extends Environment with SidedEnvironment with
def node = if (isClient) null else keyboard.node def node = if (isClient) null else keyboard.node
override def isClient = keyboard == null override lazy val isClient = keyboard == null
def onAnalyze(stats: NBTTagCompound, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = node def onAnalyze(stats: NBTTagCompound, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = node

View File

@ -21,6 +21,10 @@ class PowerConverter extends Environment with Analyzable with IEnergySink with I
withConnector(). withConnector().
create() create()
private lazy val isIndustrialCraftAvailable = Loader.isModLoaded("IC2")
private lazy val isBuildCraftAvailable = Loader.isModLoaded("BuildCraft|Energy")
private def demand = if (Settings.get.ignorePower) 0.0 else node.globalBufferSize - node.globalBuffer private def demand = if (Settings.get.ignorePower) 0.0 else node.globalBufferSize - node.globalBuffer
def onAnalyze(stats: NBTTagCompound, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = null def onAnalyze(stats: NBTTagCompound, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = null
@ -30,13 +34,16 @@ class PowerConverter extends Environment with Analyzable with IEnergySink with I
override def updateEntity() { override def updateEntity() {
super.updateEntity() super.updateEntity()
if (isServer) { if (isServer) {
if (Loader.isModLoaded("IC2")) { if (isIndustrialCraftAvailable) {
loadIC2() loadIC2()
} }
if (demand > 0 && Loader.isModLoaded("BuildCraft|Energy")) { if (isBuildCraftAvailable && demand > 1 && world.getWorldInfo.getWorldTotalTime % Settings.get.tickFrequency == 0) {
val wantInMJ = demand.toFloat / Settings.get.ratioBuildCraft val wantInMJ = demand.toFloat / Settings.get.ratioBuildCraft
val gotInMJ = getPowerProvider.useEnergy(1, wantInMJ, true) val powerProvider = getPowerProvider
node.changeBuffer(gotInMJ * Settings.get.ratioBuildCraft) if (wantInMJ < powerProvider.getEnergyStored) {
val gotInMJ = powerProvider.useEnergy(1, wantInMJ, true)
node.changeBuffer(gotInMJ * Settings.get.ratioBuildCraft)
}
} }
} }
} }
@ -74,7 +81,7 @@ class PowerConverter extends Environment with Analyzable with IEnergySink with I
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
// IndustrialCraft // IndustrialCraft
private var isIC2Loaded = false private var addedToPowerGrid = false
private var lastPacketSize = 0.0 private var lastPacketSize = 0.0
@ -82,17 +89,17 @@ class PowerConverter extends Environment with Analyzable with IEnergySink with I
@Optional.Method(modid = "IC2") @Optional.Method(modid = "IC2")
def loadIC2() { def loadIC2() {
if (!isIC2Loaded) { if (!addedToPowerGrid) {
MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this)) MinecraftForge.EVENT_BUS.post(new EnergyTileLoadEvent(this))
isIC2Loaded = true addedToPowerGrid = true
} }
} }
@Optional.Method(modid = "IC2") @Optional.Method(modid = "IC2")
def unloadIC2() { def unloadIC2() {
if (isIC2Loaded) { if (addedToPowerGrid) {
MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this)) MinecraftForge.EVENT_BUS.post(new EnergyTileUnloadEvent(this))
isIC2Loaded = false addedToPowerGrid = false
} }
} }

View File

@ -114,14 +114,14 @@ trait Redstone extends RotationAware with network.Environment with Persistable w
case emitter: IRedstoneEmitter => case emitter: IRedstoneEmitter =>
var strength = 0 var strength = 0
for (i <- -1 to 5) { for (i <- -1 to 5) {
strength = strength max emitter.getEmittedSignalStrength(i, side.getOpposite.ordinal()) strength = math.max(strength, emitter.getEmittedSignalStrength(i, side.getOpposite.ordinal()))
} }
strength strength
case _ => 0 case _ => 0
} }
} }
else 0 else 0
vanilla max redLogic math.max(vanilla, redLogic)
} }
protected def onRedstoneInputChanged(side: ForgeDirection) {} protected def onRedstoneInputChanged(side: ForgeDirection) {}
@ -131,7 +131,9 @@ trait Redstone extends RotationAware with network.Environment with Persistable w
world.notifyBlocksOfNeighborChange(x, y, z, block.blockID) world.notifyBlocksOfNeighborChange(x, y, z, block.blockID)
} }
else { else {
val (nx, ny, nz) = (x + side.offsetX, y + side.offsetY, z + side.offsetZ) val nx = x + side.offsetX
val ny = y + side.offsetY
val nz = z + side.offsetZ
world.notifyBlockOfNeighborChange(nx, ny, nz, block.blockID) world.notifyBlockOfNeighborChange(nx, ny, nz, block.blockID)
world.notifyBlocksOfNeighborChange(nx, ny, nz, world.getBlockId(nx, ny, nz)) world.notifyBlocksOfNeighborChange(nx, ny, nz, world.getBlockId(nx, ny, nz))
} }

View File

@ -97,7 +97,7 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
def updateXpInfo() { def updateXpInfo() {
// xp(level) = base + (level * const) ^ exp // xp(level) = base + (level * const) ^ exp
// pow(xp(level) - base, 1/exp) / const = level // pow(xp(level) - base, 1/exp) / const = level
level = (Math.pow(xp - Settings.get.baseXpToLevel, 1 / Settings.get.exponentialXpGrowth) / Settings.get.constantXpGrowth).toInt min 30 level = math.min((Math.pow(xp - Settings.get.baseXpToLevel, 1 / Settings.get.exponentialXpGrowth) / Settings.get.constantXpGrowth).toInt, 30)
if (battery != null) { if (battery != null) {
battery.setLocalBufferSize(Settings.get.bufferRobot + Settings.get.bufferPerLevel * level) battery.setLocalBufferSize(Settings.get.bufferRobot + Settings.get.bufferPerLevel * level)
} }
@ -140,7 +140,7 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with ISidedInventory w
Blocks.robotAfterimage.setBlock(world, ox, oy, oz, 1) Blocks.robotAfterimage.setBlock(world, ox, oy, oz, 1)
assert(Delegator.subBlock(world, ox, oy, oz).exists(_ == Blocks.robotAfterimage)) assert(Delegator.subBlock(world, ox, oy, oz).exists(_ == Blocks.robotAfterimage))
// Here instead of Lua callback so that it gets called on client, too. // Here instead of Lua callback so that it gets called on client, too.
val moveTicks = (Settings.get.moveDelay * 20).toInt max 1 val moveTicks = math.max((Settings.get.moveDelay * 20).toInt, 1)
setAnimateMove(ox, oy, oz, moveTicks) setAnimateMove(ox, oy, oz, moveTicks)
if (isServer) { if (isServer) {
world.scheduleBlockUpdate(ox, oy, oz, Blocks.robotAfterimage.parent.blockID, moveTicks - 1) world.scheduleBlockUpdate(ox, oy, oz, Blocks.robotAfterimage.parent.blockID, moveTicks - 1)

View File

@ -100,9 +100,9 @@ class RobotProxy(val robot: Robot) extends Computer(robot.isClient) with ISidedI
override def onInventoryChanged() = robot.onInventoryChanged() override def onInventoryChanged() = robot.onInventoryChanged()
override def isClient = robot.isClient override lazy val isClient = robot.isClient
override def isServer = robot.isServer override lazy val isServer = robot.isServer
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //

View File

@ -38,6 +38,8 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
var hasPower = true var hasPower = true
var cachedBounds: Option[AxisAlignedBB] = None
def canConnect(side: ForgeDirection) = toLocal(side) != ForgeDirection.SOUTH def canConnect(side: ForgeDirection) = toLocal(side) != ForgeDirection.SOUTH
def sidedNode(side: ForgeDirection) = if (canConnect(side)) node else null def sidedNode(side: ForgeDirection) = if (canConnect(side)) node else null
@ -49,8 +51,7 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
def localPosition = { def localPosition = {
val (lx, ly, _) = project(this) val (lx, ly, _) = project(this)
val (ox, oy, _) = project(origin) val (ox, oy, _) = project(origin)
val (px, py) = (lx - ox, ly - oy) (lx - ox, ly - oy)
(px, py)
} }
override def hasKeyboard = screens.exists(screen => ForgeDirection.VALID_DIRECTIONS. override def hasKeyboard = screens.exists(screen => ForgeDirection.VALID_DIRECTIONS.
@ -66,6 +67,7 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
origin = this origin = this
screens.clear() screens.clear()
screens += this screens += this
cachedBounds = None
} }
def click(player: EntityPlayer, hitX: Float, hitY: Float, hitZ: Float): Boolean = { def click(player: EntityPlayer, hitX: Float, hitY: Float, hitZ: Float): Boolean = {
@ -119,12 +121,15 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
override def updateEntity() { override def updateEntity() {
super.updateEntity() super.updateEntity()
if (isServer) { if (isServer && world.getWorldInfo.getWorldTotalTime % Settings.get.tickFrequency == 0) {
if (litPixels < 0) { if (litPixels < 0) {
litPixels = buffer.lines.foldLeft(0)((acc, line) => acc + line.count(_ != ' ')) litPixels = 0
for (line <- buffer.lines) for (c <- line) {
if (c != ' ') litPixels += 1
}
} }
val hadPower = hasPower val hadPower = hasPower
val neededPower = Settings.get.screenCost + pixelCost * litPixels val neededPower = (Settings.get.screenCost + pixelCost * litPixels) * 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, hasPower)
@ -213,15 +218,18 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
override def getRenderBoundingBox = override def getRenderBoundingBox =
if ((width == 1 && height == 1) || !isOrigin) super.getRenderBoundingBox if ((width == 1 && height == 1) || !isOrigin) super.getRenderBoundingBox
else { else cachedBounds match {
val (sx, sy, sz) = unproject(width, height, 1) case Some(bounds) => bounds
val ox = x + (if (sx < 0) 1 else 0) case _ =>
val oy = y + (if (sy < 0) 1 else 0) val (sx, sy, sz) = unproject(width, height, 1)
val oz = z + (if (sz < 0) 1 else 0) val ox = x + (if (sx < 0) 1 else 0)
val b = AxisAlignedBB.getAABBPool.getAABB(ox, oy, oz, ox + sx, oy + sy, oz + sz) val oy = y + (if (sy < 0) 1 else 0)
b.setBounds(b.minX min b.maxX, b.minY min b.maxY, b.minZ min b.maxZ, val oz = z + (if (sz < 0) 1 else 0)
b.minX max b.maxX, b.minY max b.maxY, b.minZ max b.maxZ) val b = AxisAlignedBB.getBoundingBox(ox, oy, oz, ox + sx, oy + sy, oz + sz)
b b.setBounds(math.min(b.minX, b.maxX), math.min(b.minY, b.maxY), math.min(b.minZ, b.maxZ),
math.max(b.minX, b.maxX), math.max(b.minY, b.maxY), math.max(b.minZ, b.maxZ))
cachedBounds = Some(b)
b
} }
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
@ -297,6 +305,7 @@ class Screen(var tier: Int) extends Buffer with SidedEnvironment with Rotatable
screen.height = newHeight screen.height = newHeight
screen.origin = newOrigin screen.origin = newOrigin
screen.screens ++= newScreens // It's a set, so there won't be duplicates. screen.screens ++= newScreens // It's a set, so there won't be duplicates.
screen.cachedBounds = None
} }
true true
} }

View File

@ -16,9 +16,9 @@ trait TileEntity {
def block: Block def block: Block
def isClient = world.isRemote lazy val isClient = world.isRemote
def isServer = !isClient lazy val isServer = !isClient
@SideOnly(Side.CLIENT) @SideOnly(Side.CLIENT)
def readFromNBTForClient(nbt: NBTTagCompound) {} def readFromNBTForClient(nbt: NBTTagCompound) {}

View File

@ -120,7 +120,7 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
}) })
def pause(seconds: Double): Boolean = { def pause(seconds: Double): Boolean = {
val ticksToPause = (seconds * 20).toInt max 0 val ticksToPause = math.max((seconds * 20).toInt, 0)
def shouldPause(state: Computer.State.Value) = state match { def shouldPause(state: Computer.State.Value) = state match {
case Computer.State.Stopping | Computer.State.Stopped => false case Computer.State.Stopping | Computer.State.Stopped => false
case Computer.State.Paused if ticksToPause <= remainingPause => false case Computer.State.Paused if ticksToPause <= remainingPause => false
@ -215,27 +215,29 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
worldTime = owner.world.getWorldTime worldTime = owner.world.getWorldTime
// We can have rollbacks from '/time set'. Avoid getting negative uptimes. // We can have rollbacks from '/time set'. Avoid getting negative uptimes.
timeStarted = timeStarted min worldTime timeStarted = math.min(timeStarted, worldTime)
// Reset direct call limits. // Reset direct call limits.
callCounts.synchronized(callCounts.clear()) callCounts.synchronized(if (callCounts.size > 0) 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 if (owner.world.getWorldInfo.getWorldTotalTime % Settings.get.tickFrequency == 0) {
state.synchronized(state.top match { val cost = (if (isRobot) Settings.get.robotCost else Settings.get.computerCost) * Settings.get.tickFrequency
case Computer.State.Paused | state.synchronized(state.top match {
Computer.State.Restarting | case Computer.State.Paused |
Computer.State.Stopping | Computer.State.Restarting |
Computer.State.Stopped => // No power consumption. Computer.State.Stopping |
case Computer.State.Sleeping if lastUpdate < sleepUntil && signals.isEmpty => Computer.State.Stopped => // No power consumption.
if (!node.tryChangeBuffer(-cost * Settings.get.sleepCostFactor)) { case Computer.State.Sleeping if lastUpdate < sleepUntil && signals.isEmpty =>
crash("not enough energy") if (!node.tryChangeBuffer(-cost * Settings.get.sleepCostFactor)) {
} crash("not enough energy")
case _ => }
if (!node.tryChangeBuffer(-cost)) { case _ =>
crash("not enough energy") if (!node.tryChangeBuffer(-cost)) {
} crash("not enough energy")
}) }
})
}
// Avoid spamming user list across the network. // Avoid spamming user list across the network.
if (worldTime % 20 == 0 && usersChanged) { if (worldTime % 20 == 0 && usersChanged) {
@ -396,17 +398,19 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
} }
private def processAddedComponents() { private def processAddedComponents() {
for (component <- addedComponents) { if (addedComponents.size > 0) {
if (component.canBeSeenFrom(node)) { for (component <- addedComponents) {
components.synchronized(components += component.address -> component.name) if (component.canBeSeenFrom(node)) {
// Skip the signal if we're not initialized yet, since we'd generate a components.synchronized(components += component.address -> component.name)
// duplicate in the startup script otherwise. // Skip the signal if we're not initialized yet, since we'd generate a
if (kernelMemory > 0) { // duplicate in the startup script otherwise.
signal("component_added", component.address, component.name) if (kernelMemory > 0) {
signal("component_added", component.address, component.name)
}
} }
} }
addedComponents.clear()
} }
addedComponents.clear()
} }
private def verifyComponents() { private def verifyComponents() {
@ -1214,7 +1218,7 @@ class Computer(val owner: tileentity.Computer) extends ManagedComponent with Con
// memory, regardless of the memory need of the underlying system // memory, regardless of the memory need of the underlying system
// (which may change across releases). // (which may change across releases).
lua.gc(LuaState.GcAction.COLLECT, 0) lua.gc(LuaState.GcAction.COLLECT, 0)
kernelMemory = lua.getTotalMemory - lua.getFreeMemory max 1 kernelMemory = math.max(lua.getTotalMemory - lua.getFreeMemory, 1)
recomputeMemory() recomputeMemory()
// Fake zero sleep to avoid stopping if there are no signals. // Fake zero sleep to avoid stopping if there are no signals.

View File

@ -33,8 +33,8 @@ class Crafting(val owner: MCTileEntity) extends ManagedComponent {
val manager = CraftingManager.getInstance val manager = CraftingManager.getInstance
val result = manager.findMatchingRecipe(CraftingInventory, owner.getWorldObj) val result = manager.findMatchingRecipe(CraftingInventory, owner.getWorldObj)
if (result == null) return false if (result == null) return false
val targetStackSize = if (result.isStackable) wantedCount min result.getMaxStackSize else result.stackSize val targetStackSize = if (result.isStackable) math.min(wantedCount, result.getMaxStackSize) else result.stackSize
val timesCrafted = (targetStackSize / result.stackSize) min amountPossible val timesCrafted = math.min(targetStackSize / result.stackSize, amountPossible)
if (timesCrafted <= 0) return true if (timesCrafted <= 0) return true
GameRegistry.onItemCrafted(context.player, result, this) GameRegistry.onItemCrafted(context.player, result, this)
val surplus = mutable.ArrayBuffer.empty[ItemStack] val surplus = mutable.ArrayBuffer.empty[ItemStack]
@ -75,7 +75,7 @@ class Crafting(val owner: MCTileEntity) extends ManagedComponent {
val stack = inventory.getStackInSlot(toParentSlot(slot)) val stack = inventory.getStackInSlot(toParentSlot(slot))
setInventorySlotContents(slot, stack) setInventorySlotContents(slot, stack)
if (stack != null) { if (stack != null) {
amountPossible = amountPossible min stack.stackSize amountPossible = math.min(amountPossible, stack.stackSize)
} }
} }
} }

View File

@ -133,7 +133,7 @@ class FileSystem(val fileSystem: api.fs.FileSystem, var label: Label) extends Ma
Option(fileSystem.getHandle(handle)) match { Option(fileSystem.getHandle(handle)) match {
case Some(file) => case Some(file) =>
// Limit size of read buffer to avoid crazy allocations. // Limit size of read buffer to avoid crazy allocations.
val buffer = new Array[Byte](n min Settings.get.maxReadBuffer) val buffer = new Array[Byte](math.min(n, Settings.get.maxReadBuffer))
val read = file.read(buffer) val read = file.read(buffer)
if (read >= 0) { if (read >= 0) {
val bytes = val bytes =

View File

@ -38,11 +38,11 @@ class Generator(val owner: MCTileEntity) extends ManagedComponent {
if (space <= 0) { if (space <= 0) {
return result(false, "queue is full") return result(false, "queue is full")
} }
val moveCount = stack.stackSize min space min count val moveCount = math.min(stack.stackSize, math.min(space, count))
existingStack.stackSize += moveCount existingStack.stackSize += moveCount
stack.stackSize -= moveCount stack.stackSize -= moveCount
case _ => case _ =>
inventory = Some(stack.splitStack(stack.stackSize min count)) inventory = Some(stack.splitStack(math.min(stack.stackSize, count)))
} }
player.inventory.setInventorySlotContents(context.selectedSlot, stack) player.inventory.setInventorySlotContents(context.selectedSlot, stack)
result(true) result(true)
@ -61,7 +61,7 @@ class Generator(val owner: MCTileEntity) extends ManagedComponent {
val count = if (args.count > 0) args.checkInteger(0) else Int.MaxValue val count = if (args.count > 0) args.checkInteger(0) else Int.MaxValue
inventory match { inventory match {
case Some(stack) => case Some(stack) =>
val removedStack = stack.splitStack(count min stack.stackSize) val removedStack = stack.splitStack(math.min(count, stack.stackSize))
val success = context.player.inventory.addItemStackToInventory(removedStack) val success = context.player.inventory.addItemStackToInventory(removedStack)
stack.stackSize += removedStack.stackSize stack.stackSize += removedStack.stackSize
if (success && stack.stackSize <= 0) { if (success && stack.stackSize <= 0) {

View File

@ -56,8 +56,8 @@ abstract class GraphicsCard extends ManagedComponent {
screen(s => { screen(s => {
val (gmw, gmh) = maxResolution val (gmw, gmh) = maxResolution
val (smw, smh) = s.maxResolution val (smw, smh) = s.maxResolution
s.resolution = (gmw min smw, gmh min smh) s.resolution = (math.min(gmw, smw), math.min(gmh, smh))
s.depth = PackedColor.Depth(maxDepth.id min s.maxDepth.id) s.depth = PackedColor.Depth(math.min(maxDepth.id, s.maxDepth.id))
s.foreground = 0xFFFFFF s.foreground = 0xFFFFFF
s.background = 0x000000 s.background = 0x000000
result(true) result(true)
@ -101,7 +101,7 @@ abstract class GraphicsCard extends ManagedComponent {
@LuaCallback(value = "maxDepth", direct = true) @LuaCallback(value = "maxDepth", direct = true)
def maxDepth(context: Context, args: Arguments): Array[AnyRef] = def maxDepth(context: Context, args: Arguments): Array[AnyRef] =
screen(s => result(PackedColor.Depth(maxDepth.id min s.maxDepth.id) match { screen(s => result(PackedColor.Depth(math.min(maxDepth.id, s.maxDepth.id)) match {
case PackedColor.Depth.OneBit => 1 case PackedColor.Depth.OneBit => 1
case PackedColor.Depth.FourBit => 4 case PackedColor.Depth.FourBit => 4
case PackedColor.Depth.EightBit => 8 case PackedColor.Depth.EightBit => 8
@ -128,7 +128,7 @@ abstract class GraphicsCard extends ManagedComponent {
screen(s => { screen(s => {
val (gmw, gmh) = maxResolution val (gmw, gmh) = maxResolution
val (smw, smh) = s.maxResolution val (smw, smh) = s.maxResolution
result(gmw min smw, gmh min smh) result(math.min(gmw, smw), math.min(gmh, smh))
}) })
@LuaCallback(value = "get", direct = true) @LuaCallback(value = "get", direct = true)

View File

@ -18,13 +18,13 @@ class PowerDistributor(val owner: PowerInformation) extends ManagedComponent {
var globalBufferSize = 0.0 var globalBufferSize = 0.0
var dirty = true
private var lastSentRatio = 0.0 private var lastSentRatio = 0.0
private val buffers = mutable.Set.empty[Connector] private val buffers = mutable.ArrayBuffer.empty[Connector]
private val distributors = mutable.Set.empty[PowerDistributor] private val distributors = mutable.ArrayBuffer.empty[PowerDistributor]
private var dirty = true
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@ -37,36 +37,29 @@ class PowerDistributor(val owner: PowerInformation) extends ManagedComponent {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
def changeBuffer(delta: Double): Double = { def changeBuffer(delta: Double): Double = {
if (delta == 0) { if (delta == 0) 0
return 0 else if (Settings.get.ignorePower) {
if (delta < 0) 0
else /* if (delta > 0) */ delta
} }
if (Settings.get.ignorePower) { else this.synchronized {
if (delta < 0) {
return 0
}
else /* if (delta > 0) */ {
return delta
}
}
this.synchronized {
val oldBuffer = globalBuffer val oldBuffer = globalBuffer
globalBuffer = (globalBuffer + delta) max 0 min globalBufferSize globalBuffer = math.min(math.max(globalBuffer + delta, 0), globalBufferSize)
if (globalBuffer == oldBuffer) { if (globalBuffer == oldBuffer) {
return delta return delta
} }
dirty = true dirty = true
if (delta < 0) { if (delta < 0) {
var remaining = -delta var remaining = -delta
for (connector <- buffers) { for (connector <- buffers if remaining > 0 && connector.localBufferSize > 0) {
if (connector.localBuffer > 0) { if (connector.localBuffer > 0) {
connector.dirty = true
if (connector.localBuffer < remaining) { if (connector.localBuffer < remaining) {
remaining -= connector.localBuffer remaining -= connector.localBuffer
connector.localBuffer = 0 connector.localBuffer = 0
} }
else { else {
connector.localBuffer -= remaining connector.localBuffer -= remaining
return 0 remaining = 0
} }
} }
} }
@ -74,9 +67,8 @@ class PowerDistributor(val owner: PowerInformation) extends ManagedComponent {
} }
else /* if (delta > 0) */ { else /* if (delta > 0) */ {
var remaining = delta var remaining = delta
for (connector <- buffers) { for (connector <- buffers if remaining > 0 && connector.localBufferSize > 0) {
if (connector.localBuffer < connector.localBufferSize) { if (connector.localBuffer < connector.localBufferSize) {
connector.dirty = true
val space = connector.localBufferSize - connector.localBuffer val space = connector.localBufferSize - connector.localBuffer
if (space < remaining) { if (space < remaining) {
remaining -= space remaining -= space
@ -84,7 +76,7 @@ class PowerDistributor(val owner: PowerInformation) extends ManagedComponent {
} }
else { else {
connector.localBuffer += remaining connector.localBuffer += remaining
return 0 remaining = 0
} }
} }
} }
@ -96,7 +88,7 @@ class PowerDistributor(val owner: PowerInformation) extends ManagedComponent {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
override def update() { override def update() {
if (node != null && (dirty || buffers.exists(_.dirty))) { if (dirty && owner.world.getWorldInfo.getWorldTotalTime % Settings.get.tickFrequency == 0 && node != null) {
updateCachedValues() updateCachedValues()
} }
} }
@ -108,21 +100,25 @@ class PowerDistributor(val owner: PowerInformation) extends ManagedComponent {
if (node == this.node) { if (node == this.node) {
for (node <- node.reachableNodes) node match { for (node <- node.reachableNodes) node match {
case connector: Connector if connector.localBufferSize > 0 => this.synchronized { case connector: Connector if connector.localBufferSize > 0 => this.synchronized {
assert(!buffers.contains(connector))
buffers += connector buffers += connector
globalBuffer += connector.localBuffer globalBuffer += connector.localBuffer
globalBufferSize += connector.localBufferSize globalBufferSize += connector.localBufferSize
} }
case _ => node.host match { case _ => node.host match {
case distributor: PowerDistributor if distributor.node.canBeSeenFrom(this.node) => case distributor: PowerDistributor if distributor.node.canBeSeenFrom(this.node) =>
assert(!distributors.contains(distributor))
distributors += distributor distributors += distributor
case _ => case _ =>
} }
} }
assert(!distributors.contains(this))
distributors += this distributors += this
dirty = true dirty = true
} }
else node match { else node match {
case connector: Connector if connector.localBufferSize > 0 => this.synchronized { case connector: Connector if connector.localBufferSize > 0 => this.synchronized {
assert(!buffers.contains(connector))
buffers += connector buffers += connector
globalBuffer += connector.localBuffer globalBuffer += connector.localBuffer
globalBufferSize += connector.localBufferSize globalBufferSize += connector.localBufferSize
@ -130,6 +126,7 @@ class PowerDistributor(val owner: PowerInformation) extends ManagedComponent {
} }
case _ => node.host match { case _ => node.host match {
case distributor: PowerDistributor if distributor.node.canBeSeenFrom(this.node) => case distributor: PowerDistributor if distributor.node.canBeSeenFrom(this.node) =>
assert(!distributors.contains(distributor))
distributors += distributor distributors += distributor
case _ => case _ =>
} }
@ -162,16 +159,16 @@ class PowerDistributor(val owner: PowerInformation) extends ManagedComponent {
def updateCachedValues() { def updateCachedValues() {
// Computer average fill ratio of all buffers. // Computer average fill ratio of all buffers.
val (sumBuffer, sumBufferSize) = var sumBuffer, sumBufferSize = 0.0
buffers.foldRight((0.0, 0.0))((c, acc) => { for (buffer <- buffers) {
c.dirty = false // clear dirty flag for all connectors sumBuffer += buffer.localBuffer
(acc._1 + c.localBuffer, acc._2 + c.localBufferSize) sumBufferSize += buffer.localBufferSize
}) }
// Only send updates if the state changed by more than 5%, more won't be // 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 // noticeable "from the outside" anyway. We send more frequent updates in
// the gui/container of a block that needs it (like robots). // the gui/container of a block that needs it (like robots).
val fillRatio = sumBuffer / sumBufferSize val fillRatio = sumBuffer / sumBufferSize
val shouldSend = (lastSentRatio - fillRatio).abs > (5.0 / 100.0) val shouldSend = math.abs(lastSentRatio - fillRatio) > (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

View File

@ -73,7 +73,7 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) with RobotConte
if (args.count > 0 && args.checkAny(0) != null) checkSlot(args, 0) if (args.count > 0 && args.checkAny(0) != null) checkSlot(args, 0)
else selectedSlot else selectedSlot
result(stackInSlot(slot) match { result(stackInSlot(slot) match {
case Some(stack) => (robot.getInventoryStackLimit min stack.getMaxStackSize) - stack.stackSize case Some(stack) => math.min(robot.getInventoryStackLimit, stack.getMaxStackSize) - stack.stackSize
case _ => robot.getInventoryStackLimit case _ => robot.getInventoryStackLimit
}) })
} }
@ -98,8 +98,8 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) with RobotConte
else result((stackInSlot(selectedSlot), stackInSlot(slot)) match { else result((stackInSlot(selectedSlot), stackInSlot(slot)) match {
case (Some(from), Some(to)) => case (Some(from), Some(to)) =>
if (haveSameItemType(from, to)) { if (haveSameItemType(from, to)) {
val space = (robot.getInventoryStackLimit min to.getMaxStackSize) - to.stackSize val space = math.min(robot.getInventoryStackLimit, to.getMaxStackSize) - to.stackSize
val amount = count min space min from.stackSize val amount = math.min(count, math.min(space, from.stackSize))
if (amount > 0) { if (amount > 0) {
from.stackSize -= amount from.stackSize -= amount
to.stackSize += amount to.stackSize += amount
@ -148,7 +148,7 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) with RobotConte
if (dropped != null && dropped.stackSize > 0) { if (dropped != null && dropped.stackSize > 0) {
def tryDropIntoInventory(inventory: IInventory, filter: (Int) => Boolean) = { def tryDropIntoInventory(inventory: IInventory, filter: (Int) => Boolean) = {
var success = false var success = false
val maxStackSize = inventory.getInventoryStackLimit min dropped.getMaxStackSize val maxStackSize = math.min(inventory.getInventoryStackLimit, dropped.getMaxStackSize)
val shouldTryMerge = !dropped.isItemStackDamageable && dropped.getMaxStackSize > 1 && inventory.getInventoryStackLimit > 1 val shouldTryMerge = !dropped.isItemStackDamageable && dropped.getMaxStackSize > 1 && inventory.getInventoryStackLimit > 1
if (shouldTryMerge) { if (shouldTryMerge) {
for (slot <- 0 until inventory.getSizeInventory if dropped.stackSize > 0 && filter(slot)) { for (slot <- 0 until inventory.getSizeInventory if dropped.stackSize > 0 && filter(slot)) {
@ -157,7 +157,7 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) with RobotConte
existing.isItemEqual(dropped) && ItemStack.areItemStackTagsEqual(existing, dropped) existing.isItemEqual(dropped) && ItemStack.areItemStackTagsEqual(existing, dropped)
if (shouldMerge) { if (shouldMerge) {
val space = maxStackSize - existing.stackSize val space = maxStackSize - existing.stackSize
val amount = space min dropped.stackSize val amount = math.min(space, dropped.stackSize)
assert(amount > 0) assert(amount > 0)
success = true success = true
existing.stackSize += amount existing.stackSize += amount
@ -168,7 +168,7 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) with RobotConte
def canDropIntoSlot(slot: Int) = filter(slot) && inventory.isItemValidForSlot(slot, dropped) && inventory.getStackInSlot(slot) == null def canDropIntoSlot(slot: Int) = filter(slot) && inventory.isItemValidForSlot(slot, dropped) && inventory.getStackInSlot(slot) == null
for (slot <- 0 until inventory.getSizeInventory if dropped.stackSize > 0 && canDropIntoSlot(slot)) { for (slot <- 0 until inventory.getSizeInventory if dropped.stackSize > 0 && canDropIntoSlot(slot)) {
val amount = maxStackSize min dropped.stackSize val amount = math.min(maxStackSize, dropped.stackSize)
inventory.setInventorySlotContents(slot, dropped.splitStack(amount)) inventory.setInventorySlotContents(slot, dropped.splitStack(amount))
success = true success = true
} }
@ -256,8 +256,8 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) with RobotConte
for (slot <- 0 until inventory.getSizeInventory if !success && filter(slot)) { for (slot <- 0 until inventory.getSizeInventory if !success && filter(slot)) {
val stack = inventory.getStackInSlot(slot) val stack = inventory.getStackInSlot(slot)
if (stack != null) { if (stack != null) {
val maxStackSize = robot.getInventoryStackLimit min stack.getMaxStackSize val maxStackSize = math.min(robot.getInventoryStackLimit, stack.getMaxStackSize)
val amount = maxStackSize min stack.stackSize min count val amount = math.min(maxStackSize, math.min(stack.stackSize, count))
val sucked = stack.splitStack(amount) val sucked = stack.splitStack(amount)
success = player.inventory.addItemStackToInventory(sucked) success = player.inventory.addItemStackToInventory(sucked)
stack.stackSize += sucked.stackSize stack.stackSize += sucked.stackSize
@ -600,7 +600,7 @@ class Robot(val robot: tileentity.Robot) extends Computer(robot) with RobotConte
private def checkOptionalItemCount(args: Arguments, n: Int) = private def checkOptionalItemCount(args: Arguments, n: Int) =
if (args.count > n && args.checkAny(n) != null) { if (args.count > n && args.checkAny(n) != null) {
args.checkInteger(n) max 0 min robot.getInventoryStackLimit math.max(args.checkInteger(n), math.min(0, robot.getInventoryStackLimit))
} }
else robot.getInventoryStackLimit else robot.getInventoryStackLimit

View File

@ -30,7 +30,7 @@ class WirelessNetworkCard(val owner: TileEntity) extends NetworkCard {
@LuaCallback("setStrength") @LuaCallback("setStrength")
def setStrength(context: Context, args: Arguments): Array[AnyRef] = { def setStrength(context: Context, args: Arguments): Array[AnyRef] = {
strength = args.checkDouble(0) max 0 min Settings.get.maxWirelessRange strength = math.max(args.checkDouble(0), math.min(0, Settings.get.maxWirelessRange))
result(strength) result(strength)
} }

View File

@ -80,17 +80,17 @@ class Inventory(player: Player) extends InventoryPlayer(player) {
val existing = getStackInSlot(slot) val existing = getStackInSlot(slot)
existing != null && existing.isItemEqual(stack) && existing != null && existing.isItemEqual(stack) &&
(!existing.getHasSubtypes || existing.getItemDamage == stack.getItemDamage) && (!existing.getHasSubtypes || existing.getItemDamage == stack.getItemDamage) &&
(existing.stackSize < (existing.getMaxStackSize min getInventoryStackLimit)) (existing.stackSize < math.min(existing.getMaxStackSize, getInventoryStackLimit))
}).getOrElse(getFirstEmptyStackAccepting(stack)) }).getOrElse(getFirstEmptyStackAccepting(stack))
if (slot >= firstInventorySlot) { if (slot >= firstInventorySlot) {
if (getStackInSlot(slot) == null) { if (getStackInSlot(slot) == null) {
val amount = stack.stackSize min (getInventoryStackLimit min stack.getMaxStackSize) val amount = math.min(stack.stackSize, math.min(getInventoryStackLimit, stack.getMaxStackSize))
setInventorySlotContents(slot, stack.splitStack(amount)) setInventorySlotContents(slot, stack.splitStack(amount))
} }
else { else {
val existing = getStackInSlot(slot) val existing = getStackInSlot(slot)
val space = (getInventoryStackLimit min existing.getMaxStackSize) - existing.stackSize val space = math.min(getInventoryStackLimit, existing.getMaxStackSize) - existing.stackSize
val amount = stack.stackSize min space val amount = math.min(stack.stackSize, space)
existing.stackSize += amount existing.stackSize += amount
stack.stackSize -= amount stack.stackSize -= amount
} }

View File

@ -153,7 +153,7 @@ class Player(val robot: Robot) extends EntityPlayer(robot.world, Settings.get.na
(!PortalGun.isPortalGun(stack) || PortalGun.isStandardPortalGun(stack)) && { (!PortalGun.isPortalGun(stack) || PortalGun.isStandardPortalGun(stack)) && {
val oldSize = stack.stackSize val oldSize = stack.stackSize
val oldDamage = if (stack != null) stack.getItemDamage else 0 val oldDamage = if (stack != null) stack.getItemDamage else 0
val heldTicks = 0 max stack.getMaxItemUseDuration min (duration * 20).toInt val heldTicks = math.max(0, math.min(stack.getMaxItemUseDuration, (duration * 20).toInt))
val newStack = stack.useItemRightClick(world, this) val newStack = stack.useItemRightClick(world, this)
if (isUsingItem) { if (isUsingItem) {
getItemInUse.onPlayerStoppedUsing(world, this, getItemInUse.getMaxItemUseDuration - heldTicks) getItemInUse.onPlayerStoppedUsing(world, this, getItemInUse.getMaxItemUseDuration - heldTicks)
@ -270,7 +270,7 @@ class Player(val robot: Robot) extends EntityPlayer(robot.world, Settings.get.na
if (stack != null) { if (stack != null) {
robot.addXp(Settings.get.robotActionXp) robot.addXp(Settings.get.robotActionXp)
} }
return (breakTime * Settings.get.harvestRatio * ((1 - robot.level * Settings.get.harvestSpeedBoostPerLevel) max 0)) max 0.05 return math.max(breakTime * Settings.get.harvestRatio * math.max(1 - robot.level * Settings.get.harvestSpeedBoostPerLevel, 0), 0.05)
} }
0 0
} }
@ -280,13 +280,13 @@ class Player(val robot: Robot) extends EntityPlayer(robot.world, Settings.get.na
private def tryRepair(stack: ItemStack, oldDamage: Int) { private def tryRepair(stack: ItemStack, oldDamage: Int) {
val needsRepairing = stack.isItemStackDamageable && stack.getItemDamage > oldDamage val needsRepairing = stack.isItemStackDamageable && stack.getItemDamage > oldDamage
val damageRate = Settings.get.itemDamageRate * ((1 - robot.level * Settings.get.toolEfficiencyPerLevel) max 0) val damageRate = Settings.get.itemDamageRate * math.max(1 - robot.level * Settings.get.toolEfficiencyPerLevel, 0)
val shouldRepair = needsRepairing && getRNG.nextDouble() >= damageRate val shouldRepair = needsRepairing && getRNG.nextDouble() >= damageRate
if (shouldRepair) { if (shouldRepair) {
// If an item takes a lot of damage at once we don't necessarily want to // If an item takes a lot of damage at once we don't necessarily want to
// make *all* of that damage go away. Instead we scale it according to // make *all* of that damage go away. Instead we scale it according to
// our damage probability. This makes sure we don't discard massive // our damage probability. This makes sure we don't discard massive
// damage spikes (e.g. on axes when using the treecapitator mod or such). // damage spikes (e.g. on axes when using the TreeCapitator mod or such).
val addedDamage = ((stack.getItemDamage - oldDamage) * damageRate).toInt val addedDamage = ((stack.getItemDamage - oldDamage) * damageRate).toInt
stack.setItemDamage(oldDamage + addedDamage) stack.setItemDamage(oldDamage + addedDamage)
} }

View File

@ -277,7 +277,7 @@ trait VirtualFileSystem extends OutputStreamFileSystem {
override def available() = override def available() =
if (isClosed) 0 if (isClosed) 0
else (file.data.length - position) max 0 else math.max(file.data.length - position, 0)
override def close() = isClosed = true override def close() = isClosed = true
@ -293,9 +293,10 @@ trait VirtualFileSystem extends OutputStreamFileSystem {
override def read(b: Array[Byte], off: Int, len: Int) = override def read(b: Array[Byte], off: Int, len: Int) =
if (!isClosed) { if (!isClosed) {
if (available == 0) -1 val count = available()
if (count == 0) -1
else { else {
val n = len min available val n = math.min(len, count)
file.data.view(position, file.data.length).copyToArray(b, off, n) file.data.view(position, file.data.length).copyToArray(b, off, n)
position += n position += n
n n
@ -311,7 +312,7 @@ trait VirtualFileSystem extends OutputStreamFileSystem {
override def skip(n: Long) = override def skip(n: Long) =
if (!isClosed) { if (!isClosed) {
position = ((position + n) min Int.MaxValue).toInt position = math.min((position + n).toInt, Int.MaxValue)
position position
} }
else throw new io.IOException("file is closed") else throw new io.IOException("file is closed")

View File

@ -85,7 +85,7 @@ object ZipFileInputStreamFileSystem {
var root: ArchiveDirectory = null var root: ArchiveDirectory = null
for (entry <- directories ++ files) { for (entry <- directories ++ files) {
if (entry.path.length > 0) { if (entry.path.length > 0) {
val parent = entry.path.substring(0, entry.path.lastIndexOf('/') max 0) val parent = entry.path.substring(0, math.max(entry.path.lastIndexOf('/'), 0))
directories.find(d => d.path == parent) match { directories.find(d => d.path == parent) match {
case Some(directory) => directory.children += entry case Some(directory) => directory.children += entry
case _ => case _ =>

View File

@ -13,8 +13,6 @@ trait Connector extends Node with network.Connector with Persistable {
var localBuffer = 0.0 var localBuffer = 0.0
var dirty = true
private var distributor: Option[PowerDistributor] = None private var distributor: Option[PowerDistributor] = None
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
@ -26,80 +24,76 @@ trait Connector extends Node with network.Connector with Persistable {
// ----------------------------------------------------------------------- // // ----------------------------------------------------------------------- //
def changeBuffer(delta: Double): Double = { def changeBuffer(delta: Double): Double = {
if (delta == 0) { if (delta == 0) 0
return 0 else if (Settings.get.ignorePower) {
if (delta < 0) 0
else /* if (delta > 0) */ delta
} }
if (Settings.get.ignorePower) { else {
if (delta < 0) { this.synchronized(distributor match {
return 0 case Some(d) => d.synchronized(d.changeBuffer(change(delta)))
} case _ => change(delta)
else /* if (delta > 0) */ { })
return delta
}
} }
def change() = { }
val oldBuffer = localBuffer
localBuffer += delta private def change(delta: Double): Double = {
val remaining = if (localBuffer < 0) { if (localBufferSize <= 0) return delta
val remaining = localBuffer val oldBuffer = localBuffer
localBuffer = 0 localBuffer += delta
remaining val remaining = if (localBuffer < 0) {
} val remaining = localBuffer
else if (localBuffer > localBufferSize) { localBuffer = 0
val remaining = localBuffer - localBufferSize
localBuffer = localBufferSize
remaining
}
else 0
dirty ||= (localBuffer != oldBuffer)
remaining remaining
} }
this.synchronized(distributor match { else if (localBuffer > localBufferSize) {
case Some(d) => d.synchronized(d.changeBuffer(change())) val remaining = localBuffer - localBufferSize
case _ => change() localBuffer = localBufferSize
}) remaining
}
else 0
if (localBuffer != oldBuffer) {
this.synchronized(distributor match {
case Some(d) => d.dirty = true
case _ =>
})
}
remaining
} }
def tryChangeBuffer(delta: Double): Boolean = { def tryChangeBuffer(delta: Double): Boolean = {
if (delta == 0) { if (delta == 0) true
return true else if (Settings.get.ignorePower) delta < 0
} else {
if (Settings.get.ignorePower) { this.synchronized(distributor match {
if (delta < 0) { case Some(d) => d.synchronized {
return true val newGlobalBuffer = globalBuffer + delta
} newGlobalBuffer >= 0 && newGlobalBuffer <= globalBufferSize && d.changeBuffer(delta) == 0
else /* if (delta > 0) */ {
return false
}
}
this.synchronized(distributor match {
case Some(d) => d.synchronized {
val newGlobalBuffer = globalBuffer + delta
newGlobalBuffer >= 0 && newGlobalBuffer <= globalBufferSize && d.changeBuffer(delta) == 0
}
case _ =>
val newLocalBuffer = localBuffer + delta
if (newLocalBuffer < 0 || newLocalBuffer > localBufferSize) {
false
} }
else { case _ =>
localBuffer = newLocalBuffer val newLocalBuffer = localBuffer + delta
true if (newLocalBuffer < 0 || newLocalBuffer > localBufferSize) {
} false
}) }
else {
localBuffer = newLocalBuffer
true
}
})
}
} }
def setLocalBufferSize(size: Double) { def setLocalBufferSize(size: Double) {
this.synchronized(distributor match { this.synchronized(distributor match {
case Some(d) => d.synchronized { case Some(d) => d.synchronized {
localBufferSize = size max 0 localBufferSize = math.max(size, 0)
val surplus = (localBuffer - localBufferSize) max 0 val surplus = math.max(localBuffer - localBufferSize, 0)
localBuffer = localBuffer min localBufferSize localBuffer = math.min(localBuffer, localBufferSize)
d.changeBuffer(surplus) d.changeBuffer(surplus)
} }
case _ => case _ =>
localBufferSize = size max 0 localBufferSize = math.max(size, 0)
localBuffer = localBuffer min localBufferSize localBuffer = math.min(localBuffer, localBufferSize)
}) })
} }
@ -137,8 +131,7 @@ trait Connector extends Node with network.Connector with Persistable {
override def load(nbt: NBTTagCompound) { override def load(nbt: NBTTagCompound) {
super.load(nbt) super.load(nbt)
localBuffer = nbt.getDouble("buffer") max 0 min localBufferSize localBuffer = math.max(nbt.getDouble("buffer"), math.min(0, localBufferSize))
dirty = true
} }
override def save(nbt: NBTTagCompound) { override def save(nbt: NBTTagCompound) {

View File

@ -220,15 +220,15 @@ object LuaStateFactory {
state.pushScalaFunction(lua => { state.pushScalaFunction(lua => {
val string = lua.checkString(1) val string = lua.checkString(1)
val start = (lua.checkInteger(2) match { val start = math.max(0, lua.checkInteger(2) match {
case i if i < 0 => string.length + i case i if i < 0 => string.length + i
case i => i - 1 case i => i - 1
}) max 0 })
val end = val end =
if (lua.getTop > 2) (lua.checkInteger(3) match { if (lua.getTop > 2) math.min(string.length, lua.checkInteger(3) match {
case i if i < 0 => string.length + i + 1 case i if i < 0 => string.length + i + 1
case i => i case i => i
}) min string.length })
else string.length else string.length
if (end <= start) lua.pushString("") if (end <= start) lua.pushString("")
else lua.pushString(string.substring(start, end)) else lua.pushString(string.substring(start, end))

View File

@ -8,7 +8,7 @@ class RTree[Data](private val M: Int)(implicit val coordinate: Data => (Double,
// Used for quick checks whether values are in the tree, e.g. for updates. // Used for quick checks whether values are in the tree, e.g. for updates.
private val entries = mutable.Map.empty[Data, Leaf] private val entries = mutable.Map.empty[Data, Leaf]
private val m = (M / 2) max 1 private val m = math.max(M / 2, 1)
private var root = new NonLeaf() private var root = new NonLeaf()
@ -215,7 +215,7 @@ class RTree[Data](private val M: Int)(implicit val coordinate: Data => (Double,
val newVol2 = r2.volumeIncluding(value) val newVol2 = r2.volumeIncluding(value)
val growth1 = newVol1 - r1.volume val growth1 = newVol1 - r1.volume
val growth2 = newVol2 - r2.volume val growth2 = newVol2 - r2.volume
val d = (growth2 - growth1).abs val d = math.abs(growth2 - growth1)
if (d > best) { if (d > best) {
bestValue = Some(value) bestValue = Some(value)
r = if (growth1 < growth2 || (growth1 == growth2 && newVol1 < newVol2)) r1 else r2 r = if (growth1 < growth2 || (growth1 == growth2 && newVol1 < newVol2)) r1 else r2
@ -263,9 +263,9 @@ class RTree[Data](private val M: Int)(implicit val coordinate: Data => (Double,
private class Point(val x: Double, val y: Double, val z: Double) { private class Point(val x: Double, val y: Double, val z: Double) {
def this(p: (Double, Double, Double)) = this(p._1, p._2, p._3) def this(p: (Double, Double, Double)) = this(p._1, p._2, p._3)
def min(other: Point) = new Point(x min other.x, y min other.y, z min other.z) def min(other: Point) = new Point(math.min(x, other.x), math.min(y, other.y), math.min(z, other.z))
def max(other: Point) = new Point(x max other.x, y max other.y, z max other.z) def max(other: Point) = new Point(math.max(x, other.x), math.max(y, other.y), math.max(z, other.z))
def asTuple = (x, y, z) def asTuple = (x, y, z)
} }

View File

@ -71,13 +71,13 @@ class TextBuffer(var width: Int, var height: Int, initialDepth: PackedColor.Dept
*/ */
def size_=(value: (Int, Int)): Boolean = { def size_=(value: (Int, Int)): Boolean = {
val (iw, ih) = value val (iw, ih) = value
val (w, h) = (iw max 1, ih max 1) val (w, h) = (math.max(iw, 1), math.max(ih, 1))
if (width != w || height != h) { if (width != w || height != h) {
val newBuffer = Array.fill(h, w)(' ') val newBuffer = Array.fill(h, w)(' ')
val newColor = Array.fill(h, w)(packed) val newColor = Array.fill(h, w)(packed)
(0 until (h min height)).foreach(y => { (0 until math.min(h, height)).foreach(y => {
Array.copy(buffer(y), 0, newBuffer(y), 0, w min width) Array.copy(buffer(y), 0, newBuffer(y), 0, math.min(w, width))
Array.copy(color(y), 0, newColor(y), 0, w min width) Array.copy(color(y), 0, newColor(y), 0, math.min(w, width))
}) })
buffer = newBuffer buffer = newBuffer
color = newColor color = newColor
@ -98,7 +98,7 @@ class TextBuffer(var width: Int, var height: Int, initialDepth: PackedColor.Dept
var changed = false var changed = false
val line = buffer(row) val line = buffer(row)
val lineColor = color(row) val lineColor = color(row)
for (x <- col until ((col + s.length) min width)) if (x >= 0) { for (x <- col until math.min(col + s.length, width)) if (x >= 0) {
val c = s(x - col) val c = s(x - col)
changed = changed || (line(x) != c) || (lineColor(x) != packed) changed = changed || (line(x) != c) || (lineColor(x) != packed)
line(x) = c line(x) = c
@ -113,10 +113,10 @@ class TextBuffer(var width: Int, var height: Int, initialDepth: PackedColor.Dept
if (w <= 0 || h <= 0) return false if (w <= 0 || h <= 0) return false
if (col + w < 0 || row + h < 0 || col >= width || row >= height) return false if (col + w < 0 || row + h < 0 || col >= width || row >= height) return false
var changed = false var changed = false
for (y <- (row max 0) until ((row + h) min height)) { for (y <- math.max(row, 0) until math.min(row + h, height)) {
val line = buffer(y) val line = buffer(y)
val lineColor = color(y) val lineColor = color(y)
for (x <- (col max 0) until ((col + w) min width)) { for (x <- math.max(col, 0) until math.min(col + w, width)) {
changed = changed || (line(x) != c) || (lineColor(x) != packed) changed = changed || (line(x) != c) || (lineColor(x) != packed)
line(x) = c line(x) = c
lineColor(x) = packed lineColor(x) = packed
@ -133,11 +133,11 @@ class TextBuffer(var width: Int, var height: Int, initialDepth: PackedColor.Dept
// Loop over the target rectangle, starting from the directions away from // Loop over the target rectangle, starting from the directions away from
// the source rectangle and copy the data. This way we ensure we don't // the source rectangle and copy the data. This way we ensure we don't
// overwrite anything we still need to copy. // overwrite anything we still need to copy.
val (dx0, dx1) = ((col + tx + w - 1) max 0 min (width - 1), (col + tx) max 0 min width) match { val (dx0, dx1) = (math.max(col + tx + w - 1, math.min(0, width - 1)), math.max(col + tx, math.min(0, width))) match {
case dx if tx > 0 => dx case dx if tx > 0 => dx
case dx => dx.swap case dx => dx.swap
} }
val (dy0, dy1) = ((row + ty + h - 1) max 0 min (height - 1), (row + ty) max 0 min height) match { val (dy0, dy1) = (math.max(row + ty + h - 1, math.min(0, height - 1)), math.max(row + ty, math.min(0, height))) match {
case dy if ty > 0 => dy case dy if ty > 0 => dy
case dy => dy.swap case dy => dy.swap
} }
@ -170,7 +170,7 @@ class TextBuffer(var width: Int, var height: Int, initialDepth: PackedColor.Dept
size = (w, h) size = (w, h)
val b = nbt.getTagList("buffer") val b = nbt.getTagList("buffer")
for (i <- 0 until (h min b.tagCount)) { for (i <- 0 until math.min(h, b.tagCount)) {
val line = b.tagAt(i).asInstanceOf[NBTTagString].data val line = b.tagAt(i).asInstanceOf[NBTTagString].data
set(0, i, line) set(0, i, line)
} }

View File

@ -33,10 +33,9 @@ object WirelessNetwork {
case Some(tree) => case Some(tree) =>
tree(card) match { tree(card) match {
case Some((x, y, z)) => case Some((x, y, z)) =>
val (dx, dy, dz) = ( val dx = math.abs(card.owner.xCoord + 0.5 - x)
(card.owner.xCoord + 0.5 - x).abs, val dy = math.abs(card.owner.yCoord + 0.5 - y)
(card.owner.yCoord + 0.5 - y).abs, val dz = math.abs(card.owner.zCoord + 0.5 - z)
(card.owner.zCoord + 0.5 - z).abs)
if (dx > 0.5 || dy > 0.5 || dz > 0.5) { if (dx > 0.5 || dy > 0.5 || dz > 0.5) {
tree.remove(card) tree.remove(card)
tree.add(card) tree.add(card)