diff --git a/src/main/scala/li/cil/oc/common/Proxy.scala b/src/main/scala/li/cil/oc/common/Proxy.scala index d81679730..064d5d04d 100644 --- a/src/main/scala/li/cil/oc/common/Proxy.scala +++ b/src/main/scala/li/cil/oc/common/Proxy.scala @@ -85,6 +85,7 @@ class Proxy { api.Driver.add(driver.item.WirelessNetworkCard) if (Mods.StargateTech2.isAvailable) { + api.Driver.add(driver.converter.BusPacketNetScanDevice) api.Driver.add(driver.item.AbstractBusCard) } if (Mods.ComputerCraft15.isAvailable) { diff --git a/src/main/scala/li/cil/oc/server/component/AbstractBus.scala b/src/main/scala/li/cil/oc/server/component/AbstractBus.scala index dc0cbd191..fb66846b3 100644 --- a/src/main/scala/li/cil/oc/server/component/AbstractBus.scala +++ b/src/main/scala/li/cil/oc/server/component/AbstractBus.scala @@ -21,7 +21,7 @@ class AbstractBus(val device: IBusDevice) extends component.ManagedComponent wit protected var address = 0 - protected var sendQueue: Option[QueuedPacket] = None + protected var sendQueue: Option[BusPacket[_]] = None protected var owner: Option[Context] = None @@ -40,18 +40,11 @@ class AbstractBus(val device: IBusDevice) extends component.ManagedComponent wit owner.foreach(_.signal("bus_message", Int.box(packet.getProtocolID), Int.box(packet.getSender), Int.box(packet.getTarget), data, metadata)) } - override def getNextPacketToSend = if (sendQueue.isDefined) { - val info = sendQueue.get + override def getNextPacketToSend = this.synchronized { + val packet = sendQueue.orNull sendQueue = None - val packet = new BusPacketLIP(info.sender, info.target) - for ((key, value) <- info.data) { - packet.set(key, value) - } - packet.setMetadata(new BusPacketLIP.LIPMetadata("OpenComputers", node.address, null)) - packet.finish() packet } - else null override def isInterfaceEnabled = isEnabled @@ -78,17 +71,46 @@ class AbstractBus(val device: IBusDevice) extends component.ManagedComponent wit } @Callback(doc = """function(address:number, data:table):boolean -- Sends data across the abstract bus.""") - def send(context: Context, args: Arguments): Array[AnyRef] = { + 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)) { - sendQueue = Some(new QueuedPacket(address.toShort, target.toShort, Map(data.toSeq.map(entry => (entry._1.toString, entry._2.toString)): _*))) + 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) @@ -124,17 +146,4 @@ class AbstractBus(val device: IBusDevice) extends component.ManagedComponent wit nbt.setBoolean("enabled", isEnabled) nbt.setInteger("address", address) } - - protected class QueuedPacket(val sender: Short, val target: Short, val data: Map[String, String]) { - // Extra braces because we don't want/have to keep size as a field. - { - val size = data.foldLeft(0)((acc, arg) => { - acc + arg._1.length + arg._2.length - }) - if (size > Settings.get.maxNetworkPacketSize) { - throw new IllegalArgumentException("packet too big (max " + Settings.get.maxNetworkPacketSize + ")") - } - } - } - } diff --git a/src/main/scala/li/cil/oc/server/driver/converter/BusPacketNetScanDevice.scala b/src/main/scala/li/cil/oc/server/driver/converter/BusPacketNetScanDevice.scala new file mode 100644 index 000000000..f64fb78ec --- /dev/null +++ b/src/main/scala/li/cil/oc/server/driver/converter/BusPacketNetScanDevice.scala @@ -0,0 +1,21 @@ +package li.cil.oc.server.driver.converter + +import java.util +import li.cil.oc.api +import scala.collection.convert.WrapAsScala._ +import stargatetech2.api.bus.BusPacketNetScan + +object BusPacketNetScanDevice extends api.driver.Converter { + override def convert(value: scala.Any, output: util.Map[AnyRef, AnyRef]) = + value match { + case device: BusPacketNetScan.Device => + output += "address" -> Short.box(device.address) + output += "name" -> device.name + output += "description" -> device.description + output += "enabled" -> Boolean.box(device.enabled) + output += "x" -> Int.box(device.x) + output += "y" -> Int.box(device.y) + output += "z" -> Int.box(device.z) + case _ => + } +}