mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-15 10:21:45 -04:00
Extended implementation of switch CC peripheral to properly "fake" connected modems (all the remote stuffs).
This means CC can now call methods on OC peripherals \o/
This commit is contained in:
parent
d3918d39dc
commit
19e39a2f13
@ -5,13 +5,90 @@ import dan200.computercraft.api.peripheral.IComputerAccess
|
||||
import dan200.computercraft.api.peripheral.IPeripheral
|
||||
import li.cil.oc.Settings
|
||||
import li.cil.oc.api
|
||||
import li.cil.oc.api.machine.Context
|
||||
import li.cil.oc.api.network.Component
|
||||
import li.cil.oc.common.tileentity.AccessPoint
|
||||
import li.cil.oc.common.tileentity.Switch
|
||||
import li.cil.oc.util.ResultWrapper._
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
import scala.collection.convert.WrapAsJava._
|
||||
import scala.collection.convert.WrapAsScala._
|
||||
import scala.collection.mutable
|
||||
|
||||
class SwitchPeripheral(val switch: Switch) extends IPeripheral {
|
||||
private val methods = Map[String, (IComputerAccess, ILuaContext, Array[AnyRef]) => Array[AnyRef]](
|
||||
// Generic modem methods.
|
||||
"open" -> ((computer, context, arguments) => {
|
||||
val port = checkPort(arguments, 0)
|
||||
if (switch.openPorts(computer).size >= 128)
|
||||
throw new IllegalArgumentException("too many open channels")
|
||||
result(switch.openPorts(computer).add(port))
|
||||
}),
|
||||
"isOpen" -> ((computer, context, arguments) => {
|
||||
val port = checkPort(arguments, 0)
|
||||
result(switch.openPorts(computer).contains(port))
|
||||
}),
|
||||
"close" -> ((computer, context, arguments) => {
|
||||
val port = checkPort(arguments, 0)
|
||||
result(switch.openPorts(computer).remove(port))
|
||||
}),
|
||||
"closeAll" -> ((computer, context, arguments) => {
|
||||
switch.openPorts(computer).clear()
|
||||
null
|
||||
}),
|
||||
"transmit" -> ((computer, context, arguments) => {
|
||||
val sendPort = checkPort(arguments, 0)
|
||||
val answerPort = checkPort(arguments, 1)
|
||||
val data = Seq(Int.box(answerPort)) ++ arguments.drop(2)
|
||||
val packet = api.Network.newPacket(s"cc${computer.getID}_${computer.getAttachmentName}", null, sendPort, data.toArray)
|
||||
result(switch.tryEnqueuePacket(None, packet))
|
||||
}),
|
||||
"isWireless" -> ((computer, context, arguments) => {
|
||||
result(switch.isInstanceOf[AccessPoint])
|
||||
}),
|
||||
|
||||
// Undocumented modem messages.
|
||||
"callRemote" -> ((computer, context, arguments) => {
|
||||
val address = checkString(arguments, 0)
|
||||
visibleComponents.find(_.address == address) match {
|
||||
case Some(component) =>
|
||||
val method = checkString(arguments, 1)
|
||||
val fakeContext = new CCContext(computer, context)
|
||||
component.invoke(method, fakeContext, arguments.drop(2): _*)
|
||||
case _ => null
|
||||
}
|
||||
}),
|
||||
"getMethodsRemote" -> ((computer, context, arguments) => {
|
||||
val address = checkString(arguments, 0)
|
||||
visibleComponents.find(_.address == address) match {
|
||||
case Some(component) => result(mapAsJavaMap(component.methods.zipWithIndex.map(t => (t._2 + 1, t._1)).toMap))
|
||||
case _ => null
|
||||
}
|
||||
}),
|
||||
"getNamesRemote" -> ((computer, context, arguments) => {
|
||||
result(mapAsJavaMap(visibleComponents.map(_.address).zipWithIndex.map(t => (t._2 + 1, t._1)).toMap))
|
||||
}),
|
||||
"getTypeRemote" -> ((computer, context, arguments) => {
|
||||
val address = checkString(arguments, 0)
|
||||
visibleComponents.find(_.address == address) match {
|
||||
case Some(component) => result(component.name)
|
||||
case _ => null
|
||||
}
|
||||
}),
|
||||
"isPresentRemote" -> ((computer, context, arguments) => {
|
||||
val address = checkString(arguments, 0)
|
||||
result(visibleComponents.exists(_.address == address))
|
||||
}),
|
||||
|
||||
// OC specific.
|
||||
"maxPacketSize" -> ((computer, context, arguments) => {
|
||||
result(Settings.get.maxNetworkPacketSize)
|
||||
})
|
||||
)
|
||||
|
||||
private val methodNames = methods.keys.toArray.sorted
|
||||
|
||||
override def getType = "modem"
|
||||
|
||||
override def attach(computer: IComputerAccess) {
|
||||
@ -24,34 +101,9 @@ class SwitchPeripheral(val switch: Switch) extends IPeripheral {
|
||||
switch.openPorts -= computer
|
||||
}
|
||||
|
||||
override def getMethodNames = Array("open", "isOpen", "close", "closeAll", "maxPacketSize", "transmit", "isWireless")
|
||||
override def getMethodNames = methodNames
|
||||
|
||||
override def callMethod(computer: IComputerAccess, context: ILuaContext, method: Int, arguments: Array[AnyRef]) = getMethodNames()(method) match {
|
||||
case "open" =>
|
||||
val port = checkPort(arguments, 0)
|
||||
if (switch.openPorts(computer).size >= 128)
|
||||
throw new IllegalArgumentException("too many open channels")
|
||||
result(switch.openPorts(computer).add(port))
|
||||
case "isOpen" =>
|
||||
val port = checkPort(arguments, 0)
|
||||
result(switch.openPorts(computer).contains(port))
|
||||
case "close" =>
|
||||
val port = checkPort(arguments, 0)
|
||||
result(switch.openPorts(computer).remove(port))
|
||||
case "closeAll" =>
|
||||
switch.openPorts(computer).clear()
|
||||
null
|
||||
case "maxPacketSize" =>
|
||||
result(Settings.get.maxNetworkPacketSize)
|
||||
case "transmit" =>
|
||||
val sendPort = checkPort(arguments, 0)
|
||||
val answerPort = checkPort(arguments, 1)
|
||||
val data = Seq(Int.box(answerPort)) ++ arguments.drop(2)
|
||||
val packet = api.Network.newPacket(s"cc${computer.getID}_${computer.getAttachmentName}", null, sendPort, data.toArray)
|
||||
result(switch.tryEnqueuePacket(None, packet))
|
||||
case "isWireless" => result(switch.isInstanceOf[AccessPoint])
|
||||
case _ => null
|
||||
}
|
||||
override def callMethod(computer: IComputerAccess, context: ILuaContext, method: Int, arguments: Array[AnyRef]) = methods(methodNames(method))(computer, context, arguments)
|
||||
|
||||
override def equals(other: IPeripheral) = other match {
|
||||
case peripheral: SwitchPeripheral => peripheral.switch == switch
|
||||
@ -66,4 +118,41 @@ class SwitchPeripheral(val switch: Switch) extends IPeripheral {
|
||||
throw new IllegalArgumentException(s"bad argument #${index + 1} (number in [1, 65535] expected)")
|
||||
port
|
||||
}
|
||||
|
||||
private def checkString(args: Array[AnyRef], index: Int) = {
|
||||
if (args.length < index - 1 || !args(index).isInstanceOf[String])
|
||||
throw new IllegalArgumentException(s"bad argument #${index + 1} (string expected)")
|
||||
args(index).asInstanceOf[String]
|
||||
}
|
||||
|
||||
private def visibleComponents = {
|
||||
ForgeDirection.VALID_DIRECTIONS.flatMap(side => {
|
||||
val node = switch.sidedNode(side)
|
||||
node.reachableNodes.collect {
|
||||
case component: Component if component.canBeSeenFrom(node) => component
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
class CCContext(val computer: IComputerAccess, val context: ILuaContext) extends Context {
|
||||
override def node() = switch.node
|
||||
|
||||
override def isPaused = false
|
||||
|
||||
override def stop() = false
|
||||
|
||||
override def canInteract(player: String) = true
|
||||
|
||||
override def signal(name: String, args: AnyRef*) = {
|
||||
computer.queueEvent(name, args.toArray)
|
||||
true
|
||||
}
|
||||
|
||||
override def pause(seconds: Double) = false
|
||||
|
||||
override def isRunning = true
|
||||
|
||||
override def start() = false
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user