mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-08 06:41:23 -04:00
Two-way forwarding of network messages for mountable sub-nodes.
Avoid errors when calling load on machines multiple times.
This commit is contained in:
parent
31e4c3c53a
commit
88eae3bfe5
@ -164,13 +164,6 @@ class Rack(playerInventory: InventoryPlayer, val rack: tileentity.Rack) extends
|
||||
Localization.localizeImmediately(rack.getInventoryName),
|
||||
8, 6, 0x404040)
|
||||
|
||||
// for (i <- 0 to 3 if powerButtons(i).func_146115_a) {
|
||||
// val tooltip = new java.util.ArrayList[String]
|
||||
// tooltip.addAll(asJavaCollection(if (rack.isRunning(i)) Localization.Computer.TurnOff.lines.toIterable else Localization.Computer.TurnOn.lines.toIterable))
|
||||
// copiedDrawHoveringText(tooltip, mouseX - guiLeft, mouseY - guiTop, fontRendererObj)
|
||||
// }
|
||||
//
|
||||
|
||||
GL11.glColor3f(1, 1, 1)
|
||||
mc.renderEngine.bindTexture(Textures.guiRack)
|
||||
|
||||
|
@ -22,6 +22,7 @@ object FileSystemAccessHandler {
|
||||
server.lastAccess = System.currentTimeMillis()
|
||||
t.markChanged(slot)
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
case _ =>
|
||||
|
@ -16,18 +16,23 @@ import li.cil.oc.api.network.ComponentHost
|
||||
import li.cil.oc.api.network.Connector
|
||||
import li.cil.oc.api.network.EnvironmentHost
|
||||
import li.cil.oc.api.network.ManagedEnvironment
|
||||
import li.cil.oc.api.network.Message
|
||||
import li.cil.oc.api.network.Node
|
||||
import li.cil.oc.api.network.Packet
|
||||
import li.cil.oc.api.network.Visibility
|
||||
import li.cil.oc.common.Slot
|
||||
import li.cil.oc.integration.Mods
|
||||
import li.cil.oc.integration.opencomputers.DriverRedstoneCard
|
||||
import li.cil.oc.integration.stargatetech2.DriverAbstractBusCard
|
||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||
import li.cil.oc.util.ExtendedInventory._
|
||||
import li.cil.oc.util.ExtendedNBT._
|
||||
import net.minecraft.entity.player.EntityPlayer
|
||||
import net.minecraft.inventory.IInventory
|
||||
import net.minecraft.item.ItemStack
|
||||
import net.minecraft.nbt.NBTTagCompound
|
||||
import net.minecraft.nbt.NBTTagIntArray
|
||||
import net.minecraftforge.common.util.Constants.NBT
|
||||
import net.minecraftforge.common.util.ForgeDirection
|
||||
|
||||
import scala.collection.convert.WrapAsJava._
|
||||
@ -36,7 +41,7 @@ import scala.collection.convert.WrapAsScala._
|
||||
class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalancer with traits.ComponentInventory with traits.Rotatable with traits.BundledRedstoneAware with traits.AbstractBusAware with Analyzable with internal.Rack with traits.StateAware {
|
||||
var isRelayEnabled = true
|
||||
val lastData = new Array[NBTTagCompound](getSizeInventory)
|
||||
val hasChanged = new Array[Boolean](getSizeInventory)
|
||||
val hasChanged = Array.fill(getSizeInventory)(true)
|
||||
|
||||
// Map node connections for each installed mountable. Each mountable may
|
||||
// have up to four outgoing connections, with the first one always being
|
||||
@ -46,33 +51,81 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
|
||||
// messages.
|
||||
// mountable -> connectable -> side
|
||||
val nodeMapping = Array.fill(getSizeInventory)(Array.fill[Option[ForgeDirection]](4)(None))
|
||||
val snifferNodes = Array.fill(getSizeInventory)(Array.fill(3)(api.Network.newNode(this, Visibility.Neighbors).create()))
|
||||
|
||||
def connect(mountableIndex: Int, nodeIndex: Int, side: Option[ForgeDirection]): Unit = {
|
||||
def connect(slot: Int, connectableIndex: Int, side: Option[ForgeDirection]): Unit = {
|
||||
val newSide = side match {
|
||||
case Some(direction) if direction != ForgeDirection.UNKNOWN => Option(direction)
|
||||
case Some(direction) if direction != ForgeDirection.UNKNOWN && direction != ForgeDirection.SOUTH => Option(direction)
|
||||
case _ => None
|
||||
}
|
||||
|
||||
val oldSide = nodeMapping(mountableIndex)(nodeIndex)
|
||||
val oldSide = nodeMapping(slot)(connectableIndex)
|
||||
if (oldSide == newSide) return
|
||||
|
||||
// If it's the primary node cut the direct connection.
|
||||
if (nodeIndex == 0 && oldSide.isDefined) {
|
||||
val node = getMountable(mountableIndex).node()
|
||||
val plug = sidedNode(toGlobal(oldSide.get))
|
||||
if (node != null && plug != null) {
|
||||
node.disconnect(plug)
|
||||
// Cut connection / remove sniffer node.
|
||||
val mountable = getMountable(slot)
|
||||
if (mountable != null && oldSide.isDefined) {
|
||||
if (connectableIndex == 0) {
|
||||
val node = mountable.node
|
||||
val plug = sidedNode(toGlobal(oldSide.get))
|
||||
if (node != null && plug != null) {
|
||||
node.disconnect(plug)
|
||||
}
|
||||
}
|
||||
else {
|
||||
snifferNodes(slot)(connectableIndex).remove()
|
||||
}
|
||||
}
|
||||
|
||||
nodeMapping(mountableIndex)(nodeIndex) = newSide
|
||||
nodeMapping(slot)(connectableIndex) = newSide
|
||||
|
||||
// If it's the primary node establish a direct connection.
|
||||
if (nodeIndex == 0 && newSide.isDefined) {
|
||||
val node = getMountable(mountableIndex).node()
|
||||
val plug = sidedNode(toGlobal(newSide.get))
|
||||
if (node != null && plug != null) {
|
||||
node.connect(plug)
|
||||
// Establish connection / add sniffer node.
|
||||
if (mountable != null && newSide.isDefined) {
|
||||
if (connectableIndex == 0) {
|
||||
val node = mountable.node
|
||||
val plug = sidedNode(toGlobal(newSide.get))
|
||||
if (node != null && plug != null) {
|
||||
node.connect(plug)
|
||||
}
|
||||
}
|
||||
else if (connectableIndex < mountable.getConnectableCount) {
|
||||
val connectable = mountable.getConnectableAt(connectableIndex)
|
||||
if (connectable != null && connectable.node != null) {
|
||||
if (connectable.node.network == null) {
|
||||
api.Network.joinNewNetwork(connectable.node)
|
||||
}
|
||||
connectable.node.connect(snifferNodes(slot)(connectableIndex))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def reconnect(plugSide: ForgeDirection): Unit = {
|
||||
for (slot <- 0 until getSizeInventory) {
|
||||
val mapping = nodeMapping(slot)
|
||||
mapping(0) match {
|
||||
case Some(side) if toGlobal(side) == plugSide =>
|
||||
val mountable = getMountable(slot)
|
||||
if (mountable != null && mountable.node != null && node != mountable.node) {
|
||||
mountable.node.connect(sidedNode(plugSide))
|
||||
}
|
||||
case _ => // Not connected to this side.
|
||||
}
|
||||
for (connectableIndex <- 0 until 3) {
|
||||
mapping(connectableIndex) match {
|
||||
case Some(side) if toGlobal(side) == plugSide =>
|
||||
val mountable = getMountable(slot)
|
||||
if (mountable != null && connectableIndex < mountable.getConnectableCount) {
|
||||
val connectable = mountable.getConnectableAt(connectableIndex)
|
||||
if (connectable != null && connectable.node != null) {
|
||||
if (connectable.node.network == null) {
|
||||
api.Network.joinNewNetwork(connectable.node)
|
||||
}
|
||||
connectable.node.connect(snifferNodes(slot)(connectableIndex))
|
||||
}
|
||||
}
|
||||
case _ => // Not connected to this side.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -86,14 +139,14 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
|
||||
// When a message arrives on a bus, also send it to all secondary nodes
|
||||
// connected to it. Only deliver it to that very node, if it's not the
|
||||
// sender, to avoid loops.
|
||||
for (mountableIndex <- 0 until getSizeInventory) {
|
||||
val mapping = nodeMapping(mountableIndex)
|
||||
for (nodeIndex <- 0 until 3) {
|
||||
mapping(nodeIndex + 1) match {
|
||||
for (slot <- 0 until getSizeInventory) {
|
||||
val mapping = nodeMapping(slot)
|
||||
for (connectableIndex <- 0 until 3) {
|
||||
mapping(connectableIndex + 1) match {
|
||||
case Some(side) if sourceSide.contains(toGlobal(side)) =>
|
||||
val mountable = getMountable(mountableIndex)
|
||||
if (mountable != null) {
|
||||
val connectable = mountable.getConnectableAt(nodeIndex)
|
||||
val mountable = getMountable(slot)
|
||||
if (mountable != null && connectableIndex < mountable.getConnectableCount) {
|
||||
val connectable = mountable.getConnectableAt(connectableIndex)
|
||||
if (connectable != null) {
|
||||
connectable.receivePacket(packet)
|
||||
}
|
||||
@ -104,6 +157,40 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
|
||||
}
|
||||
}
|
||||
|
||||
override protected def onPlugConnect(plug: Plug, node: Node): Unit = {
|
||||
super.onPlugConnect(plug, node)
|
||||
connectComponents()
|
||||
reconnect(plug.side)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
// Environment
|
||||
|
||||
override def onMessage(message: Message): Unit = {
|
||||
super.onMessage(message)
|
||||
if (message.name == "network.message") message.data match {
|
||||
case Array(packet: Packet) =>
|
||||
for (slot <- 0 until getSizeInventory) {
|
||||
val mapping = nodeMapping(slot)
|
||||
for (connectableIndex <- 0 until 3) {
|
||||
mapping(connectableIndex + 1) match {
|
||||
case Some(side) =>
|
||||
val mountable = getMountable(slot)
|
||||
if (mountable != null && connectableIndex < mountable.getConnectableCount) {
|
||||
val connectable = mountable.getConnectableAt(connectableIndex)
|
||||
if (connectable != null && connectable.node == message.source) {
|
||||
sidedNode(toGlobal(side)).sendToReachable("network.message", packet)
|
||||
return
|
||||
}
|
||||
}
|
||||
case _ => // Not connected to a bus.
|
||||
}
|
||||
}
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
// SidedEnvironment
|
||||
|
||||
@ -223,19 +310,23 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
|
||||
// ComponentInventory
|
||||
|
||||
override protected def onItemAdded(slot: Int, stack: ItemStack): Unit = {
|
||||
for (connectable <- 0 until 4) {
|
||||
nodeMapping(slot)(connectable) = None
|
||||
if (isServer) {
|
||||
for (connectable <- 0 until 4) {
|
||||
nodeMapping(slot)(connectable) = None
|
||||
}
|
||||
lastData(slot) = null
|
||||
hasChanged(slot) = true
|
||||
}
|
||||
lastData(slot) = null
|
||||
hasChanged(slot) = true
|
||||
super.onItemAdded(slot, stack)
|
||||
}
|
||||
|
||||
override protected def onItemRemoved(slot: Int, stack: ItemStack): Unit = {
|
||||
for (connectable <- 0 until 4) {
|
||||
nodeMapping(slot)(connectable) = None
|
||||
if (isServer) {
|
||||
for (connectable <- 0 until 4) {
|
||||
nodeMapping(slot)(connectable) = None
|
||||
}
|
||||
lastData(slot) = null
|
||||
}
|
||||
lastData(slot) = null
|
||||
super.onItemRemoved(slot, stack)
|
||||
}
|
||||
|
||||
@ -272,7 +363,11 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
|
||||
|
||||
override def readFromNBTForServer(nbt: NBTTagCompound): Unit = {
|
||||
super.readFromNBTForServer(nbt)
|
||||
// TODO read lastState and nodeMapping
|
||||
|
||||
isRelayEnabled = nbt.getBoolean(Settings.namespace + "isRelayEnabled")
|
||||
nbt.getTagList(Settings.namespace + "nodeMapping", NBT.TAG_INT_ARRAY).map((buses: NBTTagIntArray) =>
|
||||
buses.func_150302_c().map(id => if (id < 0 || id == ForgeDirection.UNKNOWN.ordinal() || id == ForgeDirection.SOUTH.ordinal()) None else Option(ForgeDirection.getOrientation(id)))).
|
||||
copyToArray(nodeMapping)
|
||||
|
||||
// Kickstart initialization.
|
||||
_isOutputEnabled = hasRedstoneCard
|
||||
@ -281,18 +376,26 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
|
||||
|
||||
override def writeToNBTForServer(nbt: NBTTagCompound): Unit = {
|
||||
super.writeToNBTForServer(nbt)
|
||||
// TODO store lastState and nodeMapping
|
||||
|
||||
nbt.setBoolean(Settings.namespace + "isRelayEnabled", isRelayEnabled)
|
||||
nbt.setNewTagList(Settings.namespace + "nodeMapping", nodeMapping.map(buses =>
|
||||
toNbt(buses.map(side => side.map(_.ordinal()).getOrElse(-1)))))
|
||||
}
|
||||
|
||||
@SideOnly(Side.CLIENT) override
|
||||
def readFromNBTForClient(nbt: NBTTagCompound): Unit = {
|
||||
super.readFromNBTForClient(nbt)
|
||||
// TODO read lastState
|
||||
|
||||
val data = nbt.getTagList(Settings.namespace + "lastData", NBT.TAG_COMPOUND).
|
||||
toArray[NBTTagCompound]
|
||||
data.copyToArray(lastData)
|
||||
}
|
||||
|
||||
override def writeToNBTForClient(nbt: NBTTagCompound): Unit = {
|
||||
super.writeToNBTForClient(nbt)
|
||||
// TODO store lastState
|
||||
|
||||
val data = lastData.map(tag => if (tag == null) new NBTTagCompound() else tag)
|
||||
nbt.setNewTagList(Settings.namespace + "lastData", data)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
@ -56,21 +56,6 @@ class Server(val rack: tileentity.Rack, val slot: Int) extends Environment with
|
||||
}
|
||||
|
||||
override def onMessage(message: Message) {
|
||||
// If we're internal mode and this server is not connected to any side, we
|
||||
// must manually propagate network messages to other servers in the rack.
|
||||
// Ensure the message originated in our local network, to avoid infinite
|
||||
// recursion if two unconnected servers are in one server rack.
|
||||
// if (rack.internalSwitch && message.name == "network.message" &&
|
||||
// rack.sides(this.slot).isEmpty && // Only if we're in internal mode.
|
||||
// message.source != machine.node && // In this case it was relayed from another internal machine.
|
||||
// node.network.node(message.source.address) != null) {
|
||||
// for (slot <- rack.servers.indices) {
|
||||
// rack.servers(slot) match {
|
||||
// case Some(server) if server != this => server.machine.node.sendToNeighbors(message.name, message.data: _*)
|
||||
// case _ =>
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
override def load(nbt: NBTTagCompound) {
|
||||
@ -151,9 +136,9 @@ class Server(val rack: tileentity.Rack, val slot: Int) extends Environment with
|
||||
|
||||
override def getData: NBTTagCompound = {
|
||||
val nbt = new NBTTagCompound()
|
||||
nbt.setBoolean("isRunning", machine.isRunning)
|
||||
nbt.setBoolean("isRunning", wasRunning)
|
||||
nbt.setBoolean("hasErrored", hadErrored)
|
||||
nbt.setLong("lastAccess", lastAccess)
|
||||
nbt.setBoolean("hasErrored", machine.lastError() != null)
|
||||
nbt
|
||||
}
|
||||
|
||||
|
@ -660,9 +660,8 @@ class Machine(val host: MachineHost) extends prefab.ManagedEnvironment with mach
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
override def load(nbt: NBTTagCompound) = Machine.this.synchronized(state.synchronized {
|
||||
assert(state.top == Machine.State.Stopped)
|
||||
assert(_users.isEmpty)
|
||||
assert(signals.isEmpty)
|
||||
assert(state.top == Machine.State.Stopped || state.top == Machine.State.Paused)
|
||||
close()
|
||||
state.clear()
|
||||
|
||||
super.load(nbt)
|
||||
|
@ -42,7 +42,7 @@ trait Node extends ImmutableNode {
|
||||
|
||||
def remove() = if (network != null) network.remove(this)
|
||||
|
||||
private def isInSameNetwork(other: ImmutableNode) = network != null && network == other.network
|
||||
private def isInSameNetwork(other: ImmutableNode) = network != null && other != null && network == other.network
|
||||
|
||||
// ----------------------------------------------------------------------- //
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user