Moved some more logic to save handler and removed old compatibility code from save/load logic in machines (they'd be reset by now anyway due to API changes).

This commit is contained in:
Florian Nücke 2014-08-02 13:34:53 +02:00
parent e008949c7b
commit beb33d4819
2 changed files with 39 additions and 28 deletions

View File

@ -4,8 +4,11 @@ import java.io
import java.io.{File, FileFilter} import java.io.{File, FileFilter}
import java.util.logging.Level import java.util.logging.Level
import li.cil.oc.api.driver.Container
import li.cil.oc.api.machine.Owner
import li.cil.oc.{OpenComputers, Settings} import li.cil.oc.{OpenComputers, Settings}
import net.minecraft.world.ChunkCoordIntPair import net.minecraft.nbt.NBTTagCompound
import net.minecraft.world.{ChunkCoordIntPair, World}
import net.minecraftforge.common.DimensionManager import net.minecraftforge.common.DimensionManager
import net.minecraftforge.event.ForgeSubscribe import net.minecraftforge.event.ForgeSubscribe
import net.minecraftforge.event.world.{ChunkDataEvent, WorldEvent} import net.minecraftforge.event.world.{ChunkDataEvent, WorldEvent}
@ -24,6 +27,37 @@ object SaveHandler {
def statePath = new io.File(savePath, "state") def statePath = new io.File(savePath, "state")
def scheduleSave(owner: Owner, nbt: NBTTagCompound, name: String, data: Array[Byte]) {
scheduleSave(owner.world, owner.x, owner.z, nbt, name, data)
}
def scheduleSave(container: Container, nbt: NBTTagCompound, name: String, data: Array[Byte]) {
scheduleSave(container.world, math.round(container.xPosition - 0.5).toInt, math.round(container.zPosition - 0.5).toInt, nbt, name, data)
}
def scheduleSave(world: World, x: Int, z: Int, nbt: NBTTagCompound, name: String, data: Array[Byte]) {
val dimension = world.provider.dimensionId
val chunk = new ChunkCoordIntPair(x >> 4, z >> 4)
// We have to save the dimension and chunk coordinates, because they are
// not available on load / may have changed if the computer was moved.
nbt.setInteger("dimension", dimension)
nbt.setInteger("chunkX", chunk.chunkXPos)
nbt.setInteger("chunkZ", chunk.chunkZPos)
scheduleSave(dimension, chunk, name, data)
}
def load(nbt: NBTTagCompound, name: String): Array[Byte] = {
// Since we have no world yet, we rely on the dimension we were saved in.
// Same goes for the chunk. This also works around issues with computers
// being moved (e.g. Redstone in Motion).
val dimension = nbt.getInteger("dimension")
val chunk = new ChunkCoordIntPair(nbt.getInteger("chunkX"), nbt.getInteger("chunkZ"))
load(dimension, chunk, name)
}
def scheduleSave(dimension: Int, chunk: ChunkCoordIntPair, name: String, data: Array[Byte]) = saveData.synchronized { def scheduleSave(dimension: Int, chunk: ChunkCoordIntPair, name: String, data: Array[Byte]) = saveData.synchronized {
if (chunk == null) throw new IllegalArgumentException("chunk is null") if (chunk == null) throw new IllegalArgumentException("chunk is null")
else { else {

View File

@ -12,7 +12,6 @@ import li.cil.oc.util.ExtendedLuaState.extendLuaState
import li.cil.oc.util.LuaStateFactory import li.cil.oc.util.LuaStateFactory
import li.cil.oc.{OpenComputers, Settings, api} import li.cil.oc.{OpenComputers, Settings, api}
import net.minecraft.nbt.NBTTagCompound import net.minecraft.nbt.NBTTagCompound
import net.minecraft.world.ChunkCoordIntPair
class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architecture { class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architecture {
private[machine] var lua: LuaState = null private[machine] var lua: LuaState = null
@ -328,29 +327,14 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
// on. First, clear the stack, meaning the current kernel. // on. First, clear the stack, meaning the current kernel.
lua.setTop(0) lua.setTop(0)
// Since we have no world yet, we rely on the dimension we were saved in. persistence.unpersist(SaveHandler.load(nbt, machine.node.address + "_kernel"))
// Same goes for the chunk. This also works around issues with computers
// being moved (e.g. Redstone in Motion).
val dimension = nbt.getInteger("dimension")
val chunk =
if (nbt.hasKey("chunkX") && nbt.hasKey("chunkZ"))
new ChunkCoordIntPair(nbt.getInteger("chunkX"), nbt.getInteger("chunkZ"))
else
new ChunkCoordIntPair(machine.owner.x >> 4, machine.owner.z >> 4)
val kernel =
if (nbt.hasKey("kernel")) nbt.getByteArray("kernel")
else SaveHandler.load(dimension, chunk, machine.node.address + "_kernel")
persistence.unpersist(kernel)
if (!lua.isThread(1)) { if (!lua.isThread(1)) {
// This shouldn't really happen, but there's a chance it does if // This shouldn't really happen, but there's a chance it does if
// the save was corrupt (maybe someone modified the Lua files). // the save was corrupt (maybe someone modified the Lua files).
throw new LuaRuntimeException("Invalid kernel.") throw new LuaRuntimeException("Invalid kernel.")
} }
if (state.contains(Machine.State.SynchronizedCall) || state.contains(Machine.State.SynchronizedReturn)) { if (state.contains(Machine.State.SynchronizedCall) || state.contains(Machine.State.SynchronizedReturn)) {
val stack = persistence.unpersist(SaveHandler.load(nbt, machine.node.address + "_stack"))
if (nbt.hasKey("stack")) nbt.getByteArray("stack")
else SaveHandler.load(dimension, chunk, machine.node.address + "_stack")
persistence.unpersist(stack)
if (!(if (state.contains(Machine.State.SynchronizedCall)) lua.isFunction(2) else lua.isTable(2))) { if (!(if (state.contains(Machine.State.SynchronizedCall)) lua.isFunction(2) else lua.isTable(2))) {
// Same as with the above, should not really happen normally, but // Same as with the above, should not really happen normally, but
// could for the same reasons. // could for the same reasons.
@ -389,19 +373,12 @@ class NativeLuaArchitecture(val machine: api.machine.Machine) extends Architectu
// Save the kernel state (which is always at stack index one). // Save the kernel state (which is always at stack index one).
assert(lua.isThread(1)) assert(lua.isThread(1))
// We have to save the dimension and chunk coordinates, because they are SaveHandler.scheduleSave(machine.owner, nbt, machine.node.address + "_kernel", persistence.persist(1))
// not available on load / may have changed if the computer was moved.
val dimension = machine.owner.world.provider.dimensionId
val chunk = new ChunkCoordIntPair(machine.owner.x >> 4, machine.owner.z >> 4)
nbt.setInteger("dimension", dimension)
nbt.setInteger("chunkX", chunk.chunkXPos)
nbt.setInteger("chunkZ", chunk.chunkZPos)
SaveHandler.scheduleSave(dimension, chunk, machine.node.address + "_kernel", persistence.persist(1))
// While in a driver call we have one object on the global stack: either // While in a driver call we have one object on the global stack: either
// the function to call the driver with, or the result of the call. // the function to call the driver with, or the result of the call.
if (state.contains(Machine.State.SynchronizedCall) || state.contains(Machine.State.SynchronizedReturn)) { if (state.contains(Machine.State.SynchronizedCall) || state.contains(Machine.State.SynchronizedReturn)) {
assert(if (state.contains(Machine.State.SynchronizedCall)) lua.isFunction(2) else lua.isTable(2)) assert(if (state.contains(Machine.State.SynchronizedCall)) lua.isFunction(2) else lua.isTable(2))
SaveHandler.scheduleSave(dimension, chunk, machine.node.address + "_stack", persistence.persist(2)) SaveHandler.scheduleSave(machine.owner, nbt, machine.node.address + "_stack", persistence.persist(2))
} }
nbt.setInteger("kernelMemory", math.ceil(kernelMemory / ramScale).toInt) nbt.setInteger("kernelMemory", math.ceil(kernelMemory / ramScale).toInt)