made power distributor logic a component to be re-usable in robots; general shuffling for robot stuff, now building an "internal" network for each robot that is *not* connected to the outside world. this will limit some cards installed in the robot (e.g. gpus won't work with external screens) but makes it much easier to re-use components without having the issue that they interfere with external stuff (also, it makes robots less of a complete replacement for normal computers, which they should not be, they have a very specific role, after all); reworked how stuff gets saved a bit more, nodes are now generally saved by their host - in particular the base tile entity we use (Environment) will now only automatically save its node if it is that node's host

This commit is contained in:
Florian Nücke 2013-11-17 12:54:58 +01:00
parent 6e1ba98ecf
commit f135d86b58
39 changed files with 546 additions and 519 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 215 B

After

Width:  |  Height:  |  Size: 220 B

View File

@ -7,6 +7,11 @@ package li.cil.oc.api.driver;
* a computer's inventory.
*/
public enum Slot {
/**
* Invalid slot type.
*/
None,
/**
* Extension cards such as graphics cards or redstone cards.
*/

View File

@ -63,8 +63,8 @@ class PacketHandler extends CommonPacketHandler {
}
def onPowerStateResponse(p: PacketParser) =
p.readTileEntity[PowerDistributor]() match {
case Some(t) => t.average = p.readDouble()
p.readTileEntity[PowerInformation]() match {
case Some(t) => t.globalPower = p.readDouble()
case _ => // Invalid packet.
}

View File

@ -132,7 +132,6 @@ object CableRenderer extends TileEntitySpecialRenderer {
GL11.glPushMatrix()
GL11.glTranslated(x, y, z)
GL11.glColor3f(1, 1, 1)
bindTexture(texture)
GL11.glCallList(displayLists + cable.neighbors)

View File

@ -13,13 +13,13 @@ object PowerDistributorRenderer extends TileEntitySpecialRenderer {
private val sideOn = new ResourceLocation(Config.resourceDomain, "textures/blocks/power_distributor_on.png")
override def renderTileEntityAt(tileEntity: TileEntity, x: Double, y: Double, z: Double, f: Float) = {
val balancer = tileEntity.asInstanceOf[tileentity.PowerDistributor]
if (balancer.average > 0) {
val distributor = tileEntity.asInstanceOf[tileentity.PowerDistributor]
if (distributor.globalPower > 0) {
GL11.glPushAttrib(0xFFFFFF)
RenderState.disableLighting()
RenderState.makeItBlend()
RenderState.setBlendAlpha(balancer.average.toFloat)
RenderState.setBlendAlpha(distributor.globalPower.toFloat)
GL11.glPushMatrix()

View File

@ -4,6 +4,7 @@ import li.cil.oc.api.network.{Message, Node, Visibility}
import li.cil.oc.common.component
import li.cil.oc.common.tileentity
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.{Persistable, PackedColor, TextBuffer}
import li.cil.oc.{api, Config}
import net.minecraft.nbt.NBTTagCompound
@ -115,7 +116,8 @@ class Buffer(val owner: Buffer.Environment) extends api.network.Environment with
// ----------------------------------------------------------------------- //
override def load(nbt: NBTTagCompound) = {
buffer.load(nbt.getCompoundTag(Config.namespace + "buffer"))
node.load(nbt.getCompoundTag("node"))
buffer.load(nbt.getCompoundTag("buffer"))
}
override def save(nbt: NBTTagCompound) = {
@ -135,9 +137,8 @@ class Buffer(val owner: Buffer.Environment) extends api.network.Environment with
}
}
val screenNbt = new NBTTagCompound
buffer.save(screenNbt)
nbt.setCompoundTag(Config.namespace + "buffer", screenNbt)
nbt.setNewCompoundTag("node", node.save)
nbt.setNewCompoundTag("buffer", buffer.save)
}
}
@ -164,22 +165,6 @@ object Buffer {
// ----------------------------------------------------------------------- //
override def onConnect(node: Node) {
super.onConnect(node)
if (node == this.node) {
node.connect(buffer.node)
}
}
override def onDisconnect(node: Node) {
super.onDisconnect(node)
if (node == this.node) {
buffer.node.remove()
}
}
// ----------------------------------------------------------------------- //
def onScreenColorChange(foreground: Int, background: Int) {
if (isServer) {
world.markTileEntityChunkModified(x, y, z, this.asInstanceOf[net.minecraft.tileentity.TileEntity])

View File

@ -1,52 +1,22 @@
package li.cil.oc.common.container
import li.cil.oc.api
import li.cil.oc.client.gui.Icons
import li.cil.oc.common.tileentity
import net.minecraft.entity.player.{EntityPlayer, InventoryPlayer}
import net.minecraft.inventory.Slot
import net.minecraft.item.ItemStack
class Case(playerInventory: InventoryPlayer, `case`: tileentity.Case) extends Player(playerInventory, `case`) {
addSlotToContainer(new Slot(`case`, getInventory.size, 58, 17) {
setBackgroundIcon(Icons.get(api.driver.Slot.Power))
override def isItemValid(item: ItemStack) = {
`case`.isItemValidForSlot(0, item)
}
})
addSlotToContainer(58, 17, api.driver.Slot.Power)
for (i <- 0 to 2) {
val index = getInventory.size
addSlotToContainer(new Slot(`case`, index, 80, 17 + i * slotSize) {
setBackgroundIcon(Icons.get(api.driver.Slot.Card))
override def isItemValid(item: ItemStack) = {
`case`.isItemValidForSlot(index, item)
}
})
addSlotToContainer(80, 17 + i * slotSize, api.driver.Slot.Card)
}
for (i <- 0 to 1) {
val index = getInventory.size
addSlotToContainer(new Slot(`case`, index, 102, 17 + i * slotSize) {
setBackgroundIcon(Icons.get(api.driver.Slot.Memory))
override def isItemValid(item: ItemStack) = {
`case`.isItemValidForSlot(index, item)
}
})
addSlotToContainer(102, 17 + i * slotSize, api.driver.Slot.Memory)
}
for (i <- 0 to 1) {
val index = getInventory.size
addSlotToContainer(new Slot(`case`, index, 124, 17 + i * slotSize) {
setBackgroundIcon(Icons.get(api.driver.Slot.HardDiskDrive))
override def isItemValid(item: ItemStack) = {
`case`.isItemValidForSlot(index, item)
}
})
addSlotToContainer(124, 17 + i * slotSize, api.driver.Slot.HardDiskDrive)
}
// Show the player's inventory.

View File

@ -2,17 +2,8 @@ package li.cil.oc.common.container
import li.cil.oc.common.tileentity
import net.minecraft.entity.player.InventoryPlayer
import net.minecraft.inventory.Slot
import net.minecraft.item.ItemStack
class DiskDrive(playerInventory: InventoryPlayer, drive: tileentity.DiskDrive) extends Player(playerInventory, drive) {
// Floppy slot.
addSlotToContainer(new Slot(drive, 0, 80, 35) {
override def isItemValid(item: ItemStack) = {
drive.isItemValidForSlot(0, item)
}
})
// Show the player's inventory.
addSlotToContainer(80, 35)
addPlayerInventorySlots(8, 84)
}

View File

@ -1,5 +1,7 @@
package li.cil.oc.common.container
import li.cil.oc.api
import li.cil.oc.client.gui.Icons
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.entity.player.InventoryPlayer
import net.minecraft.inventory.Container
@ -103,6 +105,17 @@ abstract class Player(protected val playerInventory: InventoryPlayer, val otherI
somethingChanged
}
def addSlotToContainer(x: Int, y: Int, slot: api.driver.Slot = api.driver.Slot.None) {
val index = getInventory.size
addSlotToContainer(new Slot(otherInventory, index, x, y) {
setBackgroundIcon(Icons.get(slot))
override def isItemValid(item: ItemStack) = {
otherInventory.isItemValidForSlot(index, item)
}
})
}
/** Render player inventory at the specified coordinates. */
protected def addPlayerInventorySlots(left: Int, top: Int) = {
// Show the inventory proper. Start at plus one to skip hot bar.

View File

@ -1,46 +1,22 @@
package li.cil.oc.common.container
import li.cil.oc.api
import li.cil.oc.client.gui.Icons
import li.cil.oc.common.tileentity
import net.minecraft.entity.player.{EntityPlayer, InventoryPlayer}
import net.minecraft.inventory.Slot
import net.minecraft.item.ItemStack
class Robot(playerInventory: InventoryPlayer, robot: tileentity.Robot) extends Player(playerInventory, robot) {
addSlotToContainer(new Slot(robot, getInventory.size, 176, 200) {
setBackgroundIcon(Icons.get(api.driver.Slot.Tool))
override def isItemValid(item: ItemStack) = {
robot.isItemValidForSlot(0, item)
}
})
for (i <- 0 to 1) {
val index = getInventory.size
addSlotToContainer(new Slot(robot, index, 194 + i * slotSize, 200) {
setBackgroundIcon(Icons.get(api.driver.Slot.Card))
override def isItemValid(item: ItemStack) = {
robot.isItemValidForSlot(index, item)
}
})
}
addSlotToContainer(176 + 0 * slotSize, 200, api.driver.Slot.Tool)
addSlotToContainer(176 + 1 * slotSize, 200, api.driver.Slot.Card)
addSlotToContainer(176 + 2 * slotSize, 200, api.driver.Slot.HardDiskDrive)
for (i <- 0 to 2) {
val y = 142 + i * slotSize
for (j <- 0 to 2) {
val x = 176 + j * slotSize
val index = getInventory.size
addSlotToContainer(new Slot(robot, index, x, y) {
override def isItemValid(item: ItemStack) = {
robot.isItemValidForSlot(index, item)
}
})
addSlotToContainer(x, y)
}
}
// Show the player's inventory.
addPlayerInventorySlots(8, 142)
override def canInteractWith(player: EntityPlayer) =

View File

@ -41,7 +41,7 @@ trait ComponentInventory extends Inventory with network.Environment with Persist
}
}
components collect {
case Some(component) => node.connect(component.node)
case Some(component) => connectItemNode(component.node)
}
}
}
@ -81,7 +81,7 @@ trait ComponentInventory extends Inventory with network.Environment with Persist
case Some(component) =>
components(slot) = Some(component)
component.load(driver.nbt(item))
node.connect(component.node)
connectItemNode(component.node)
case _ => // No environment (e.g. RAM).
}
case _ => // No driver.
@ -103,4 +103,8 @@ trait ComponentInventory extends Inventory with network.Environment with Persist
case _ => // Nothing to do.
}
}
protected def connectItemNode(node: Node) {
this.node.connect(node)
}
}

View File

@ -4,6 +4,7 @@ import li.cil.oc.Config
import li.cil.oc.api.network._
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.server.{PacketSender => ServerPacketSender, driver, component}
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.ForgeDirection
@ -84,12 +85,16 @@ abstract class Computer(isRemote: Boolean) extends Environment with ComponentInv
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
if (computer != null) computer.load(nbt)
if (isServer) {
computer.load(nbt.getCompoundTag(Config.namespace + "computer"))
}
}
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
if (computer != null) computer.save(nbt)
if (isServer) {
nbt.setNewCompoundTag(Config.namespace + "computer", computer.save)
}
}
// ----------------------------------------------------------------------- //

View File

@ -1,6 +1,8 @@
package li.cil.oc.common.tileentity
import li.cil.oc.Config
import li.cil.oc.api.{Network, network}
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.Persistable
import net.minecraft.nbt.NBTTagCompound
import scala.math.ScalaNumber
@ -40,13 +42,13 @@ abstract class Environment extends net.minecraft.tileentity.TileEntity with Tile
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
load(nbt)
if (node != null) node.load(nbt)
if (node != null && node.host == this) node.load(nbt.getCompoundTag(Config.namespace + "node"))
}
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
save(nbt)
if (node != null) node.save(nbt)
if (node != null && node.host == this) nbt.setNewCompoundTag(Config.namespace + "node", node.save)
}
// ----------------------------------------------------------------------- //

