From f8bfbf55b153b1efd3e83d06d46d5e0657ad40ef Mon Sep 17 00:00:00 2001 From: payonel Date: Tue, 2 Jan 2018 20:59:09 -0800 Subject: [PATCH] make component inventory components array even more lazy allow a component inventory to define its inventory size from nbt even after the components array has been accessed. The array will appear to be size zero until initialized closes #2522 --- .../common/inventory/ComponentInventory.scala | 29 +++++++++++++++---- .../li/cil/oc/common/tileentity/Case.scala | 8 ++++- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/main/scala/li/cil/oc/common/inventory/ComponentInventory.scala b/src/main/scala/li/cil/oc/common/inventory/ComponentInventory.scala index 6aa9c5349..8caf654c8 100644 --- a/src/main/scala/li/cil/oc/common/inventory/ComponentInventory.scala +++ b/src/main/scala/li/cil/oc/common/inventory/ComponentInventory.scala @@ -17,7 +17,16 @@ import scala.collection.convert.WrapAsScala._ import scala.collection.mutable trait ComponentInventory extends Inventory with network.Environment { - lazy val components = Array.fill[Option[ManagedEnvironment]](getSizeInventory)(None) + private var _components: Array[Option[ManagedEnvironment]] = _ + protected var isSizeInventoryReady: Boolean = true + + def components: Array[Option[ManagedEnvironment]] = { + if (_components == null && isSizeInventoryReady) { + _components = Array.fill[Option[ManagedEnvironment]](getSizeInventory)(None) + } + if (_components == null) Array[Option[ManagedEnvironment]]() else _components + } + protected val updatingComponents = mutable.ArrayBuffer.empty[ManagedEnvironment] // ----------------------------------------------------------------------- // @@ -99,11 +108,19 @@ trait ComponentInventory extends Inventory with network.Environment { for (slot <- 0 until getSizeInventory) { val stack = getStackInSlot(slot) if (stack != null) { - components(slot) match { - case Some(component) => - // We're guaranteed to have a driver for entries. - save(component, Driver.driverFor(stack), stack) - case _ => // Nothing special to save. + if (slot >= components.length) { + // isSizeInventoryReady was added to resolve issues where an inventory was used before its + // nbt data had been parsed. See https://github.com/MightyPirates/OpenComputers/issues/2522 + // If this error is hit again, perhaps another subtype needs to handle nbt loading like Case does + OpenComputers.log.error(s"ComponentInventory components length ${components.length} does not accommodate inventory size ${getSizeInventory}") + return + } else { + components(slot) match { + case Some(component) => + // We're guaranteed to have a driver for entries. + save(component, Driver.driverFor(stack), stack) + case _ => // Nothing special to save. + } } } } diff --git a/src/main/scala/li/cil/oc/common/tileentity/Case.scala b/src/main/scala/li/cil/oc/common/tileentity/Case.scala index b71f7464c..dd26a205f 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/Case.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/Case.scala @@ -25,7 +25,12 @@ import net.minecraftforge.common.util.ForgeDirection import scala.collection.convert.WrapAsJava._ class Case(var tier: Int) extends traits.PowerAcceptor with traits.Computer with traits.Colored with internal.Case with DeviceInfo { - def this() = this(0) + def this() = { + this(0) + // If no tier was defined when constructing this case, then we don't yet know the inventory size + // this is set back to true when the nbt data is loaded + isSizeInventoryReady = false + } // Used on client side to check whether to render disk activity/network indicators. var lastFileSystemAccess = 0L @@ -78,6 +83,7 @@ class Case(var tier: Int) extends traits.PowerAcceptor with traits.Computer with tier = nbt.getByte(Settings.namespace + "tier") max 0 min 3 color = Color.byTier(tier) super.readFromNBTForServer(nbt) + isSizeInventoryReady = true } override def writeToNBTForServer(nbt: NBTTagCompound) {