blob: fb66846b3627ec8c6337c3f4a38549abb5563430 [file] [log] [blame] [raw]
package li.cil.oc.server.component
import li.cil.oc.Settings
import li.cil.oc.api.Network
import li.cil.oc.api.network._
import li.cil.oc.common.component
import net.minecraft.nbt.NBTTagCompound
import scala.collection.convert.WrapAsScala._
import stargatetech2.api.StargateTechAPI
import stargatetech2.api.bus._
class AbstractBus(val device: IBusDevice) extends component.ManagedComponent with IBusDriver {
val node = Network.newNode(this, Visibility.Neighbors).
withComponent("abstract_bus").
withConnector().
create()
val busInterface: IBusInterface = StargateTechAPI.api.getFactory.getIBusInterface(device, this)
protected var isEnabled = true
protected var address = 0
protected var sendQueue: Option[BusPacket[_]] = None
protected var owner: Option[Context] = None
// ----------------------------------------------------------------------- //
override def getShortName = "Computer"
override def getDescription = "An OpenComputers computer or server."
override def canHandlePacket(sender: Short, protocolID: Int, hasLIP: Boolean) = hasLIP
override def handlePacket(packet: BusPacket[_]) {
val lip = packet.getPlainText
val data = Map(lip.getEntryList.map(key => (key, lip.get(key))): _*)
val metadata = Map("mod" -> lip.getMetadata.modID, "device" -> lip.getMetadata.deviceName, "player" -> lip.getMetadata.playerName)
owner.foreach(_.signal("bus_message", Int.box(packet.getProtocolID), Int.box(packet.getSender), Int.box(packet.getTarget), data, metadata))
}
override def getNextPacketToSend = this.synchronized {
val packet = sendQueue.orNull
sendQueue = None
packet
}
override def isInterfaceEnabled = isEnabled
override def getInterfaceAddress = address.toShort
// ----------------------------------------------------------------------- //
@Callback(doc = """function():boolean -- Whether the local bus interface is enabled.""")
def getEnabled(context: Context, args: Arguments): Array[AnyRef] = result(isEnabled)
@Callback(doc = """function(enabled:boolean):boolean -- Sets whether the local bus interface should be enabled.""")
def setEnabled(context: Context, args: Arguments): Array[AnyRef] = {
isEnabled = args.checkBoolean(0)
result(isEnabled)
}
@Callback(doc = """function():number -- Get the local interface address.""")
def getAddress(context: Context, args: Arguments): Array[AnyRef] = result(address)
@Callback(doc = """function(address:number):number -- Sets the local interface address.""")
def setAddress(context: Context, args: Arguments): Array[AnyRef] = {
address = args.checkInteger(0) & 0xFFFF
result(address)
}
@Callback(doc = """function(address:number, data:table):boolean -- Sends data across the abstract bus.""")
def send(context: Context, args: Arguments): Array[AnyRef] = this.synchronized {
val target = args.checkInteger(0) & 0xFFFF
val data = args.checkTable(1)
if (node.tryChangeBuffer(-Settings.get.abstractBusPacketCost)) {
val packet = new BusPacketLIP(address.toShort, target.toShort)
var size = 0
def checkSize(add: Int) {
size += add
if (size > Settings.get.maxNetworkPacketSize) {
throw new IllegalArgumentException("packet too big (max " + Settings.get.maxNetworkPacketSize + ")")
}
}
for ((key, value) <- data) {
val keyAsString = key.toString
checkSize(keyAsString.length)
val valueAsString = value.toString
checkSize(valueAsString.length)
packet.set(keyAsString, valueAsString)
}
packet.setMetadata(new BusPacketLIP.LIPMetadata("OpenComputers", node.address, null))
packet.finish()
sendQueue = Some(packet)
busInterface.sendAllPackets()
result(true)
}
else result(Unit, "not enough energy")
}
@Callback(doc = """function(mask:number):table -- Scans the network for other devices.""")
def scan(context: Context, args: Arguments): Array[AnyRef] = this.synchronized {
val mask = (args.checkInteger(0) & 0xFFFF).toShort
if (node.tryChangeBuffer(-Settings.get.abstractBusPacketCost)) {
val packet = new BusPacketNetScan(mask)
sendQueue = Some(packet)
busInterface.sendAllPackets()
Array(packet.getDevices.toArray)
}
else Array(Unit, "not enough energy")
}
@Callback(direct = true, doc = """function():number -- The maximum packet size that can be sent over the bus.""")
def maxPacketSize(context: Context, args: Arguments): Array[AnyRef] = result(Settings.get.maxNetworkPacketSize)
// ----------------------------------------------------------------------- //
override def onConnect(node: Node) {
super.onConnect(node)
if (owner.isEmpty && node.host.isInstanceOf[Context]) {
owner = Some(node.host.asInstanceOf[Context])
}
}
override def onDisconnect(node: Node) {
super.onDisconnect(node)
if (owner.isDefined && node.host.isInstanceOf[Context] && (node.host.asInstanceOf[Context] == owner.get)) {
owner = None
}
}
override def load(nbt: NBTTagCompound) {
super.load(nbt)
busInterface.readFromNBT(nbt, "bus")
// Don't default to false.
if (nbt.hasKey("enabled")) {
isEnabled = nbt.getBoolean("enabled")
}
address = nbt.getInteger("address") & 0xFFFF
}
override def save(nbt: NBTTagCompound) {
super.save(nbt)
busInterface.writeToNBT(nbt, "bus")
nbt.setBoolean("enabled", isEnabled)
nbt.setInteger("address", address)
}
}