diff --git a/li/cil/oc/common/tileentity/Computer.scala b/li/cil/oc/common/tileentity/Computer.scala index 210b8c0dc..3bd258f8c 100644 --- a/li/cil/oc/common/tileentity/Computer.scala +++ b/li/cil/oc/common/tileentity/Computer.scala @@ -98,7 +98,7 @@ abstract class Computer(isRemote: Boolean) extends Environment with ComponentInv // the network. We skip the update this round to allow other tile entities // to join the network, too, avoiding issues of missing nodes (e.g. in the // GPU which would otherwise loose track of its screen). - if (node != null && node.network != null) { + if (addedToNetwork) { computer.update() if (hasChanged) { diff --git a/li/cil/oc/common/tileentity/Hub.scala b/li/cil/oc/common/tileentity/Hub.scala new file mode 100644 index 000000000..ff2a9a47b --- /dev/null +++ b/li/cil/oc/common/tileentity/Hub.scala @@ -0,0 +1,69 @@ +package li.cil.oc.common.tileentity + +import cpw.mods.fml.relauncher.{Side, SideOnly} +import li.cil.oc.api.network.{Node, Message, Visibility, SidedEnvironment} +import li.cil.oc.util.ExtendedNBT._ +import li.cil.oc.{api, Settings} +import net.minecraft.nbt.NBTTagCompound +import net.minecraftforge.common.ForgeDirection + +trait Hub extends Environment with SidedEnvironment { + protected val plugs = ForgeDirection.VALID_DIRECTIONS.map(side => new Plug(side)) + + // ----------------------------------------------------------------------- // + + def node = null + + @SideOnly(Side.CLIENT) + def canConnect(side: ForgeDirection) = true + + def sidedNode(side: ForgeDirection) = plugs(side.ordinal()).node + + // ----------------------------------------------------------------------- // + + override def readFromNBT(nbt: NBTTagCompound) { + super.readFromNBT(nbt) + nbt.getTagList(Settings.namespace + "plugs").iterator[NBTTagCompound].zip(plugs).foreach { + case (plugNbt, plug) => plug.node.load(plugNbt) + } + } + + override def writeToNBT(nbt: NBTTagCompound) { + super.writeToNBT(nbt) + nbt.setNewTagList(Settings.namespace + "plugs", plugs.map(plug => { + val plugNbt = new NBTTagCompound() + plug.node.save(plugNbt) + plugNbt + })) + } + + // ----------------------------------------------------------------------- // + + protected class Plug(val side: ForgeDirection) extends api.network.Environment { + val node = api.Network.newNode(this, Visibility.Network).create() + + def onMessage(message: Message) { + if (isPrimary) { + onPlugMessage(this, message) + } + } + + def onConnect(node: Node) = onPlugConnect(this, node) + + def onDisconnect(node: Node) = onPlugDisconnect(this, node) + + def isPrimary = plugs(plugs.indexWhere(_.node.network == node.network)) == this + + def plugsInOtherNetworks = plugs.filter(_.node.network != node.network) + } + + protected def onPlugConnect(plug: Plug, node: Node) {} + + protected def onPlugDisconnect(plug: Plug, node: Node) {} + + protected def onPlugMessage(plug: Plug, message: Message) { + if (message.name == "network.message") { + plug.plugsInOtherNetworks.foreach(_.node.sendToReachable(message.name, message.data: _*)) + } + } +} diff --git a/li/cil/oc/common/tileentity/Rack.scala b/li/cil/oc/common/tileentity/Rack.scala index 14d082a03..d104d4e21 100644 --- a/li/cil/oc/common/tileentity/Rack.scala +++ b/li/cil/oc/common/tileentity/Rack.scala @@ -2,10 +2,10 @@ package li.cil.oc.common.tileentity import cpw.mods.fml.common.Optional import cpw.mods.fml.relauncher.{Side, SideOnly} -import li.cil.oc.api.network.{Node, Analyzable, Visibility} +import li.cil.oc.api.network.{Node, Analyzable} import li.cil.oc.server.{PacketSender => ServerPacketSender, driver, component} import li.cil.oc.util.ExtendedNBT._ -import li.cil.oc.{Items, Settings, api} +import li.cil.oc.{Items, Settings} import net.minecraft.entity.player.EntityPlayer import net.minecraft.item.ItemStack import net.minecraft.nbt.NBTTagCompound @@ -14,11 +14,11 @@ import stargatetech2.api.bus.IBusDevice // See AbstractBusAware as to why we have to define the IBusDevice here. @Optional.Interface(iface = "stargatetech2.api.bus.IBusDevice", modid = "StargateTech2") -class Rack extends Environment with Inventory with Rotatable with BundledRedstoneAware with AbstractBusAware with IBusDevice with Analyzable { - val node = api.Network.newNode(this, Visibility.None).create() - +class Rack extends Hub with Inventory with Rotatable with BundledRedstoneAware with AbstractBusAware with IBusDevice with Analyzable { val servers = Array.fill(getSizeInventory)(None: Option[component.Server]) + val sides = Array.fill(servers.length)(ForgeDirection.UNKNOWN) + // For client side, where we don't create the component. private val _isRunning = new Array[Boolean](getSizeInventory) @@ -29,6 +29,10 @@ class Rack extends Environment with Inventory with Rotatable with BundledRedston // ----------------------------------------------------------------------- // + override def canConnect(side: ForgeDirection) = side != facing + + // ----------------------------------------------------------------------- // + def isRunning(number: Int) = if (isServer) servers(number).fold(false)(_.machine.isRunning) else _isRunning(number) @@ -69,6 +73,19 @@ class Rack extends Environment with Inventory with Rotatable with BundledRedston case _ => false } + def reconnectServer(number: Int, server: component.Server) { + val serverSide = sides(number) + val serverNode = server.machine.node + for (side <- ForgeDirection.VALID_DIRECTIONS) { + if (serverSide == side || serverSide == ForgeDirection.UNKNOWN) { + sidedNode(side).connect(serverNode) + } + else { + sidedNode(side).disconnect(serverNode) + } + } + } + // ----------------------------------------------------------------------- // def getSizeInventory = 4 @@ -97,7 +114,7 @@ class Rack extends Environment with Inventory with Rotatable with BundledRedston override def updateEntity() { if (isServer) { - if (node != null && node.network != null) { + if (addedToNetwork) { servers collect { case Some(server) => server.machine.update() } @@ -170,11 +187,15 @@ class Rack extends Environment with Inventory with Rotatable with BundledRedston // ----------------------------------------------------------------------- // - override def onConnect(node: Node) { - super.onConnect(node) - if (node == this.node) { - servers collect { - case Some(server) => node.connect(server.machine.node) + override protected def onPlugConnect(plug: Plug, node: Node) { + if (node == plug.node) { + for (number <- 0 until servers.length) { + val serverSide = sides(number) + servers(number) match { + case Some(server) if serverSide == plug.side || serverSide == ForgeDirection.UNKNOWN => + plug.node.connect(server.machine.node) + case _ => + } } } } @@ -184,7 +205,7 @@ class Rack extends Environment with Inventory with Rotatable with BundledRedston if (isServer) { val server = new component.Server(this, slot) servers(slot) = Some(server) - node.connect(server.machine.node) + reconnectServer(slot, server) } } diff --git a/li/cil/oc/common/tileentity/Router.scala b/li/cil/oc/common/tileentity/Router.scala index 5f7b023b9..6fae9d1bf 100644 --- a/li/cil/oc/common/tileentity/Router.scala +++ b/li/cil/oc/common/tileentity/Router.scala @@ -1,27 +1,13 @@ package li.cil.oc.common.tileentity import cpw.mods.fml.common.{Loader, Optional} -import cpw.mods.fml.relauncher.{Side, SideOnly} import dan200.computer.api.{ILuaContext, IComputerAccess, IPeripheral} -import li.cil.oc.api.network.{Node, Message, Visibility} -import li.cil.oc.util.ExtendedNBT._ -import li.cil.oc.{Blocks, Settings, api} -import net.minecraft.nbt.NBTTagCompound -import net.minecraftforge.common.ForgeDirection +import li.cil.oc.Blocks +import li.cil.oc.api.network.Message import scala.collection.mutable @Optional.Interface(iface = "dan200.computer.api.IPeripheral", modid = "ComputerCraft") -class Router extends TileEntity with api.network.SidedEnvironment with IPeripheral with PassiveNode { - private val plugs = ForgeDirection.VALID_DIRECTIONS.map(side => new Plug(side)) - - // ----------------------------------------------------------------------- // - - @SideOnly(Side.CLIENT) - def canConnect(side: ForgeDirection) = true - - def sidedNode(side: ForgeDirection) = plugs(side.ordinal()).node - - // ----------------------------------------------------------------------- // +class Router extends Hub with IPeripheral with PassiveNode { override def canUpdate = false @@ -30,38 +16,6 @@ class Router extends TileEntity with api.network.SidedEnvironment with IPeripher worldObj.scheduleBlockUpdateFromLoad(xCoord, yCoord, zCoord, Blocks.router.parent.blockID, 0, 0) } - override def invalidate() { - super.invalidate() - for (plug <- plugs if plug.node != null) { - plug.node.remove() - } - } - - override def onChunkUnload() { - super.onChunkUnload() - for (plug <- plugs if plug.node != null) { - plug.node.remove() - } - } - - // ----------------------------------------------------------------------- // - - override def readFromNBT(nbt: NBTTagCompound) { - super.readFromNBT(nbt) - nbt.getTagList(Settings.namespace + "plugs").iterator[NBTTagCompound].zip(plugs).foreach { - case (plugNbt, plug) => plug.node.load(plugNbt) - } - } - - override def writeToNBT(nbt: NBTTagCompound) { - super.writeToNBT(nbt) - nbt.setNewTagList(Settings.namespace + "plugs", plugs.map(plug => { - val plugNbt = new NBTTagCompound() - plug.node.save(plugNbt) - plugNbt - })) - } - // ----------------------------------------------------------------------- // // Peripheral @@ -124,8 +78,6 @@ class Router extends TileEntity with api.network.SidedEnvironment with IPeripher port } - // ----------------------------------------------------------------------- // - private def queueMessage(port: Int, answerPort: Int, args: Seq[AnyRef]) { for (computer <- computers.map(_.asInstanceOf[IComputerAccess])) { if (openPorts(computer).contains(port)) @@ -136,31 +88,16 @@ class Router extends TileEntity with api.network.SidedEnvironment with IPeripher } } - private class Plug(val side: ForgeDirection) extends api.network.Environment { - val node = api.Network.newNode(this, Visibility.Network).create() - - def onMessage(message: Message) { - if (isPrimary && message.name == "network.message") { - plugsInOtherNetworks.foreach(_.node.sendToReachable(message.name, message.data: _*)) - if (Loader.isModLoaded("ComputerCraft")) { - message.data match { - case Array(port: Integer, answerPort: java.lang.Double, args@_*) => - queueMessage(port, answerPort.toInt, args) - case Array(port: Integer, args@_*) => - queueMessage(port, -1, args) - case _ => - } - } + override protected def onPlugMessage(plug: Plug, message: Message) { + super.onPlugMessage(plug, message) + if (message.name == "network.message" && Loader.isModLoaded("ComputerCraft")) { + message.data match { + case Array(port: Integer, answerPort: java.lang.Double, args@_*) => + queueMessage(port, answerPort.toInt, args) + case Array(port: Integer, args@_*) => + queueMessage(port, -1, args) + case _ => } } - - def onDisconnect(node: Node) {} - - def onConnect(node: Node) {} - - private def isPrimary = plugs(plugs.indexWhere(_.node.network == node.network)) == this - - private def plugsInOtherNetworks = plugs.filter(_.node.network != node.network) } - } diff --git a/li/cil/oc/server/component/Machine.scala b/li/cil/oc/server/component/Machine.scala index f5bbb27f1..7ac2294b2 100644 --- a/li/cil/oc/server/component/Machine.scala +++ b/li/cil/oc/server/component/Machine.scala @@ -718,8 +718,7 @@ class Machine(val owner: Machine.Owner) extends ManagedComponent with Context wi state.push(Machine.State.Yielded) state.push(Machine.State.Paused) case Machine.State.Stopping => // Nothing to do, we'll die anyway. - case _ => throw new AssertionError( - "Invalid state in executor post-processing.") + case _ => throw new AssertionError("Invalid state in executor post-processing.") } assert(state.top != Machine.State.Running) }