mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-10 07:45:05 -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),
|
Localization.localizeImmediately(rack.getInventoryName),
|
||||||
8, 6, 0x404040)
|
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)
|
GL11.glColor3f(1, 1, 1)
|
||||||
mc.renderEngine.bindTexture(Textures.guiRack)
|
mc.renderEngine.bindTexture(Textures.guiRack)
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ object FileSystemAccessHandler {
|
|||||||
server.lastAccess = System.currentTimeMillis()
|
server.lastAccess = System.currentTimeMillis()
|
||||||
t.markChanged(slot)
|
t.markChanged(slot)
|
||||||
}
|
}
|
||||||
|
case _ =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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.Connector
|
||||||
import li.cil.oc.api.network.EnvironmentHost
|
import li.cil.oc.api.network.EnvironmentHost
|
||||||
import li.cil.oc.api.network.ManagedEnvironment
|
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.Node
|
||||||
import li.cil.oc.api.network.Packet
|
import li.cil.oc.api.network.Packet
|
||||||
|
import li.cil.oc.api.network.Visibility
|
||||||
import li.cil.oc.common.Slot
|
import li.cil.oc.common.Slot
|
||||||
import li.cil.oc.integration.Mods
|
import li.cil.oc.integration.Mods
|
||||||
import li.cil.oc.integration.opencomputers.DriverRedstoneCard
|
import li.cil.oc.integration.opencomputers.DriverRedstoneCard
|
||||||
import li.cil.oc.integration.stargatetech2.DriverAbstractBusCard
|
import li.cil.oc.integration.stargatetech2.DriverAbstractBusCard
|
||||||
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
import li.cil.oc.server.{PacketSender => ServerPacketSender}
|
||||||
import li.cil.oc.util.ExtendedInventory._
|
import li.cil.oc.util.ExtendedInventory._
|
||||||
|
import li.cil.oc.util.ExtendedNBT._
|
||||||
import net.minecraft.entity.player.EntityPlayer
|
import net.minecraft.entity.player.EntityPlayer
|
||||||
import net.minecraft.inventory.IInventory
|
import net.minecraft.inventory.IInventory
|
||||||
import net.minecraft.item.ItemStack
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.nbt.NBTTagCompound
|
import net.minecraft.nbt.NBTTagCompound
|
||||||
|
import net.minecraft.nbt.NBTTagIntArray
|
||||||
|
import net.minecraftforge.common.util.Constants.NBT
|
||||||
import net.minecraftforge.common.util.ForgeDirection
|
import net.minecraftforge.common.util.ForgeDirection
|
||||||
|
|
||||||
import scala.collection.convert.WrapAsJava._
|
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 {
|
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
|
var isRelayEnabled = true
|
||||||
val lastData = new Array[NBTTagCompound](getSizeInventory)
|
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
|
// Map node connections for each installed mountable. Each mountable may
|
||||||
// have up to four outgoing connections, with the first one always being
|
// have up to four outgoing connections, with the first one always being
|
||||||
@ -46,35 +51,83 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
|
|||||||
// messages.
|
// messages.
|
||||||
// mountable -> connectable -> side
|
// mountable -> connectable -> side
|
||||||
val nodeMapping = Array.fill(getSizeInventory)(Array.fill[Option[ForgeDirection]](4)(None))
|
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 {
|
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
|
case _ => None
|
||||||
}
|
}
|
||||||
|
|
||||||
val oldSide = nodeMapping(mountableIndex)(nodeIndex)
|
val oldSide = nodeMapping(slot)(connectableIndex)
|
||||||
if (oldSide == newSide) return
|
if (oldSide == newSide) return
|
||||||
|
|
||||||
// If it's the primary node cut the direct connection.
|
// Cut connection / remove sniffer node.
|
||||||
if (nodeIndex == 0 && oldSide.isDefined) {
|
val mountable = getMountable(slot)
|
||||||
val node = getMountable(mountableIndex).node()
|
if (mountable != null && oldSide.isDefined) {
|
||||||
|
if (connectableIndex == 0) {
|
||||||
|
val node = mountable.node
|
||||||
val plug = sidedNode(toGlobal(oldSide.get))
|
val plug = sidedNode(toGlobal(oldSide.get))
|
||||||
if (node != null && plug != null) {
|
if (node != null && plug != null) {
|
||||||
node.disconnect(plug)
|
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.
|
// Establish connection / add sniffer node.
|
||||||
if (nodeIndex == 0 && newSide.isDefined) {
|
if (mountable != null && newSide.isDefined) {
|
||||||
val node = getMountable(mountableIndex).node()
|
if (connectableIndex == 0) {
|
||||||
|
val node = mountable.node
|
||||||
val plug = sidedNode(toGlobal(newSide.get))
|
val plug = sidedNode(toGlobal(newSide.get))
|
||||||
if (node != null && plug != null) {
|
if (node != null && plug != null) {
|
||||||
node.connect(plug)
|
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
|
// 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
|
// connected to it. Only deliver it to that very node, if it's not the
|
||||||
// sender, to avoid loops.
|
// sender, to avoid loops.
|
||||||
for (mountableIndex <- 0 until getSizeInventory) {
|
for (slot <- 0 until getSizeInventory) {
|
||||||
val mapping = nodeMapping(mountableIndex)
|
val mapping = nodeMapping(slot)
|
||||||
for (nodeIndex <- 0 until 3) {
|
for (connectableIndex <- 0 until 3) {
|
||||||
mapping(nodeIndex + 1) match {
|
mapping(connectableIndex + 1) match {
|
||||||
case Some(side) if sourceSide.contains(toGlobal(side)) =>
|
case Some(side) if sourceSide.contains(toGlobal(side)) =>
|
||||||
val mountable = getMountable(mountableIndex)
|
val mountable = getMountable(slot)
|
||||||
if (mountable != null) {
|
if (mountable != null && connectableIndex < mountable.getConnectableCount) {
|
||||||
val connectable = mountable.getConnectableAt(nodeIndex)
|
val connectable = mountable.getConnectableAt(connectableIndex)
|
||||||
if (connectable != null) {
|
if (connectable != null) {
|
||||||
connectable.receivePacket(packet)
|
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
|
// SidedEnvironment
|
||||||
|
|
||||||
@ -223,19 +310,23 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
|
|||||||
// ComponentInventory
|
// ComponentInventory
|
||||||
|
|
||||||
override protected def onItemAdded(slot: Int, stack: ItemStack): Unit = {
|
override protected def onItemAdded(slot: Int, stack: ItemStack): Unit = {
|
||||||
|
if (isServer) {
|
||||||
for (connectable <- 0 until 4) {
|
for (connectable <- 0 until 4) {
|
||||||
nodeMapping(slot)(connectable) = None
|
nodeMapping(slot)(connectable) = None
|
||||||
}
|
}
|
||||||
lastData(slot) = null
|
lastData(slot) = null
|
||||||
hasChanged(slot) = true
|
hasChanged(slot) = true
|
||||||
|
}
|
||||||
super.onItemAdded(slot, stack)
|
super.onItemAdded(slot, stack)
|
||||||
}
|
}
|
||||||
|
|
||||||
override protected def onItemRemoved(slot: Int, stack: ItemStack): Unit = {
|
override protected def onItemRemoved(slot: Int, stack: ItemStack): Unit = {
|
||||||
|
if (isServer) {
|
||||||
for (connectable <- 0 until 4) {
|
for (connectable <- 0 until 4) {
|
||||||
nodeMapping(slot)(connectable) = None
|
nodeMapping(slot)(connectable) = None
|
||||||
}
|
}
|
||||||
lastData(slot) = null
|
lastData(slot) = null
|
||||||
|
}
|
||||||
super.onItemRemoved(slot, stack)
|
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 = {
|
override def readFromNBTForServer(nbt: NBTTagCompound): Unit = {
|
||||||
super.readFromNBTForServer(nbt)
|
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.
|
// Kickstart initialization.
|
||||||
_isOutputEnabled = hasRedstoneCard
|
_isOutputEnabled = hasRedstoneCard
|
||||||
@ -281,18 +376,26 @@ class Rack extends traits.PowerAcceptor with traits.Hub with traits.PowerBalance
|
|||||||
|
|
||||||
override def writeToNBTForServer(nbt: NBTTagCompound): Unit = {
|
override def writeToNBTForServer(nbt: NBTTagCompound): Unit = {
|
||||||
super.writeToNBTForServer(nbt)
|
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
|
@SideOnly(Side.CLIENT) override
|
||||||
def readFromNBTForClient(nbt: NBTTagCompound): Unit = {
|
def readFromNBTForClient(nbt: NBTTagCompound): Unit = {
|
||||||
super.readFromNBTForClient(nbt)
|
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 = {
|
override def writeToNBTForClient(nbt: NBTTagCompound): Unit = {
|
||||||
super.writeToNBTForClient(nbt)
|
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) {
|
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) {
|
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 = {
|
override def getData: NBTTagCompound = {
|
||||||
val nbt = new NBTTagCompound()
|
val nbt = new NBTTagCompound()
|
||||||
nbt.setBoolean("isRunning", machine.isRunning)
|
nbt.setBoolean("isRunning", wasRunning)
|
||||||
|
nbt.setBoolean("hasErrored", hadErrored)
|
||||||
nbt.setLong("lastAccess", lastAccess)
|
nbt.setLong("lastAccess", lastAccess)
|
||||||
nbt.setBoolean("hasErrored", machine.lastError() != null)
|
|
||||||
nbt
|
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 {
|
override def load(nbt: NBTTagCompound) = Machine.this.synchronized(state.synchronized {
|
||||||
assert(state.top == Machine.State.Stopped)
|
assert(state.top == Machine.State.Stopped || state.top == Machine.State.Paused)
|
||||||
assert(_users.isEmpty)
|
close()
|
||||||
assert(signals.isEmpty)
|
|
||||||
state.clear()
|
state.clear()
|
||||||
|
|
||||||
super.load(nbt)
|
super.load(nbt)
|
||||||
|
@ -42,7 +42,7 @@ trait Node extends ImmutableNode {
|
|||||||
|
|
||||||
def remove() = if (network != null) network.remove(this)
|
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