diff --git a/src/main/scala/li/cil/oc/common/item/Tablet.scala b/src/main/scala/li/cil/oc/common/item/Tablet.scala index d8cf57f49..3d6ce41bf 100644 --- a/src/main/scala/li/cil/oc/common/item/Tablet.scala +++ b/src/main/scala/li/cil/oc/common/item/Tablet.scala @@ -40,6 +40,7 @@ import net.minecraft.world.World import net.minecraftforge.common.util.ForgeDirection import net.minecraftforge.event.world.WorldEvent +import scala.collection.convert.WrapAsJava._ import scala.collection.convert.WrapAsScala._ class Tablet(val parent: Delegator) extends Delegate { @@ -119,11 +120,16 @@ class Tablet(val parent: Delegator) extends Delegate { } class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends ComponentInventory with MachineHost with internal.Tablet { - lazy val machine = if (player.worldObj.isRemote) null else Machine.create(this) + // Remember our *original* world, so we know which tablets to clear on dimension + // changes of players holding tablets - since the player entity instance may be + // kept the same and components are not required to properly handle world changes. + val world = player.worldObj + + lazy val machine = if (world.isRemote) null else Machine.create(this) val data = new TabletData() - val tablet = if (player.worldObj.isRemote) null else new component.Tablet(this) + val tablet = if (world.isRemote) null else new component.Tablet(this) private var isInitialized = !world.isRemote @@ -229,8 +235,6 @@ class TabletWrapper(var stack: ItemStack, var player: EntityPlayer) extends Comp override def zPosition = player.posZ - override def world = player.worldObj - override def markChanged() {} // ----------------------------------------------------------------------- // @@ -338,8 +342,8 @@ object Tablet { @SubscribeEvent def onWorldUnload(e: WorldEvent.Unload) { - Client.clear() - Server.clear() + Client.clear(e.world) + Server.clear(e.world) } @SubscribeEvent @@ -371,7 +375,16 @@ object Tablet { cache.synchronized { currentStack = stack currentHolder = holder - val wrapper = cache.get(id, this) + var wrapper = cache.get(id, this) + + // Force re-load on world change, in case some components store a + // reference to the world object. + if (holder.worldObj != wrapper.world) { + cache.invalidate(id) + cache.cleanUp() + wrapper = cache.get(id, this) + } + wrapper.stack = stack wrapper.player = holder wrapper @@ -395,9 +408,10 @@ object Tablet { } } - def clear() { + def clear(world: World) { cache.synchronized { - cache.invalidateAll() + val tabletsInWorld = cache.asMap.filter(_._2.world == world) + cache.invalidateAll(asJavaIterable(tabletsInWorld.keys)) cache.cleanUp() } }