From 6bb2233cb85cadbdefba237d261ae4d27a26d24d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Sun, 11 Jan 2015 14:07:12 +0100 Subject: [PATCH] Added debug.connectToBlock, allowing debug cards to connect their local network to a remote block. Closes #751, closes #475. --- .../integration/waila/BlockDataProvider.scala | 5 ++ .../cil/oc/server/component/DebugCard.scala | 86 +++++++++++++++++++ 2 files changed, 91 insertions(+) diff --git a/src/main/scala/li/cil/oc/integration/waila/BlockDataProvider.scala b/src/main/scala/li/cil/oc/integration/waila/BlockDataProvider.scala index 133a98532..7cc595ce7 100644 --- a/src/main/scala/li/cil/oc/integration/waila/BlockDataProvider.scala +++ b/src/main/scala/li/cil/oc/integration/waila/BlockDataProvider.scala @@ -3,6 +3,7 @@ package li.cil.oc.integration.waila import java.util import li.cil.oc.Localization +import li.cil.oc.OpenComputers import li.cil.oc.api.network.Component import li.cil.oc.api.network.Connector import li.cil.oc.api.network.Node @@ -30,6 +31,10 @@ object BlockDataProvider extends IWailaDataProvider { registrar.registerNBTProvider(this, classOf[li.cil.oc.api.network.Environment]) registrar.registerNBTProvider(this, classOf[li.cil.oc.api.network.SidedEnvironment]) + + registrar.addConfig(OpenComputers.Name, "oc.address") + registrar.addConfig(OpenComputers.Name, "oc.energy") + registrar.addConfig(OpenComputers.Name, "oc.componentName") } override def getNBTData(player: EntityPlayerMP, tileEntity: TileEntity, tag: NBTTagCompound, world: World, x: Int, y: Int, z: Int) = { diff --git a/src/main/scala/li/cil/oc/server/component/DebugCard.scala b/src/main/scala/li/cil/oc/server/component/DebugCard.scala index 245a1de5d..7541263b8 100644 --- a/src/main/scala/li/cil/oc/server/component/DebugCard.scala +++ b/src/main/scala/li/cil/oc/server/component/DebugCard.scala @@ -7,6 +7,9 @@ import li.cil.oc.api.driver.EnvironmentHost import li.cil.oc.api.machine.Arguments import li.cil.oc.api.machine.Callback import li.cil.oc.api.machine.Context +import li.cil.oc.api.network.Environment +import li.cil.oc.api.network.Node +import li.cil.oc.api.network.SidedEnvironment import li.cil.oc.api.network.Visibility import li.cil.oc.api.prefab import li.cil.oc.server.component.DebugCard.CommandSender @@ -36,6 +39,12 @@ class DebugCard(host: EnvironmentHost) extends prefab.ManagedEnvironment { withConnector(). create() + // Used to detect disconnects. + private var remoteNode: Option[Node] = None + + // Used for delayed connecting to remote node again after loading. + private var remoteNodePosition: Option[(Int, Int, Int)] = None + // ----------------------------------------------------------------------- // import li.cil.oc.server.component.DebugCard.checkEnabled @@ -78,11 +87,87 @@ class DebugCard(host: EnvironmentHost) extends prefab.ManagedEnvironment { @Callback(doc = """function(command:string):number -- Runs an arbitrary command using a fake player.""") def runCommand(context: Context, args: Arguments): Array[AnyRef] = { + checkEnabled() val command = args.checkString(0) val sender = new CommandSender(host) val value = MinecraftServer.getServer.getCommandManager.executeCommand(sender, command) result(value, sender.messages.orNull) } + + @Callback(doc = """function(x:number, y:number, z:number):boolean -- Connect the debug card to the block at the specified coordinates.""") + def connectToBlock(context: Context, args: Arguments): Array[AnyRef] = { + checkEnabled() + val x = args.checkInteger(0) + val y = args.checkInteger(1) + val z = args.checkInteger(2) + findNode(x, y, z) match { + case Some(other) => + remoteNode.foreach(other => node.disconnect(other)) + remoteNode = Some(other) + remoteNodePosition = Some((x, y, z)) + node.connect(other) + result(true) + case _ => + result(Unit, "no node found at this position") + } + } + + private def findNode(x: Int, y: Int, z: Int) = + if (host.world.blockExists(x, y, z)) { + host.world.getTileEntity(x, y, z) match { + case env: SidedEnvironment => ForgeDirection.VALID_DIRECTIONS.map(env.sidedNode).find(_ != null) + case env: Environment => Option(env.node) + case _ => None + } + } + else None + + // ----------------------------------------------------------------------- // + + override def onConnect(node: Node): Unit = { + super.onConnect(node) + if (node == this.node) remoteNodePosition.foreach { + case (x, y, z) => + remoteNode = findNode(x, y, z) + remoteNode match { + case Some(other) => node.connect(other) + case _ => remoteNodePosition = None + } + } + } + + override def onDisconnect(node: Node): Unit = { + super.onDisconnect(node) + if (node == this.node) { + remoteNode.foreach(other => other.disconnect(node)) + } + else if (remoteNode.contains(node)) { + remoteNode = None + remoteNodePosition = None + } + } + + // ----------------------------------------------------------------------- // + + override def load(nbt: NBTTagCompound): Unit = { + super.load(nbt) + if (nbt.hasKey(Settings.namespace + "remoteX")) { + val x = nbt.getInteger(Settings.namespace + "remoteX") + val y = nbt.getInteger(Settings.namespace + "remoteY") + val z = nbt.getInteger(Settings.namespace + "remoteZ") + remoteNodePosition = Some((x, y, z)) + } + } + + override def save(nbt: NBTTagCompound): Unit = { + super.save(nbt) + remoteNodePosition.foreach { + case (x, y, z) => + nbt.setInteger(Settings.namespace + "remoteX", x) + nbt.setInteger(Settings.namespace + "remoteY", y) + nbt.setInteger(Settings.namespace + "remoteZ", z) + } + } } object DebugCard { @@ -369,4 +454,5 @@ object DebugCard { override def func_145748_c_() = fakePlayer.func_145748_c_() } + }