View File

@ -1,12 +1,13 @@
package li.cil.oc.common.tileentity
import li.cil.oc.Config
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.Persistable
import net.minecraft.entity.item.EntityItem
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.inventory.IInventory
import net.minecraft.item.ItemStack
import net.minecraft.nbt.{NBTTagList, NBTTagCompound}
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.world.World
trait Inventory extends TileEntity with IInventory with Persistable {
@ -82,34 +83,27 @@ trait Inventory extends TileEntity with IInventory with Persistable {
override def load(nbt: NBTTagCompound) {
super.load(nbt)
val inventoryNbt = nbt.getTagList(Config.namespace + "inventory.items")
for (i <- 0 until inventoryNbt.tagCount) {
val slotNbt = inventoryNbt.tagAt(i).asInstanceOf[NBTTagCompound]
nbt.getTagList(Config.namespace + "items").foreach[NBTTagCompound](slotNbt => {
val slot = slotNbt.getByte("slot")
if (slot >= 0 && slot < items.length) {
val item = ItemStack.loadItemStackFromNBT(slotNbt.getCompoundTag("item"))
items(slot) = Some(item)
items(slot) = Some(ItemStack.loadItemStackFromNBT(slotNbt.getCompoundTag("item")))
}
}
})
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
val inventoryNbt = new NBTTagList()
items.zipWithIndex collect {
case (Some(stack), slot) => (stack, slot)
} foreach {
case (stack, slot) => {
val slotNbt = new NBTTagCompound()
slotNbt.setByte("slot", slot.toByte)
val itemNbt = new NBTTagCompound()
stack.writeToNBT(itemNbt)
slotNbt.setCompoundTag("item", itemNbt)
inventoryNbt.appendTag(slotNbt)
}
}
nbt.setTag(Config.namespace + "inventory.items", inventoryNbt)
nbt.setNewTagList(Config.namespace + "items",
items.zipWithIndex collect {
case (Some(stack), slot) => (stack, slot)
} map {
case (stack, slot) => {
val slotNbt = new NBTTagCompound()
slotNbt.setByte("slot", slot.toByte)
slotNbt.setNewCompoundTag("item", stack.writeToNBT)
}
})
}
// ----------------------------------------------------------------------- //

View File

@ -1,6 +1,8 @@
package li.cil.oc.common.tileentity
import li.cil.oc.Config
import li.cil.oc.server.component
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.nbt.NBTTagCompound
class Keyboard(isRemote: Boolean) extends Environment with Rotatable {
@ -15,14 +17,14 @@ class Keyboard(isRemote: Boolean) extends Environment with Rotatable {
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
if (isServer) {
keyboard.node.load(nbt)
keyboard.load(nbt.getCompoundTag(Config.namespace + "keyboard"))
}
}
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
if (isServer) {
keyboard.node.save(nbt)
nbt.setNewCompoundTag(Config.namespace + "keyboard", keyboard.save)
}
}
}

View File

@ -5,6 +5,7 @@ import cpw.mods.fml.common.{Loader, Optional}
import ic2.api.energy.event.{EnergyTileLoadEvent, EnergyTileUnloadEvent}
import ic2.api.energy.tile.IEnergySink
import li.cil.oc.api.network._
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.{Config, api}
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.common.{ForgeDirection, MinecraftForge}
@ -63,14 +64,14 @@ class PowerConverter extends Environment with IEnergySink with IPowerReceptor wi
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
if (Loader.isModLoaded("BuildCraft|Energy")) {
getPowerProvider.readFromNBT(nbt)
getPowerProvider.readFromNBT(nbt.getCompoundTag(Config.namespace + "bc"))
}
}
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
if (Loader.isModLoaded("BuildCraft|Energy")) {
getPowerProvider.writeToNBT(nbt)
nbt.setNewCompoundTag(Config.namespace + "bc", getPowerProvider.writeToNBT)
}
}

View File

