diff --git a/src/net/torvald/terrarum/SavegameCollection.kt b/src/net/torvald/terrarum/SavegameCollection.kt index 9ed762484..098a4b55e 100644 --- a/src/net/torvald/terrarum/SavegameCollection.kt +++ b/src/net/torvald/terrarum/SavegameCollection.kt @@ -29,7 +29,7 @@ import kotlin.math.roundToInt class SavegameCollection(files0: List) { /** Sorted in reverse by the last modified time of the files, index zero being the most recent */ - val files = files0.sortedBy { it.diskFile.name }.sortedByDescending { + val files: List = files0.sortedBy { it.diskFile.name }.sortedByDescending { it.getLastModifiedTime().shl(2) or it.diskFile.extension.matches(Regex("^[abc]${'$'}")).toLong(1) or it.diskFile.extension.isBlank().toLong(0) diff --git a/src/net/torvald/terrarum/gameworld/ChunkPool.kt b/src/net/torvald/terrarum/gameworld/ChunkPool.kt index cd8c708b4..d88c6ba43 100644 --- a/src/net/torvald/terrarum/gameworld/ChunkPool.kt +++ b/src/net/torvald/terrarum/gameworld/ChunkPool.kt @@ -1,13 +1,16 @@ package net.torvald.terrarum.gameworld +import net.torvald.terrarum.App import net.torvald.terrarum.INGAME import net.torvald.terrarum.Point2i -import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.ClusteredFormatDOM import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.archivers.Clustfile import net.torvald.terrarum.realestate.LandUtil import net.torvald.terrarum.realestate.LandUtil.CHUNK_H import net.torvald.terrarum.realestate.LandUtil.CHUNK_W +import net.torvald.terrarum.savegame.DiskEntry +import net.torvald.terrarum.savegame.DiskSkimmer +import net.torvald.terrarum.savegame.EntryFile import net.torvald.terrarum.serialise.Common import net.torvald.terrarum.serialise.toUint import net.torvald.unsafe.UnsafeHelper @@ -37,7 +40,8 @@ enum class ChunkAllocClass { * Created by minjaesong on 2024-09-07. */ open class ChunkPool( - val DOM: ClusteredFormatDOM, + // `DiskSkimmer` or `ClusteredFormatDOM` + val disk: Any, val wordSizeInBytes: Long, val world: GameWorld, val chunkNumToFileNum: (Int) -> String, @@ -165,18 +169,47 @@ open class ChunkPool( } private fun fetchFromDisk(chunkNumber: Int) { - // read data from the disk val fileName = chunkNumToFileNum(chunkNumber) - Clustfile(DOM, fileName).let { - val bytes = Common.unzip(it.readBytes()) - val ptr = allocate(chunkNumber) - UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size) - renumber(ptr) + + // read data from the disk + if (disk is ClusteredFormatDOM) { + Clustfile(disk, fileName).let { + val bytes = Common.unzip(it.readBytes()) + val ptr = allocate(chunkNumber) + UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size) + renumber(ptr) + } + } + else if (disk is DiskSkimmer) { + val fileID = fileName.toLong() + disk.getFile(fileID)!!.let { + val bytes = Common.unzip(it.bytes) + val ptr = allocate(chunkNumber) + UnsafeHelper.memcpyFromArrToPtr(bytes, 0, ptr.ptr, bytes.size) + renumber(ptr) + } } } private fun storeToDisk(chunkNumber: Int) { - TODO() + val fileName = chunkNumToFileNum(chunkNumber) + + // write to the disk (the disk must be an autosaving copy of the original) + if (disk is ClusteredFormatDOM) { + Clustfile(disk, fileName).let { + val bytes = Common.zip(serialise(chunkNumber).iterator()) + it.overwrite(bytes.toByteArray()) + } + } + // append the new entry + else if (disk is DiskSkimmer) { + val fileID = fileName.toLong() + + val bytes = Common.zip(serialise(chunkNumber).iterator()) + val oldEntry = disk.getEntry(fileID) + val timeNow = App.getTIME_T() + disk.appendEntry(DiskEntry(fileID, 0L, oldEntry?.creationDate ?: timeNow, timeNow, EntryFile(bytes))) + } } private fun checkForChunk(chunkNumber: Int) { @@ -185,6 +218,14 @@ open class ChunkPool( } } + private fun serialise(chunkNumber: Int): ByteArray { + val ptr = pointers[chunkNumber]!! + val out = ByteArray(chunkSize.toInt()) + UnsafeHelper.memcpyFromPtrToArr(ptr, out, 0, chunkSize) + return out + } + + /** * Given the word-aligned byte sequence of `[B0, B1, B2, B3, ...]`, * Return format: diff --git a/src/net/torvald/terrarum/savegame/DiskSkimmer.kt b/src/net/torvald/terrarum/savegame/DiskSkimmer.kt index 91a56a8e7..1de79e410 100644 --- a/src/net/torvald/terrarum/savegame/DiskSkimmer.kt +++ b/src/net/torvald/terrarum/savegame/DiskSkimmer.kt @@ -26,6 +26,7 @@ class DiskSkimmer( noInit: Boolean = false ): SimpleFileSystem { + override fun getBackingFile() = diskFile /* diff --git a/src/net/torvald/unsafe/UnsafePtr.kt b/src/net/torvald/unsafe/UnsafePtr.kt index e7aceeb1b..79d01de87 100644 --- a/src/net/torvald/unsafe/UnsafePtr.kt +++ b/src/net/torvald/unsafe/UnsafePtr.kt @@ -50,6 +50,10 @@ internal object UnsafeHelper { unsafe.copyMemory(srcObj, getArrayOffset(srcObj) + startIndex, null, destPos, len.toLong()) fun memcpyFromArrToPtr(srcObj: Any, startIndex: Int, destPos: Long, len: Long) = unsafe.copyMemory(srcObj, getArrayOffset(srcObj) + startIndex, null, destPos, len) + fun memcpyFromPtrToArr(srcPos: Long, destObj: Any, startIndex: Int, len: Int) = + unsafe.copyMemory(null, srcPos, destObj, getArrayOffset(destObj) + startIndex, len.toLong()) + fun memcpyFromPtrToArr(srcPos: Long, destObj: Any, startIndex: Int, len: Long) = + unsafe.copyMemory(null, srcPos, destObj, getArrayOffset(destObj) + startIndex, len) /** * The array object in JVM is stored in this memory map: