From 0caf328c1245347e45a0e1dc9fa6bde3346f41b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 17 Feb 2015 12:39:35 +0100 Subject: [PATCH 1/3] Fixes possible NPE in Raid tooltip, closes #918. --- src/main/scala/li/cil/oc/common/block/Raid.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/li/cil/oc/common/block/Raid.scala b/src/main/scala/li/cil/oc/common/block/Raid.scala index 7c32128e3..e23b1a959 100644 --- a/src/main/scala/li/cil/oc/common/block/Raid.scala +++ b/src/main/scala/li/cil/oc/common/block/Raid.scala @@ -29,7 +29,7 @@ class Raid(protected implicit val tileTag: ClassTag[tileentity.Raid]) extends Si super.tooltipTail(metadata, stack, player, tooltip, advanced) if (KeyBindings.showExtendedTooltips) { val data = new RaidData(stack) - for (disk <- data.disks) { + for (disk <- data.disks if disk != null) { tooltip.add("- " + disk.getDisplayName) } } From 0a0609696470b70c639807493d64977b8bf9b171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 17 Feb 2015 12:44:43 +0100 Subject: [PATCH 2/3] Fixed memory sizes in Lua architectures, closes #919. --- .../li/cil/oc/integration/opencomputers/DriverMemory.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/scala/li/cil/oc/integration/opencomputers/DriverMemory.scala b/src/main/scala/li/cil/oc/integration/opencomputers/DriverMemory.scala index bb655ecd1..ea7bf66b1 100644 --- a/src/main/scala/li/cil/oc/integration/opencomputers/DriverMemory.scala +++ b/src/main/scala/li/cil/oc/integration/opencomputers/DriverMemory.scala @@ -10,7 +10,7 @@ import net.minecraft.item.ItemStack object DriverMemory extends Item with driver.item.Memory { override def amount(stack: ItemStack) = Items.multi.subItem(stack) match { - case Some(memory: item.Memory) => memory.tier + case Some(memory: item.Memory) => memory.tier + 1 case _ => 0.0 } From 6e4879c1f2c222765893f67fc5018feb620719ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Tue, 17 Feb 2015 13:35:20 +0100 Subject: [PATCH 3/3] Handling a few more corner-cases in network merges/address changes, hopefully closing #911 for good this time. --- .../li/cil/oc/server/network/Network.scala | 89 +++++++++++-------- .../scala/li/cil/oc/server/network/Node.scala | 9 +- 2 files changed, 57 insertions(+), 41 deletions(-) diff --git a/src/main/scala/li/cil/oc/server/network/Network.scala b/src/main/scala/li/cil/oc/server/network/Network.scala index 17dd7fa3a..e6a1c487f 100644 --- a/src/main/scala/li/cil/oc/server/network/Network.scala +++ b/src/main/scala/li/cil/oc/server/network/Network.scala @@ -9,7 +9,8 @@ import li.cil.oc.OpenComputers import li.cil.oc.Settings import li.cil.oc.api import li.cil.oc.api.network -import li.cil.oc.api.network.{Node => ImmutableNode, _} +import li.cil.oc.api.network._ +import li.cil.oc.api.network.{Node => ImmutableNode} import li.cil.oc.common.block.Cable import li.cil.oc.common.tileentity import li.cil.oc.integration.Mods @@ -21,8 +22,8 @@ import net.minecraft.nbt._ import net.minecraft.tileentity.TileEntity import net.minecraftforge.common.util.ForgeDirection -import scala.collection.convert.WrapAsScala._ import scala.collection.JavaConverters._ +import scala.collection.convert.WrapAsScala._ import scala.collection.mutable import scala.collection.mutable.ArrayBuffer @@ -50,13 +51,21 @@ private class Network private(private val data: mutable.Map[String, Network.Vert node.data.network = wrapper }) - // Called by nodes when they may have changed address from loading. - def remap(node: MutableNode) { - data.find(_._2.data == node) match { - case Some((address, vertex)) => - data -= address - data += node.address -> vertex - case _ => // Eh? + // Called by nodes when they want to change address from loading. + def remap(remappedNode: MutableNode, newAddress: String) { + data.get(remappedNode.address) match { + case Some(node) => + val neighbors = node.edges.map(_.other(node)) + node.data.remove() + node.data.address = newAddress + while (data.contains(node.data.address)) { + node.data.address = java.util.UUID.randomUUID().toString + } + if (neighbors.isEmpty) + addNew(node.data) + else + neighbors.foreach(_.data.connect(node.data)) + case _ => throw new AssertionError("Node believes it belongs to a network it doesn't.") } } @@ -217,7 +226,7 @@ private class Network private(private val data: mutable.Map[String, Network.Vert newNode } - private def add(oldNode: Network.Vertex, addedNode: MutableNode) = { + private def add(oldNode: Network.Vertex, addedNode: MutableNode): Boolean = { // Queue onConnect calls to avoid side effects from callbacks. val connects = mutable.Buffer.empty[(ImmutableNode, Iterable[ImmutableNode])] // Check if the other node is new or if we have to merge networks. @@ -248,44 +257,52 @@ private class Network private(private val data: mutable.Map[String, Network.Vert // never happen in normal operation anyway. It *can* happen when NBT // editing stuff or using mods to clone blocks (e.g. WorldEdit). otherNetwork.data.filter(entry => data.contains(entry._1)).toArray.foreach { - case (address, node: Network.Vertex) => + case (_, node: Network.Vertex) => val neighbors = node.edges.map(_.other(node)) node.data.remove() - node.data.address = java.util.UUID.randomUUID().toString + do { + node.data.address = java.util.UUID.randomUUID().toString + } while (data.contains(node.data.address) || otherNetwork.data.contains(node.data.address)) if (neighbors.isEmpty) otherNetwork.addNew(node.data) else neighbors.foreach(_.data.connect(node.data)) } - if (addedNode.reachability == Visibility.Neighbors) - connects += ((addedNode, Iterable(oldNode.data))) - if (oldNode.data.reachability == Visibility.Neighbors) - connects += ((oldNode.data, Iterable(addedNode))) + // The address change can theoretically cause the node to be kicked from + // its old network (via onConnect callbacks), so we make sure it's still + // in the same network. If it isn't we start over. + if (addedNode.network != null && addedNode.network.asInstanceOf[Network.Wrapper].network == otherNetwork) { + if (addedNode.reachability == Visibility.Neighbors) + connects += ((addedNode, Iterable(oldNode.data))) + if (oldNode.data.reachability == Visibility.Neighbors) + connects += ((oldNode.data, Iterable(addedNode))) - val oldNodes = nodes - val newNodes = otherNetwork.nodes - val oldVisibleNodes = oldNodes.filter(_.reachability == Visibility.Network) - val newVisibleNodes = newNodes.filter(_.reachability == Visibility.Network) + val oldNodes = nodes + val newNodes = otherNetwork.nodes + val oldVisibleNodes = oldNodes.filter(_.reachability == Visibility.Network) + val newVisibleNodes = newNodes.filter(_.reachability == Visibility.Network) - newVisibleNodes.foreach(node => connects += ((node, oldNodes))) - oldVisibleNodes.foreach(node => connects += ((node, newNodes))) + newVisibleNodes.foreach(node => connects += ((node, oldNodes))) + oldVisibleNodes.foreach(node => connects += ((node, newNodes))) - data ++= otherNetwork.data - connectors ++= otherNetwork.connectors - globalBuffer += otherNetwork.globalBuffer - globalBufferSize += otherNetwork.globalBufferSize - otherNetwork.data.values.foreach(node => { - node.data match { - case connector: Connector => connector.distributor = Some(wrapper) - case _ => - } - node.data.network = wrapper - }) - otherNetwork.data.clear() - otherNetwork.connectors.clear() + data ++= otherNetwork.data + connectors ++= otherNetwork.connectors + globalBuffer += otherNetwork.globalBuffer + globalBufferSize += otherNetwork.globalBufferSize + otherNetwork.data.values.foreach(node => { + node.data match { + case connector: Connector => connector.distributor = Some(wrapper) + case _ => + } + node.data.network = wrapper + }) + otherNetwork.data.clear() + otherNetwork.connectors.clear() - Network.Edge(oldNode, node(addedNode)) + Network.Edge(oldNode, node(addedNode)) + } + else add(oldNode, addedNode) } for ((node, nodes) <- connects) nodes.foreach(_.asInstanceOf[MutableNode].onConnect(node)) diff --git a/src/main/scala/li/cil/oc/server/network/Node.scala b/src/main/scala/li/cil/oc/server/network/Node.scala index bae0e6b08..e9e98da6c 100644 --- a/src/main/scala/li/cil/oc/server/network/Node.scala +++ b/src/main/scala/li/cil/oc/server/network/Node.scala @@ -66,11 +66,10 @@ trait Node extends ImmutableNode { def load(nbt: NBTTagCompound) = { if (nbt.hasKey("address")) { - val oldAddress = address - address = nbt.getString("address") - if (address != oldAddress) network match { - case wrapper: Network.Wrapper => wrapper.network.remap(this) - case _ => + val newAddress = nbt.getString("address") + if (newAddress != address) network match { + case wrapper: Network.Wrapper => wrapper.network.remap(this, newAddress) + case _ => address = newAddress } } }