From fcdb75e4bcc2577d255d93f25900935ac41d3b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Mon, 4 Nov 2013 17:49:42 +0100 Subject: [PATCH] rudimentary driver for computercraft peripherals: it emulates a computer that is the whole network and does not provide a lua context which may cause nullpointers. good enough to allow accessing cc disk drives and read/write floppies in them. --- li/cil/oc/common/Proxy.scala | 1 + li/cil/oc/server/component/Filesystem.scala | 4 +- li/cil/oc/server/component/Peripheral.scala | 86 +++++++++++++++++++ li/cil/oc/server/driver/Peripheral.scala | 20 +++++ .../server/fs/ComputerCraftFileSystem.scala | 2 +- 5 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 li/cil/oc/server/component/Peripheral.scala create mode 100644 li/cil/oc/server/driver/Peripheral.scala diff --git a/li/cil/oc/common/Proxy.scala b/li/cil/oc/common/Proxy.scala index 9c188a2df..8d27a8e9f 100644 --- a/li/cil/oc/common/Proxy.scala +++ b/li/cil/oc/common/Proxy.scala @@ -28,6 +28,7 @@ class Proxy { api.Driver.add(driver.RedstoneCard) api.Driver.add(driver.CommandBlock) api.Driver.add(driver.PowerSupply) + api.Driver.add(driver.Peripheral) MinecraftForge.EVENT_BUS.register(Computer) MinecraftForge.EVENT_BUS.register(network.Network) diff --git a/li/cil/oc/server/component/Filesystem.scala b/li/cil/oc/server/component/Filesystem.scala index 0cc72dd4a..dbc967987 100644 --- a/li/cil/oc/server/component/Filesystem.scala +++ b/li/cil/oc/server/component/Filesystem.scala @@ -10,8 +10,8 @@ import scala.Some import scala.collection.mutable class FileSystem(val fileSystem: api.fs.FileSystem, var label: String) extends ManagedComponent { - val node = api.Network.newNode(this, Visibility.Neighbors). - withComponent("filesystem"). + val node = api.Network.newNode(this, Visibility.Network). + withComponent("filesystem", Visibility.Neighbors). create() private val owners = mutable.Map.empty[String, mutable.Set[Int]] diff --git a/li/cil/oc/server/component/Peripheral.scala b/li/cil/oc/server/component/Peripheral.scala new file mode 100644 index 000000000..687f57f1f --- /dev/null +++ b/li/cil/oc/server/component/Peripheral.scala @@ -0,0 +1,86 @@ +package li.cil.oc.server.component + +import dan200.computer.api.{IMount, IWritableMount, IComputerAccess, IPeripheral} +import li.cil.oc.api +import li.cil.oc.api.network._ +import scala.collection.convert.WrapAsScala._ +import scala.collection.mutable + +class Peripheral(peripheral: IPeripheral) extends ManagedComponent with IComputerAccess { + val node = api.Network.newNode(this, Visibility.Network). + withComponent("peripheral"). + create() + + private val mounts = mutable.Map.empty[String, ManagedEnvironment] + + // ----------------------------------------------------------------------- // + + @LuaCallback(value = "getType", asynchronous = true) + def getType(context: Context, args: Arguments): Array[Object] = + result(peripheral.getType) + + @LuaCallback(value = "getMethodNames", asynchronous = true) + def getMethodNames(context: Context, args: Arguments): Array[Object] = + peripheral.getMethodNames.map(_.asInstanceOf[AnyRef]) + + @LuaCallback(value = "callMethod", asynchronous = true) + def callMethod(context: Context, args: Arguments): Array[Object] = { + val method = args.checkInteger(0) + peripheral.callMethod(this, null, method, args.drop(1).map { + case x: Array[Byte] => new String(x, "UTF-8") + case x => x + }.toArray) + } + + // ----------------------------------------------------------------------- // + + override def onConnect(node: Node) { + super.onConnect(node) + if (node == this.node) { + peripheral.attach(this) + } + } + + override def onDisconnect(node: Node) { + super.onDisconnect(node) + if (node == this.node) { + peripheral.detach(this) + for ((_, env) <- mounts) { + env.node.remove() + } + } + } + + // ----------------------------------------------------------------------- // + + def getID = -1 + + def getAttachmentName = node.address + + def queueEvent(event: String, arguments: Array[AnyRef]) { + node.sendToReachable("computer.signal", Seq(event) ++ arguments: _*) + } + + def mount(desiredLocation: String, mount: IMount) = + mountFileSystem(desiredLocation, api.FileSystem.fromComputerCraft(mount)) + + def mountWritable(desiredLocation: String, mount: IWritableMount) = + mountFileSystem(desiredLocation, api.FileSystem.fromComputerCraft(mount)) + + private def mountFileSystem(desiredLocation: String, fs: api.fs.FileSystem) = + if (!mounts.contains(desiredLocation)) { + val env = api.FileSystem.asManagedEnvironment(fs, desiredLocation) + env.node.asInstanceOf[Component].setVisibility(Visibility.Network) + node.connect(env.node) + mounts += desiredLocation -> env + desiredLocation + } + else null + + def unmount(location: String) { + mounts.remove(location) match { + case Some(env) => env.node.remove() + case _ => + } + } +} diff --git a/li/cil/oc/server/driver/Peripheral.scala b/li/cil/oc/server/driver/Peripheral.scala new file mode 100644 index 000000000..d3d9cb10e --- /dev/null +++ b/li/cil/oc/server/driver/Peripheral.scala @@ -0,0 +1,20 @@ +package li.cil.oc.server.driver + +import dan200.computer.api.IPeripheral +import li.cil.oc.api.driver +import li.cil.oc.server.component +import net.minecraft.world.World + +object Peripheral extends driver.Block { + def worksWith(world: World, x: Int, y: Int, z: Int) = + world.getBlockTileEntity(x, y, z) match { + case peripheral: IPeripheral => true + case _ => false + } + + def createEnvironment(world: World, x: Int, y: Int, z: Int) = + world.getBlockTileEntity(x, y, z) match { + case peripheral: IPeripheral => new component.Peripheral(peripheral) + case _ => null + } +} diff --git a/li/cil/oc/server/fs/ComputerCraftFileSystem.scala b/li/cil/oc/server/fs/ComputerCraftFileSystem.scala index 976c89abe..0bf89677b 100644 --- a/li/cil/oc/server/fs/ComputerCraftFileSystem.scala +++ b/li/cil/oc/server/fs/ComputerCraftFileSystem.scala @@ -18,7 +18,7 @@ class ComputerCraftFileSystem(val mount: IMount) extends InputStreamFileSystem { override def list(path: String) = { val result = new java.util.ArrayList[String] mount.list(path, result) - result.toArray.asInstanceOf[Array[String]] + result.toArray.map(_.asInstanceOf[String]) } override def size(path: String) = mount.getSize(path)