@ -1,102 +1,44 @@
package li.cil.oc.common.tileentity
import li.cil.oc.Config
import li.cil.oc.api.network._
import li.cil.oc.client.{PacketSender => ClientPacketSender}
import li.cil.oc.server.network.Connector
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.{Config, api}
import li.cil.oc.server.component
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.nbt.NBTTagCompound
import scala.collection.convert.WrapAsScala._
import scala.collection.mutable
class PowerDistributor extends Environment with Analyzable {
val node = api.Network.newNode(this, Visibility.Network).
withComponent("power", Visibility.Network).
create()
class PowerDistributor extends Environment with PowerInformation with Analyzable {
val distributor = new component.PowerDistributor(this)
var globalBuffer = 0.0
var globalBufferSize = 0.0
var average = 0.0
private var lastSentAverage = 0.0
private val buffers = mutable.Set.empty[Connector]
private val distributors = mutable.Set.empty[PowerDistributor]
private var dirty = true
// ----------------------------------------------------------------------- //
@LuaCallback(value = "buffer", direct = true)
def buffer(context: Context, args: Arguments): Array[AnyRef] = result(globalBuffer)
@LuaCallback(value = "bufferSize", direct = true)
def bufferSize(context: Context, args: Arguments): Array[AnyRef] = result(globalBufferSize)
def node = distributor.node
// ----------------------------------------------------------------------- //
override def onAnalyze(stats: NBTTagCompound, player: EntityPlayer, side: Int, hitX: Float, hitY: Float, hitZ: Float) = {
stats.setString(Config.namespace + "text.Analyzer.TotalEnergy", "%.2f/%.2f".format(globalBuffer, globalBufferSize))
stats.setString(Config.namespace + "text.Analyzer.TotalEnergy", "%.2f/%.2f".format(distributor.globalBuffer, distributor.globalBufferSize))
this
}
// ----------------------------------------------------------------------- //
def changeBuffer(delta: Double): Boolean = {
if (delta != 0) this.synchronized {
val oldBuffer = globalBuffer
globalBuffer = (globalBuffer + delta) max 0 min globalBufferSize
if (globalBuffer != oldBuffer) {
dirty = true
if (delta < 0) {
var remaining = -delta
for (connector <- buffers) {
connector.synchronized(if (connector.localBuffer > 0) {
connector.dirty = true
if (connector.localBuffer < remaining) {
remaining -= connector.localBuffer
connector.localBuffer = 0
}
else {
connector.localBuffer -= remaining
return true
}
})
}
}
else if (delta > 0) {
var remaining = delta
for (connector <- buffers) {
connector.synchronized(if (connector.localBuffer < connector.localBufferSize) {
connector.dirty = true
val space = connector.localBufferSize - connector.localBuffer
if (space < remaining) {
remaining -= space
connector.localBuffer = connector.localBufferSize
}
else {
connector.localBuffer += remaining
return true
}
})
}
}
}
}
false
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
distributor.load(nbt.getCompoundTag(Config.namespace + "distributor"))
}
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
nbt.setNewCompoundTag(Config.namespace + "distributor", distributor.save)
}
// ----------------------------------------------------------------------- //
override def updateEntity() {
super.updateEntity()
if (isServer && (dirty || buffers.exists(_.dirty))) {
updateCachedValues()
}
distributor.update()
}
override def validate() {
@ -105,82 +47,4 @@ class PowerDistributor extends Environment with Analyzable {
ClientPacketSender.sendPowerStateRequest(this)
}
}
// ----------------------------------------------------------------------- //
override def onConnect(node: Node) {
super.onConnect(node)
if (node == this.node) {
for (node <- node.network.nodes) node match {
case connector: Connector if connector.localBufferSize > 0 => this.synchronized {
buffers += connector
globalBuffer += connector.localBuffer
globalBufferSize += connector.localBufferSize
}
case _ => node.host match {
case distributor: PowerDistributor => distributors += distributor
case _ =>
}
}
dirty = true
}
else node match {
case connector: Connector => this.synchronized {
buffers += connector
globalBuffer += connector.localBuffer
globalBufferSize += connector.localBufferSize
dirty = true
}
case _ => node.host match {
case distributor: PowerDistributor => distributors += distributor
case _ =>
}
}
}
override def onDisconnect(node: Node) {
super.onDisconnect(node)
if (node == this.node) this.synchronized {
buffers.clear()
distributors.clear()
globalBuffer = 0
globalBufferSize = 0
average = -1
}
else node match {
case connector: Connector => this.synchronized {
buffers -= connector
globalBuffer -= connector.localBuffer
globalBufferSize -= connector.localBufferSize
dirty = true
}
case _ => node.host match {
case distributor: PowerDistributor => distributors -= distributor
case _ =>
}
}
}
// ----------------------------------------------------------------------- //
def updateCachedValues() {
// Computer average fill ratio of all buffers.
val (sumBuffer, sumBufferSize) =
buffers.foldRight((0.0, 0.0))((c, acc) => {
c.dirty = false // clear dirty flag for all connectors
(acc._1 + c.localBuffer, acc._2 + c.localBufferSize)
})
average = if (globalBufferSize > 0) globalBuffer / globalBufferSize else 0
val shouldSend = (lastSentAverage - average).abs > 0.05
for (distributor <- distributors) distributor.synchronized {
distributor.dirty = false
distributor.globalBuffer = sumBuffer
distributor.globalBufferSize = sumBufferSize
distributor.average = average
if (shouldSend) {
distributor.lastSentAverage = lastSentAverage
ServerPacketSender.sendPowerState(distributor)
}
}
}
}

View File

@ -0,0 +1,5 @@
package li.cil.oc.common.tileentity
trait PowerInformation extends TileEntity {
var globalPower = 0.0
}

View File

