| package li.cil.oc.common |
| |
| import java.io |
| import java.util.logging.Level |
| import li.cil.oc.{OpenComputers, Settings} |
| import net.minecraft.world.ChunkCoordIntPair |
| import net.minecraftforge.common.DimensionManager |
| import net.minecraftforge.event.ForgeSubscribe |
| import net.minecraftforge.event.world.{ChunkDataEvent, WorldEvent} |
| import scala.collection.mutable |
| |
| // Used by the native lua state to store kernel and stack data in auxiliary |
| // files instead of directly in the tile entity data, avoiding potential |
| // problems with the tile entity data becoming too large. |
| object SaveHandler { |
| val saveData = mutable.Map.empty[ChunkCoordIntPair, mutable.Map[String, Array[Byte]]] |
| |
| def savePath = new io.File(DimensionManager.getCurrentSaveRootDirectory, Settings.savePath + "state") |
| |
| def scheduleSave(chunk: ChunkCoordIntPair, name: String, data: Array[Byte]) = saveData.synchronized { |
| if (chunk == null) throw new IllegalArgumentException("chunk is null") |
| else saveData.getOrElseUpdate(chunk, mutable.Map.empty[String, Array[Byte]]) += name -> data |
| } |
| |
| def load(chunk: ChunkCoordIntPair, name: String): Array[Byte] = { |
| if (chunk == null) throw new IllegalArgumentException("chunk is null") |
| val path = savePath |
| val chunkPath = new io.File(path, s"${chunk.chunkXPos}.${chunk.chunkZPos}") |
| val file = new io.File(chunkPath, name) |
| try { |
| // val bis = new io.BufferedInputStream(new GZIPInputStream(new io.FileInputStream(file))) |
| val bis = new io.BufferedInputStream(new io.FileInputStream(file)) |
| val bos = new io.ByteArrayOutputStream |
| val buffer = new Array[Byte](8 * 1024) |
| var read = 0 |
| do { |
| read = bis.read(buffer) |
| if (read > 0) { |
| bos.write(buffer, 0, read) |
| } |
| } while (read >= 0) |
| bis.close() |
| bos.toByteArray |
| } |
| catch { |
| case e: io.IOException => |
| OpenComputers.log.log(Level.WARNING, "Error loading auxiliary tile entity data.", e) |
| Array.empty[Byte] |
| } |
| } |
| |
| @ForgeSubscribe |
| def onChunkSave(e: ChunkDataEvent.Save) = saveData.synchronized { |
| val path = savePath |
| val chunk = e.getChunk.getChunkCoordIntPair |
| val chunkPath = new io.File(path, s"${chunk.chunkXPos}.${chunk.chunkZPos}") |
| if (chunkPath.exists && chunkPath.isDirectory) { |
| for (file <- chunkPath.listFiles()) file.delete() |
| } |
| saveData.get(chunk) match { |
| case Some(entries) => |
| chunkPath.mkdirs() |
| for ((name, data) <- entries) { |
| val file = new io.File(chunkPath, name) |
| try { |
| // val fos = new GZIPOutputStream(new io.FileOutputStream(file)) |
| val fos = new io.BufferedOutputStream(new io.FileOutputStream(file)) |
| fos.write(data) |
| fos.close() |
| } |
| catch { |
| case e: io.IOException => OpenComputers.log.log(Level.WARNING, s"Error saving auxiliary tile entity data to '${file.getAbsolutePath}.", e) |
| } |
| } |
| case _ => chunkPath.delete() |
| } |
| } |
| |
| @ForgeSubscribe |
| def onWorldSave(e: WorldEvent.Save) = saveData.synchronized { |
| saveData.clear() |
| } |
| } |