@ -5,9 +5,10 @@ import cpw.mods.fml.common.{Loader, Optional}
import li.cil.oc.Config
import li.cil.oc.api.network
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.Persistable
import mods.immibis.redlogic.api.wiring._
import net.minecraft.nbt.{NBTTagByte, NBTTagList, NBTTagCompound}
import net.minecraft.nbt.{NBTTagByteArray, NBTTagCompound}
import net.minecraftforge.common.ForgeDirection
@Optional.InterfaceList(Array(
@ -104,67 +105,25 @@ with IConnectable with IBundledEmitter with IBundledUpdatable with IRedstoneEmit
override def load(nbt: NBTTagCompound) = {
super.load(nbt)
val inputNbt = nbt.getTagList(Config.namespace + "redstone.input")
for (i <- 0 until (_input.length min inputNbt.tagCount)) {
_input(i) = inputNbt.tagAt(i).asInstanceOf[NBTTagByte].data
}
nbt.getByteArray(Config.namespace + "rs.input").copyToArray(_input)
nbt.getByteArray(Config.namespace + "rs.output").copyToArray(_output)
val outputNbt = nbt.getTagList(Config.namespace + "redstone.output")
for (i <- 0 until (_output.length min outputNbt.tagCount)) {
_output(i) = outputNbt.tagAt(i).asInstanceOf[NBTTagByte].data
nbt.getTagList(Config.namespace + "rs.bundledInput").iterator[NBTTagByteArray].zipWithIndex.foreach {
case (input, side) => input.byteArray.copyToArray(_bundledInput(side))
}
val bundledInputNbt = nbt.getTagList(Config.namespace + "redstone.bundledInput")
for (i <- 0 until (_bundledInput.length min bundledInputNbt.tagCount)) {
val bundleNbt = bundledInputNbt.tagAt(i).asInstanceOf[NBTTagList]
for (j <- 0 until (_bundledInput(i).length min bundleNbt.tagCount())) {
_bundledInput(i)(j) = bundleNbt.tagAt(j).asInstanceOf[NBTTagByte].data
}
}
val bundledOutputNbt = nbt.getTagList(Config.namespace + "redstone.bundledOutput")
for (i <- 0 until (_bundledOutput.length min bundledOutputNbt.tagCount)) {
val bundleNbt = bundledOutputNbt.tagAt(i).asInstanceOf[NBTTagList]
for (j <- 0 until (_bundledOutput(i).length min bundleNbt.tagCount())) {
_bundledOutput(i)(j) = bundleNbt.tagAt(j).asInstanceOf[NBTTagByte].data
}
nbt.getTagList(Config.namespace + "rs.bundledOutput").iterator[NBTTagByteArray].zipWithIndex.foreach {
case (input, side) => input.byteArray.copyToArray(_bundledOutput(side))
}
}
override def save(nbt: NBTTagCompound) = {
super.save(nbt)
val inputNbt = new NBTTagList()
for (i <- 0 until _input.length) {
inputNbt.appendTag(new NBTTagByte(null, _input(i)))
}
nbt.setTag(Config.namespace + "redstone.input", inputNbt)
nbt.setByteArray(Config.namespace + "rs.input", _input)
nbt.setByteArray(Config.namespace + "rs.output", _output)
val outputNbt = new NBTTagList()
for (i <- 0 until _output.length) {
outputNbt.appendTag(new NBTTagByte(null, _output(i)))
}
nbt.setTag(Config.namespace + "redstone.output", outputNbt)
val bundledInputNbt = new NBTTagList()
for (i <- 0 until _bundledInput.length) {
val bundleNbt = new NBTTagList()
for (j <- 0 until _bundledInput(i).length) {
bundleNbt.appendTag(new NBTTagByte(null, _bundledInput(i)(j)))
}
bundledInputNbt.appendTag(bundleNbt)
}
nbt.setTag(Config.namespace + "redstone.bundledInput", bundledInputNbt)
val bundledOutputNbt = new NBTTagList()
for (i <- 0 until _bundledOutput.length) {
val bundleNbt = new NBTTagList()
for (j <- 0 until _bundledOutput(i).length) {
bundleNbt.appendTag(new NBTTagByte(null, _bundledOutput(i)(j)))
}
bundledOutputNbt.appendTag(bundleNbt)
}
nbt.setTag(Config.namespace + "redstone.bundledOutput", bundledOutputNbt)
nbt.setNewTagList(Config.namespace + "rs.bundledInput", _bundledInput.view)
nbt.setNewTagList(Config.namespace + "rs.bundledOutput", _bundledOutput.view)
}
// ----------------------------------------------------------------------- //

View File

@ -1,30 +1,44 @@
package li.cil.oc.common.tileentity
import li.cil.oc.Config
import li.cil.oc.api
import li.cil.oc.api.driver.Slot
import li.cil.oc.api.network._
import li.cil.oc.client.{PacketSender => ClientPacketSender, gui}
import li.cil.oc.common.component.Buffer
import li.cil.oc.server
import li.cil.oc.server.component
import li.cil.oc.server.component.GraphicsCard
import li.cil.oc.server.driver.Registry
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.client.Minecraft
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import scala.Some
class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer.Environment {
class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer.Environment with PowerInformation {
def this() = this(false)
// ----------------------------------------------------------------------- //
val gpu = new GraphicsCard.Tier1 {
override val maxResolution = (44, 14)
}
val keyboard = new component.Keyboard(this)
var currentGui: Option[gui.Robot] = None
override val node = api.Network.newNode(this, Visibility.None).create()
override val buffer = new Buffer(this) {
override def maxResolution = (44, 14)
}
val (battery, distributor, gpu, keyboard) = if (isServer) {
val battery = api.Network.newNode(this, Visibility.Network).withConnector(10000).create()
val distributor = new component.PowerDistributor(this)
val gpu = new GraphicsCard.Tier1 {
override val maxResolution = (44, 14)
}
val keyboard = new component.Keyboard(this)
(battery, distributor, gpu, keyboard)
}
else (null, null, null, null)
// ----------------------------------------------------------------------- //
def tier = 0
@ -90,7 +104,11 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer.Environmen
override def updateEntity() {
super.updateEntity()
gpu.update()
if (isServer) {
distributor.changeBuffer(10) // just for testing
distributor.update()
gpu.update()
}
}
override def validate() {
@ -110,51 +128,63 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer.Environmen
// ----------------------------------------------------------------------- //
// override def onMessage(message: Message) {
// if (message.source.network == node.network) {
// computer.node.network.sendToReachable(message.source, message.name, message.data: _*)
// }
// else {
// node.network.sendToReachable(message.source, message.name, message.data: _*)
// }
// }
override def onConnect(node: Node) {
super.onConnect(node)
if (node == this.node) {
node.connect(gpu.node)
node.connect(buffer.node)
node.connect(keyboard.node)
server.network.Network.create(computer.node)
computer.node.connect(buffer.node)
computer.node.connect(distributor.node)
computer.node.connect(gpu.node)
distributor.node.connect(battery)
buffer.node.connect(keyboard.node)
}
super.onConnect(node)
}
override def onDisconnect(node: Node) {
super.onDisconnect(node)
if (node == this.node) {
gpu.node.remove()
battery.remove()
buffer.node.remove()
computer.node.remove()
distributor.node.remove()
gpu.node.remove()
keyboard.node.remove()
}
}
override protected def connectItemNode(node: Node) {
computer.node.connect(node)
}
// ----------------------------------------------------------------------- //
override def readFromNBT(nbt: NBTTagCompound) {
super.readFromNBT(nbt)
if (isServer) {
buffer.node.load(nbt.getCompoundTag(Config.namespace + "buffer"))
battery.load(nbt.getCompoundTag(Config.namespace + "battery"))
buffer.load(nbt.getCompoundTag(Config.namespace + "buffer"))
gpu.load(nbt.getCompoundTag(Config.namespace + "gpu"))
keyboard.node.load(nbt.getCompoundTag(Config.namespace + "keyboard"))
keyboard.load(nbt.getCompoundTag(Config.namespace + "keyboard"))
}
}
override def writeToNBT(nbt: NBTTagCompound) {
super.writeToNBT(nbt)
if (isServer) {
val bufferNbt = new NBTTagCompound()
buffer.node.save(bufferNbt)
buffer.save(bufferNbt)
nbt.setCompoundTag(Config.namespace + "buffer", bufferNbt)
val gpuNbt = new NBTTagCompound()
gpu.save(gpuNbt)
nbt.setCompoundTag(Config.namespace + "gpu", gpuNbt)
val keyboardNbt = new NBTTagCompound()
keyboard.node.save(keyboardNbt)
nbt.setCompoundTag(Config.namespace + "keyboard", keyboardNbt)
nbt.setNewCompoundTag(Config.namespace + "battery", battery.save)
nbt.setNewCompoundTag(Config.namespace + "buffer", buffer.save)
nbt.setNewCompoundTag(Config.namespace + "gpu", gpu.save)
nbt.setNewCompoundTag(Config.namespace + "keyboard", keyboard.save)
}
}
@ -173,7 +203,8 @@ class Robot(isRemote: Boolean) extends Computer(isRemote) with Buffer.Environmen
def isItemValidForSlot(slot: Int, item: ItemStack) = (slot, Registry.driverFor(item)) match {
case (0, Some(driver)) => driver.slot(item) == Slot.Tool
case (1 | 2, Some(driver)) => driver.slot(item) == Slot.Card
case (1, Some(driver)) => driver.slot(item) == Slot.Card
case (2, Some(driver)) => driver.slot(item) == Slot.HardDiskDrive
case (3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11, _) => true // Normal inventory.
case _ => false // Invalid slot.
}

View File

@ -154,16 +154,16 @@ trait Rotatable extends TileEntity with Persistable {
override def load(nbt: NBTTagCompound) = {
super.load(nbt)
_pitch = ForgeDirection.getOrientation(nbt.getInteger(Config.namespace + "rotatable.pitch"))
_yaw = ForgeDirection.getOrientation(nbt.getInteger(Config.namespace + "rotatable.yaw"))
_pitch = ForgeDirection.getOrientation(nbt.getInteger(Config.namespace + "pitch"))
_yaw = ForgeDirection.getOrientation(nbt.getInteger(Config.namespace + "yaw"))
updateTranslation()
}
override def save(nbt: NBTTagCompound) = {
super.save(nbt)
nbt.setInteger(Config.namespace + "rotatable.pitch", _pitch.ordinal)
nbt.setInteger(Config.namespace + "rotatable.yaw", _yaw.ordinal)
nbt.setInteger(Config.namespace + "pitch", _pitch.ordinal)
nbt.setInteger(Config.namespace + "yaw", _yaw.ordinal)
}
// ----------------------------------------------------------------------- //

View File

@ -143,12 +143,12 @@ class Screen(var tier: Int) extends Buffer.Environment with Rotatable with Analy
// ----------------------------------------------------------------------- //
override def readFromNBT(nbt: NBTTagCompound) {
tier = nbt.getByte(Config.namespace + "screen.tier")
tier = nbt.getByte(Config.namespace + "tier")
super.readFromNBT(nbt)
}
override def writeToNBT(nbt: NBTTagCompound) {
nbt.setByte(Config.namespace + "screen.tier", tier.toByte)
nbt.setByte(Config.namespace + "tier", tier.toByte)
super.writeToNBT(nbt)
}

View File

@ -57,31 +57,31 @@ class PacketHandler extends CommonPacketHandler {
}
def onKeyDown(p: PacketParser) =
p.readTileEntity[Environment]() match {
p.readTileEntity[Buffer.Environment]() match {
case Some(s: Screen) =>
val char = Char.box(p.readChar())
val code = Int.box(p.readInt())
s.screens.foreach(_.node.sendToNeighbors("keyboard.keyDown", p.player, char, code))
case Some(e) => e.node.sendToNeighbors("keyboard.keyDown", p.player, Char.box(p.readChar()), Int.box(p.readInt()))
case Some(e) => e.buffer.node.sendToNeighbors("keyboard.keyDown", p.player, Char.box(p.readChar()), Int.box(p.readInt()))
case _ => // Invalid packet.
}
def onKeyUp(p: PacketParser) =
p.readTileEntity[Environment]() match {
p.readTileEntity[Buffer.Environment]() match {
case Some(s: Screen) =>
val char = Char.box(p.readChar())
val code = Int.box(p.readInt())
s.screens.foreach(_.node.sendToNeighbors("keyboard.keyUp", p.player, char, code))
case Some(e) => e.node.sendToNeighbors("keyboard.keyUp", p.player, Char.box(p.readChar()), Int.box(p.readInt()))
case Some(e) => e.buffer.node.sendToNeighbors("keyboard.keyUp", p.player, Char.box(p.readChar()), Int.box(p.readInt()))
case _ => // Invalid packet.
}
def onClipboard(p: PacketParser) =
p.readTileEntity[Environment]() match {
p.readTileEntity[Buffer.Environment]() match {
case Some(s: Screen) =>
val value = p.readUTF()
s.screens.foreach(_.node.sendToNeighbors("keyboard.clipboard", p.player, value))
case Some(e) => e.node.sendToNeighbors("keyboard.clipboard", p.player, p.readUTF())
case Some(e) => e.buffer.node.sendToNeighbors("keyboard.clipboard", p.player, p.readUTF())
case _ => // Invalid packet.
}
}

View File

@ -33,11 +33,11 @@ object PacketSender {
}
}
def sendPowerState(t: PowerDistributor, player: Option[Player] = None) {
def sendPowerState(t: PowerInformation, player: Option[Player] = None) {
val pb = new PacketBuilder(PacketType.PowerStateResponse)
pb.writeTileEntity(t)
pb.writeDouble(t.average)
pb.writeDouble(t.globalPower)
player match {
case Some(p) => pb.sendToPlayer(p)

View File

@ -7,11 +7,11 @@ import java.util.concurrent._
import java.util.concurrent.atomic.AtomicInteger
import java.util.logging.Level
import li.cil.oc.api
import li.cil.oc.api.Persistable
import li.cil.oc.api.network._
import li.cil.oc.common.tileentity
import li.cil.oc.server
import li.cil.oc.util.ExtendedLuaState.extendLuaState
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.util.{GameTimeFormatter, LuaStateFactory}
import li.cil.oc.{OpenComputers, Config}
import net.minecraft.entity.player.EntityPlayer
@ -24,7 +24,7 @@ import scala.collection.mutable
import scala.math.ScalaNumber
import scala.runtime.BoxedUnit
class Computer(val owner: tileentity.Computer) extends Environment with Context with Persistable with Runnable {
class Computer(val owner: tileentity.Computer) extends ManagedComponent with Context with Runnable {
val node = api.Network.newNode(this, Visibility.Network).
withComponent("computer", Visibility.Neighbors).
withConnector().
@ -156,7 +156,7 @@ class Computer(val owner: tileentity.Computer) extends Environment with Context
// ----------------------------------------------------------------------- //
def update() {
override def update() {
// Add components that were added since the last update to the actual list
// of components if we can see them. We use this delayed approach to avoid
// issues with components that have a visibility lower than their
@ -279,7 +279,7 @@ class Computer(val owner: tileentity.Computer) extends Environment with Context
// ----------------------------------------------------------------------- //
def onConnect(node: Node) {
override def onConnect(node: Node) {
if (node == this.node) {
rom.foreach(rom => node.connect(rom.node))
tmp.foreach(tmp => node.connect(tmp.node))
@ -293,7 +293,7 @@ class Computer(val owner: tileentity.Computer) extends Environment with Context
owner.onConnect(node)
}
def onDisconnect(node: Node) {
override def onDisconnect(node: Node) {
if (node == this.node) {
stop()
rom.foreach(_.node.remove())
@ -308,7 +308,7 @@ class Computer(val owner: tileentity.Computer) extends Environment with Context
owner.onDisconnect(node)
}
def onMessage(message: Message) {
override def onMessage(message: Message) {
message.data match {
case Array(name: String, args@_*) if message.name == "computer.signal" =>
signal(name, Seq(message.source.address) ++ args: _*)
@ -365,26 +365,19 @@ class Computer(val owner: tileentity.Computer) extends Environment with Context
// ----------------------------------------------------------------------- //
def load(nbt: NBTTagCompound) = this.synchronized {
override def load(nbt: NBTTagCompound) = this.synchronized {
assert(state.top == Computer.State.Stopped)
assert(future.isEmpty)
val computerNbt = nbt.getCompoundTag(Config.namespace + "computer")
assert(users.isEmpty)
assert(signals.isEmpty)
state.clear()
val stateNbt = computerNbt.getTagList("state")
(0 until stateNbt.tagCount).
map(stateNbt.tagAt).
map(_.asInstanceOf[NBTTagInt]).
foreach(s => state.push(Computer.State(s.data)))
val usersNbt = computerNbt.getTagList("users")
(0 until usersNbt.tagCount).
map(usersNbt.tagAt).
map(_.asInstanceOf[NBTTagString]).
foreach(u => users += u.data)
super.load(nbt)
if (state.top != Computer.State.Stopped && init()) {
nbt.getTagList("state").foreach[NBTTagInt](s => state.push(Computer.State(s.data)))
nbt.getTagList("users").foreach[NBTTagString](u => users += u.data)
if (state.size > 0 && state.top != Computer.State.Stopped && init()) {
// Unlimit memory use while unpersisting.
lua.setTotalMemory(Integer.MAX_VALUE)
@ -393,14 +386,14 @@ class Computer(val owner: tileentity.Computer) extends Environment with Context
// on. First, clear the stack, meaning the current kernel.
lua.setTop(0)
unpersist(computerNbt.getByteArray("kernel"))
unpersist(nbt.getByteArray("kernel"))
if (!lua.isThread(1)) {
// This shouldn't really happen, but there's a chance it does if
// the save was corrupt (maybe someone modified the Lua files).
throw new IllegalArgumentException("Invalid kernel.")
}
if (state.contains(Computer.State.SynchronizedCall) || state.contains(Computer.State.SynchronizedReturn)) {
unpersist(computerNbt.getByteArray("stack"))
unpersist(nbt.getByteArray("stack"))
if (!(if (state.contains(Computer.State.SynchronizedCall)) lua.isFunction(2) else lua.isTable(2))) {
// Same as with the above, should not really happen normally, but
// could for the same reasons.
@ -408,17 +401,11 @@ class Computer(val owner: tileentity.Computer) extends Environment with Context
}
}
val componentsNbt = computerNbt.getTagList("components")
components ++= (0 until componentsNbt.tagCount).
map(componentsNbt.tagAt).
map(_.asInstanceOf[NBTTagCompound]).
map(c => c.getString("address") -> c.getString("name"))
val componentsNbt = nbt.getTagList("components")
components ++= componentsNbt.iterator[NBTTagCompound].map(c =>
c.getString("address") -> c.getString("name"))
val signalsNbt = computerNbt.getTagList("signals")
signals ++= (0 until signalsNbt.tagCount).
map(signalsNbt.tagAt).
map(_.asInstanceOf[NBTTagCompound]).
map(signalNbt => {
signals ++= nbt.getTagList("signals").iterator[NBTTagCompound].map(signalNbt => {
val argsNbt = signalNbt.getCompoundTag("args")
val argsLength = argsNbt.getInteger("length")
new Computer.Signal(signalNbt.getString("name"),
@ -432,21 +419,13 @@ class Computer(val owner: tileentity.Computer) extends Environment with Context
}.toArray)
})
rom.foreach(rom => {
val romNbt = computerNbt.getCompoundTag("rom")
rom.node.load(romNbt)
rom.load(romNbt)
})
tmp.foreach(tmp => {
val tmpNbt = computerNbt.getCompoundTag("tmp")
tmp.node.load(tmpNbt)
tmp.load(tmpNbt)
})
kernelMemory = computerNbt.getInteger("kernelMemory")
timeStarted = computerNbt.getLong("timeStarted")
cpuTime = computerNbt.getLong("cpuTime")
if (computerNbt.hasKey("message")) {
message = Some(computerNbt.getString("message"))
rom.foreach(rom => rom.load(nbt.getCompoundTag("rom")))
tmp.foreach(tmp => tmp.load(nbt.getCompoundTag("tmp")))
kernelMemory = nbt.getInteger("kernelMemory")
timeStarted = nbt.getLong("timeStarted")
cpuTime = nbt.getLong("cpuTime")
if (nbt.hasKey("message")) {
message = Some(nbt.getString("message"))
}
// Limit memory again.
@ -466,26 +445,17 @@ class Computer(val owner: tileentity.Computer) extends Environment with Context
else close() // Clean up in case we got a weird state stack.
}
def save(nbt: NBTTagCompound): Unit = this.synchronized {
override def save(nbt: NBTTagCompound): Unit = this.synchronized {
assert(state.top != Computer.State.Running) // Lock on 'this' should guarantee this.
assert(state.top != Computer.State.Stopping) // Only set while executor is running.
super.save(nbt)
// Make sure the component list is up-to-date.
processAddedComponents()
val computerNbt = new NBTTagCompound()
val stateNbt = new NBTTagList()
for (state <- state) {
stateNbt.appendTag(new NBTTagInt(null, state.id))
}
computerNbt.setTag("state", stateNbt)
val usersNbt = new NBTTagList()
for (user <- users) {
usersNbt.appendTag(new NBTTagString(null, user))
}
computerNbt.setTag("users", usersNbt)
nbt.setNewTagList("state", state.map(_.id))
nbt.setNewTagList("users", users)
if (state.top != Computer.State.Stopped) {
// Unlimit memory while persisting.
@ -495,12 +465,12 @@ class Computer(val owner: tileentity.Computer) extends Environment with Context
// Try persisting Lua, because that's what all of the rest depends on.
// Save the kernel state (which is always at stack index one).
assert(lua.isThread(1))
computerNbt.setByteArray("kernel", persist(1))
nbt.setByteArray("kernel", persist(1))
// While in a driver call we have one object on the global stack: either
// the function to call the driver with, or the result of the call.
if (state.contains(Computer.State.SynchronizedCall) || state.contains(Computer.State.SynchronizedReturn)) {
assert(if (state.contains(Computer.State.SynchronizedCall)) lua.isFunction(2) else lua.isTable(2))
computerNbt.setByteArray("stack", persist(2))
nbt.setByteArray("stack", persist(2))
}
val componentsNbt = new NBTTagList()
@ -510,56 +480,43 @@ class Computer(val owner: tileentity.Computer) extends Environment with Context
componentNbt.setString("name", name)
componentsNbt.appendTag(componentNbt)
}
computerNbt.setTag("components", componentsNbt)
nbt.setTag("components", componentsNbt)
val signalsNbt = new NBTTagList()
for (s <- signals.iterator) {
val signalNbt = new NBTTagCompound()
signalNbt.setString("name", s.name)
val args = new NBTTagCompound()
args.setInteger("length", s.args.length)
s.args.zipWithIndex.foreach {
case (Unit, i) => args.setByte("arg" + i, -1)
case (arg: Boolean, i) => args.setByte("arg" + i, if (arg) 1 else 0)
case (arg: Double, i) => args.setDouble("arg" + i, arg)
case (arg: String, i) => args.setString("arg" + i, arg)
case (arg: Array[Byte], i) => args.setByteArray("arg" + i, arg)
}
signalNbt.setCompoundTag("args", args)
signalNbt.setNewCompoundTag("args", args => {
args.setInteger("length", s.args.length)
s.args.zipWithIndex.foreach {
case (Unit, i) => args.setByte("arg" + i, -1)
case (arg: Boolean, i) => args.setByte("arg" + i, if (arg) 1 else 0)
case (arg: Double, i) => args.setDouble("arg" + i, arg)
case (arg: String, i) => args.setString("arg" + i, arg)
case (arg: Array[Byte], i) => args.setByteArray("arg" + i, arg)
}
})
signalsNbt.appendTag(signalNbt)
}
computerNbt.setTag("signals", signalsNbt)
nbt.setTag("signals", signalsNbt)
val romNbt = new NBTTagCompound()
rom.foreach(rom => {
rom.save(romNbt)
rom.node.save(romNbt)
})
computerNbt.setCompoundTag("rom", romNbt)
rom.foreach(rom => nbt.setNewCompoundTag("rom", rom.save))
tmp.foreach(tmp => nbt.setNewCompoundTag("tmp", tmp.save))
val tmpNbt = new NBTTagCompound()
tmp.foreach(tmp => {
tmp.save(tmpNbt)
tmp.node.save(tmpNbt)
})
computerNbt.setCompoundTag("tmp", tmpNbt)
computerNbt.setInteger("kernelMemory", kernelMemory)
computerNbt.setLong("timeStarted", timeStarted)
computerNbt.setLong("cpuTime", cpuTime)
message.foreach(computerNbt.setString("message", _))
nbt.setInteger("kernelMemory", kernelMemory)
nbt.setLong("timeStarted", timeStarted)
nbt.setLong("cpuTime", cpuTime)
message.foreach(nbt.setString("message", _))
} catch {
case e: LuaRuntimeException => {
OpenComputers.log.warning("Could not persist computer.\n" + e.toString + "\tat " + e.getLuaStackTrace.mkString("\n\tat "))
computerNbt.setInteger("state", Computer.State.Stopped.id)
nbt.removeTag("state")
}
}
// Limit memory again.
recomputeMemory()
}
nbt.setCompoundTag(Config.namespace + "computer", computerNbt)
}
private def persist(index: Int): Array[Byte] = {
@ -1086,7 +1043,7 @@ class Computer(val owner: tileentity.Computer) extends Environment with Context
}
private def close() = state.synchronized(
if (state.top != Computer.State.Stopped) {
if (state.size == 0 || state.top != Computer.State.Stopped) {
state.clear()
state.push(Computer.State.Stopped)
lua.setTotalMemory(Integer.MAX_VALUE)

View File

@ -3,6 +3,7 @@ package li.cil.oc.server.component
import java.io.{FileNotFoundException, IOException}
import li.cil.oc.api.fs.{Label, Mode}
import li.cil.oc.api.network._
import li.cil.oc.util.ExtendedNBT._
import li.cil.oc.{Config, api}
import net.minecraft.nbt.{NBTTagInt, NBTTagList, NBTTagCompound}
import scala.Some
@ -228,6 +229,7 @@ class FileSystem(val fileSystem: api.fs.FileSystem, var label: Label) extends Ma
override def load(nbt: NBTTagCompound) {
super.load(nbt)
val ownersNbt = nbt.getTagList("owners")
(0 until ownersNbt.tagCount).map(ownersNbt.tagAt).map(_.asInstanceOf[NBTTagCompound]).foreach(ownerNbt => {
val address = ownerNbt.getString("address")
@ -245,6 +247,7 @@ class FileSystem(val fileSystem: api.fs.FileSystem, var label: Label) extends Ma
override def save(nbt: NBTTagCompound) {
super.save(nbt)
val ownersNbt = new NBTTagList()
for ((address, handles) <- owners) {
val ownerNbt = new NBTTagCompound()
@ -258,9 +261,7 @@ class FileSystem(val fileSystem: api.fs.FileSystem, var label: Label) extends Ma
}
nbt.setTag("owners", ownersNbt)
val fsNbt = new NBTTagCompound()
fileSystem.save(fsNbt)
nbt.setCompoundTag("fs", fsNbt)
nbt.setNewCompoundTag("fs", fileSystem.save)
}
// ----------------------------------------------------------------------- //

View File

@ -207,16 +207,18 @@ abstract class GraphicsCard extends ManagedComponent {
override def load(nbt: NBTTagCompound) {
super.load(nbt)
if (nbt.hasKey(Config.namespace + "gpu.screen")) {
screenAddress = Some(nbt.getString(Config.namespace + "gpu.screen"))
if (nbt.hasKey("screen")) {
screenAddress = Some(nbt.getString("screen"))
screenInstance = None
}
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
if (screenAddress.isDefined) {
nbt.setString(Config.namespace + "gpu.screen", screenAddress.get)
nbt.setString("screen", screenAddress.get)
}
}
}

View File

@ -1,7 +1,6 @@
package li.cil.oc.server.component
import cpw.mods.fml.common.IPlayerTracker
import li.cil.oc.api
import li.cil.oc.api.Network
import li.cil.oc.api.network.{Node, Visibility, Message}
import li.cil.oc.common.tileentity.Environment
@ -13,7 +12,7 @@ import scala.collection.mutable
// TODO key up when screen is disconnected from which the key down came
// TODO key up after load for anything that was pressed
class Keyboard(owner: Environment) extends api.network.Environment {
class Keyboard(owner: Environment) extends ManagedComponent {
val node = Network.newNode(this, Visibility.Network).
withComponent("keyboard").
create()
@ -34,19 +33,19 @@ class Keyboard(owner: Environment) extends api.network.Environment {
// ----------------------------------------------------------------------- //
def onConnect(node: Node) {
override def onConnect(node: Node) {
if (node == this.node) {
MinecraftForge.EVENT_BUS.register(this)
}
}
def onDisconnect(node: Node) {
override def onDisconnect(node: Node) {
if (node == this.node) {
MinecraftForge.EVENT_BUS.unregister(this)
}
}
def onMessage(message: Message) = {
override def onMessage(message: Message) = {
message.data match {
case Array(p: EntityPlayer, char: Character, code: Integer) if message.name == "keyboard.keyDown" =>
if (isUseableByPlayer(p)) {

View File

@ -1,6 +1,7 @@
package li.cil.oc.server.component
import li.cil.oc.api.network.{ManagedEnvironment, Node, Message}
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.nbt.NBTTagCompound
import scala.math.ScalaNumber
@ -14,11 +15,11 @@ abstract class ManagedComponent extends ManagedEnvironment {
def onConnect(node: Node) {}
def load(nbt: NBTTagCompound) = {
if (node != null) node.load(nbt)
if (node != null) node.load(nbt.getCompoundTag("node"))
}
def save(nbt: NBTTagCompound) = {
if (node != null) node.save(nbt)
if (node != null) nbt.setNewCompoundTag("node", node.save)
}
/**

View File

@ -1,8 +1,9 @@
package li.cil.oc.server.component
import li.cil.oc.api
import li.cil.oc.api.network._
import li.cil.oc.{Config, api}
import net.minecraft.nbt.{NBTTagInt, NBTTagList, NBTTagCompound}
import li.cil.oc.util.ExtendedNBT._
import net.minecraft.nbt.{NBTTagInt, NBTTagCompound}
import scala.collection.convert.WrapAsScala._
import scala.collection.mutable
@ -81,19 +82,15 @@ class NetworkCard extends ManagedComponent {
override def load(nbt: NBTTagCompound) {
super.load(nbt)
val openPortsNbt = nbt.getTagList(Config.namespace + "modem.openPorts")
(0 until openPortsNbt.tagCount).
map(openPortsNbt.tagAt).
map(_.asInstanceOf[NBTTagInt]).
foreach(portNbt => openPorts.add(portNbt.data))
assert(openPorts.isEmpty)
openPorts ++ nbt.getTagList("openPorts").iterator[NBTTagInt].map(_.data)
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
val openPortsNbt = new NBTTagList()
for (port <- openPorts)
openPortsNbt.appendTag(new NBTTagInt(null, port))
nbt.setTag(Config.namespace + "modem.openPorts", openPortsNbt)
nbt.setNewTagList("openPorts", openPorts)
}
// ----------------------------------------------------------------------- //

View File

@ -0,0 +1,170 @@
package li.cil.oc.server.component
import li.cil.oc.api
import li.cil.oc.api.network._
import li.cil.oc.common.tileentity.PowerInformation
import li.cil.oc.server.network.Connector
import li.cil.oc.server.{PacketSender => ServerPacketSender}
import scala.collection.convert.WrapAsScala._
import scala.collection.mutable
class PowerDistributor(val owner: PowerInformation) extends ManagedComponent {
val node = api.Network.newNode(this, Visibility.Network).
withComponent("power", Visibility.Network).
create()
var globalBuffer = 0.0
var globalBufferSize = 0.0
private var lastSentState = 0.0
private val buffers = mutable.Set.empty[Connector]
private val distributors = mutable.Set.empty[PowerDistributor]
private var dirty = true
// ----------------------------------------------------------------------- //
@LuaCallback(value = "buffer", direct = true)
def buffer(context: Context, args: Arguments): Array[AnyRef] = result(globalBuffer)
@LuaCallback(value = "bufferSize", direct = true)
def bufferSize(context: Context, args: Arguments): Array[AnyRef] = result(globalBufferSize)
// ----------------------------------------------------------------------- //
def changeBuffer(delta: Double): Boolean = {
if (delta != 0) this.synchronized {
val oldBuffer = globalBuffer
globalBuffer = (globalBuffer + delta) max 0 min globalBufferSize
if (globalBuffer != oldBuffer) {
dirty = true
if (delta < 0) {
var remaining = -delta
for (connector <- buffers) {
connector.synchronized(if (connector.localBuffer > 0) {
connector.dirty = true
if (connector.localBuffer < remaining) {
remaining -= connector.localBuffer
connector.localBuffer = 0
}
else {
connector.localBuffer -= remaining
return true
}
})
}
}
else if (delta > 0) {
var remaining = delta
for (connector <- buffers) {
connector.synchronized(if (connector.localBuffer < connector.localBufferSize) {
connector.dirty = true
val space = connector.localBufferSize - connector.localBuffer
if (space < remaining) {
remaining -= space
connector.localBuffer = connector.localBufferSize
}
else {
connector.localBuffer += remaining
return true
}
})
}
}
}
}
false
}
// ----------------------------------------------------------------------- //
override def update() {
if (node != null && (dirty || buffers.exists(_.dirty))) {
updateCachedValues()
}
}
// ----------------------------------------------------------------------- //
override def onConnect(node: Node) {
super.onConnect(node)
if (node == this.node) {
for (node <- node.reachableNodes) node match {
case connector: Connector if connector.localBufferSize > 0 => this.synchronized {
buffers += connector
globalBuffer += connector.localBuffer
globalBufferSize += connector.localBufferSize
}
case _ => node.host match {
case distributor: PowerDistributor if distributor.node.canBeSeenFrom(this.node) =>
distributors += distributor
case _ =>
}
}
distributors += this
dirty = true
}
else node match {
case connector: Connector if connector.localBufferSize > 0 => this.synchronized {
buffers += connector
globalBuffer += connector.localBuffer
globalBufferSize += connector.localBufferSize
dirty = true
}
case _ => node.host match {
case distributor: PowerDistributor if distributor.node.canBeSeenFrom(this.node) =>
distributors += distributor
case _ =>
}
}
}
override def onDisconnect(node: Node) {
super.onDisconnect(node)
if (node == this.node) this.synchronized {
buffers.clear()
distributors.clear()
globalBuffer = 0
globalBufferSize = 0
}
else node match {
case connector: Connector => this.synchronized {
buffers -= connector
globalBuffer -= connector.localBuffer
globalBufferSize -= connector.localBufferSize
dirty = true
}
case _ => node.host match {
case distributor: PowerDistributor => distributors -= distributor
case _ =>
}
}
}
// ----------------------------------------------------------------------- //
def updateCachedValues() {
// Computer average fill ratio of all buffers.
val (sumBuffer, sumBufferSize) =
buffers.foldRight((0.0, 0.0))((c, acc) => {
c.dirty = false // clear dirty flag for all connectors
(acc._1 + c.localBuffer, acc._2 + c.localBufferSize)
})
val globalPower = if (globalBufferSize > 0) globalBuffer / globalBufferSize else 0
val shouldSend = (lastSentState - globalPower).abs > 0.05
for (distributor <- distributors) distributor.synchronized {
distributor.dirty = false
distributor.globalBuffer = sumBuffer
distributor.globalBufferSize = sumBufferSize
distributor.owner.globalPower = globalPower
if (shouldSend) {
distributor.lastSentState = lastSentState
ServerPacketSender.sendPowerState(owner)
}
}
}
}

View File

@ -1,11 +1,10 @@
package li.cil.oc.server.component
import li.cil.oc.api.network.{Context, Arguments, LuaCallback, Visibility}
import li.cil.oc.api.network.Visibility
import li.cil.oc.{Config, api}
class PowerSupply extends ManagedComponent {
val node = api.Network.newNode(this, Visibility.Network).
withComponent("psu").
withConnector(Config.bufferPowerSupply).
create()
@ -13,10 +12,4 @@ class PowerSupply extends ManagedComponent {
super.update()
node.changeBuffer(-Config.powerSupplyCost)
}
@LuaCallback(value = "localBufferSize", direct = true)
def bufferSize(context: Context, args: Arguments): Array[AnyRef] = result(node.localBufferSize)
@LuaCallback(value = "localBuffer", direct = true)
def buffer(context: Context, args: Arguments): Array[AnyRef] = result(node.localBuffer)
}

View File

@ -86,13 +86,13 @@ class WirelessNetworkCard(val owner: TileEntity) extends NetworkCard {
override def load(nbt: NBTTagCompound) {
super.load(nbt)
if (nbt.hasKey(Config.namespace + "modem.strength")) {
strength = nbt.getDouble(Config.namespace + "modem.strength")
if (nbt.hasKey("modem")) {
strength = nbt.getDouble("strength")
}
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
nbt.setDouble(Config.namespace + "modem.strength", strength)
nbt.setDouble("strength", strength)
}
}

View File

@ -3,7 +3,7 @@ package li.cil.oc.server.network
import li.cil.oc.Config
import li.cil.oc.api.network
import li.cil.oc.api.network.{Node => ImmutableNode}
import li.cil.oc.common.tileentity.PowerDistributor
import li.cil.oc.server.component.PowerDistributor
import li.cil.oc.util.Persistable
import net.minecraft.nbt.NBTTagCompound
import scala.collection.convert.WrapAsScala._
@ -51,14 +51,15 @@ trait Connector extends Node with network.Connector with Persistable {
override def onConnect(node: ImmutableNode) {
if (node == this) findDistributor()
else if (distributor.isEmpty) node.host match {
case distributor: PowerDistributor => this.distributor = Some(distributor)
case distributor: PowerDistributor =>
this.distributor = Some(distributor)
case _ =>
}
super.onConnect(node)
}
override def onDisconnect(node: ImmutableNode) {
if (node != this && distributor.exists(_ == node.host)) findDistributor()
if (node != this && distributor.exists(_ == node)) findDistributor()
super.onDisconnect(node)
}
@ -70,12 +71,12 @@ trait Connector extends Node with network.Connector with Persistable {
override def load(nbt: NBTTagCompound) {
super.load(nbt)
localBuffer = nbt.getDouble(Config.namespace + "connector.buffer") max 0 min localBufferSize
localBuffer = nbt.getDouble("buffer") max 0 min localBufferSize
dirty = true
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
nbt.setDouble(Config.namespace + "connector.buffer", localBuffer)
nbt.setDouble("buffer", localBuffer)
}
}

View File

@ -259,6 +259,8 @@ object Network extends api.detail.NetworkAPI {
case _ => // Invalid block.
}
def create(node: ImmutableNode): Unit = new Network(node.asInstanceOf[MutableNode])
private def getNetworkNode(world: IBlockAccess, x: Int, y: Int, z: Int) =
Option(Block.blocksList(world.getBlockId(x, y, z))) match {
case Some(block) if block.hasTileEntity(world.getBlockMetadata(x, y, z)) =>

View File

@ -1,8 +1,8 @@
package li.cil.oc.server.network
import li.cil.oc.api
import li.cil.oc.api.network.{Environment, Visibility, Node => ImmutableNode}
import li.cil.oc.util.Persistable
import li.cil.oc.{Config, api}
import net.minecraft.nbt.NBTTagCompound
import scala.collection.convert.WrapAsJava._
import scala.collection.convert.WrapAsScala._
@ -64,15 +64,15 @@ trait Node extends api.network.Node with Persistable {
override def load(nbt: NBTTagCompound) = {
super.load(nbt)
if (nbt.hasKey(Config.namespace + "node.address")) {
address = nbt.getString(Config.namespace + "node.address")
if (nbt.hasKey("address")) {
address = nbt.getString("address")
}
}
override def save(nbt: NBTTagCompound) = {
super.save(nbt)
if (address != null) {
nbt.setString(Config.namespace + "node.address", address)
nbt.setString("address", address)
}
}
}

View File

@ -7,7 +7,7 @@ object ExtendedLuaState {
implicit def extendLuaState(state: LuaState) = new ExtendedLuaState(state)
class ExtendedLuaState(state: LuaState) {
class ExtendedLuaState(val state: LuaState) {
def pushScalaFunction(f: (LuaState) => Int) = state.pushJavaFunction(new JavaFunction {
override def invoke(state: LuaState) = f(state)
})

View File

@ -0,0 +1,84 @@
package li.cil.oc.util
import net.minecraft.nbt._
import scala.language.implicitConversions
object ExtendedNBT {
implicit def toNbt(value: Byte) = new NBTTagByte(null, value)
implicit def toNbt(value: Short) = new NBTTagShort(null, value)
implicit def toNbt(value: Int) = new NBTTagInt(null, value)
implicit def toNbt(value: Long) = new NBTTagLong(null, value)
implicit def toNbt(value: Float) = new NBTTagFloat(null, value)
implicit def toNbt(value: Double) = new NBTTagDouble(null, value)
implicit def toNbt(value: Array[Byte]) = new NBTTagByteArray(null, value)
implicit def toNbt(value: String) = new NBTTagString(null, value)
implicit def byteIterableToNbt(value: Iterable[Byte]) = value.map(toNbt)
implicit def shortIterableToNbt(value: Iterable[Short]) = value.map(toNbt)
implicit def intIterableToNbt(value: Iterable[Int]) = value.map(toNbt)
implicit def longIterableToNbt(value: Iterable[Long]) = value.map(toNbt)
implicit def floatIterableToNbt(value: Iterable[Float]) = value.map(toNbt)
implicit def doubleIterableToNbt(value: Iterable[Double]) = value.map(toNbt)
implicit def byteArrayIterableToNbt(value: Iterable[Array[Byte]]) = value.map(toNbt)
implicit def stringIterableToNbt(value: Iterable[String]) = value.map(toNbt)
implicit def extendNBTTagCompound(nbt: NBTTagCompound) = new ExtendedNBTTagCompound(nbt)
implicit def extendNBTTagList(nbt: NBTTagList) = new ExtendedNBTTagList(nbt)
class ExtendedNBTTagCompound(val nbt: NBTTagCompound) {
def setNewCompoundTag(name: String, f: (NBTTagCompound) => Any) = {
val t = new NBTTagCompound()
f(t)
nbt.setCompoundTag(name, t)
nbt
}
def setNewTagList(name: String, values: Iterable[NBTBase]) = {
val t = new NBTTagList()
t.append(values)
nbt.setTag(name, t)
nbt
}
def setNewTagList(name: String, values: NBTBase*): NBTTagCompound = setNewTagList(name, values)
}
class ExtendedNBTTagList(val nbt: NBTTagList) {
def appendNewCompoundTag(f: (NBTTagCompound) => Unit) {
val t = new NBTTagCompound()
f(t)
nbt.appendTag(t)
}
def append(values: Iterable[NBTBase]) {
for (value <- values) {
nbt.appendTag(value)
}
}
def append(values: NBTBase*): Unit = append(values)
def iterator[Tag <: NBTBase] = (0 until nbt.tagCount).map(nbt.tagAt).map(_.asInstanceOf[Tag])
def foreach[Tag <: NBTBase](f: (Tag) => Unit) = iterator[Tag].foreach(f)
def map[Tag <: NBTBase, Value](f: (Tag) => Value) = iterator[Tag].map(f)
}
}

View File

@ -39,6 +39,20 @@ object RenderState {
}
}
def enableLighting() {
GL11.glEnable(GL11.GL_LIGHTING)
if (arb) {
ARBMultitexture.glActiveTextureARB(OpenGlHelper.lightmapTexUnit)
GL11.glEnable(GL11.GL_TEXTURE_2D)
ARBMultitexture.glActiveTextureARB(OpenGlHelper.defaultTexUnit)
}
else {
GL13.glActiveTexture(OpenGlHelper.lightmapTexUnit)
GL11.glEnable(GL11.GL_TEXTURE_2D)
GL13.glActiveTexture(OpenGlHelper.defaultTexUnit)
}
}
def makeItBlend() {
GL11.glEnable(GL11.GL_BLEND)
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)