mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-09 18:14:06 +09:00
fixes, bits and pieces, changes in ID referencing, terrain and wall takes damage, working test pickaxe, and a new issue
This commit is contained in:
@@ -94,7 +94,7 @@ internal class Filesystem(globals: Globals, computer: TerrarumComputer) {
|
||||
|
||||
path.dropMount()
|
||||
|
||||
return VDUtil.getFile(disk, path)?.file
|
||||
return VDUtil.getFile(disk, path)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,7 +201,7 @@ internal class Filesystem(globals: Globals, computer: TerrarumComputer) {
|
||||
if (file!!.contents is EntryFile)
|
||||
return LuaValue.valueOf(file.contents.getSizePure().toInt())
|
||||
else if (file.contents is EntryDirectory)
|
||||
return LuaValue.valueOf(file.contents.entries.size)
|
||||
return LuaValue.valueOf(file.contents.entryCount)
|
||||
}
|
||||
catch (e: KotlinNullPointerException) {
|
||||
}
|
||||
@@ -279,12 +279,12 @@ internal class Filesystem(globals: Globals, computer: TerrarumComputer) {
|
||||
|
||||
val file = VDUtil.getFile(disk1, pathFrom)!!
|
||||
try {
|
||||
VDUtil.addFile(disk2, pathTo.getParent(), file.file)
|
||||
VDUtil.addFile(disk2, pathTo.getParent(), file)
|
||||
}
|
||||
catch (e: FileNotFoundException) {
|
||||
// roll back delete on disk2
|
||||
if (oldFile != null) {
|
||||
VDUtil.addFile(disk2, oldFile.parent.entryID, oldFile.file)
|
||||
VDUtil.addFile(disk2, oldFile.parentEntryID, oldFile)
|
||||
throw FileNotFoundException("No such destination")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ object VDUtil {
|
||||
unsanitisedHierarchy.removeAt(0)
|
||||
// removes tail slash
|
||||
if (unsanitisedHierarchy.size > 0 &&
|
||||
unsanitisedHierarchy[unsanitisedHierarchy.lastIndex].isEmpty())
|
||||
unsanitisedHierarchy[unsanitisedHierarchy.lastIndex].isEmpty())
|
||||
unsanitisedHierarchy.removeAt(unsanitisedHierarchy.lastIndex)
|
||||
|
||||
unsanitisedHierarchy.forEach {
|
||||
@@ -202,7 +202,7 @@ object VDUtil {
|
||||
val calculatedCRC = diskEntry.hashCode()
|
||||
|
||||
val crcMsg = "CRC failed: expected ${entryCRC.toHex()}, got ${calculatedCRC.toHex()}\n" +
|
||||
"at file \"${diskEntry.getFilenameString(charset)}\" (entry ID ${diskEntry.entryID})"
|
||||
"at file \"${diskEntry.getFilenameString(charset)}\" (entry ID ${diskEntry.entryID})"
|
||||
|
||||
if (calculatedCRC != entryCRC) {
|
||||
if (crcWarnLevel == Level.SEVERE)
|
||||
@@ -243,7 +243,7 @@ object VDUtil {
|
||||
throw IllegalArgumentException("The entry is not directory")
|
||||
|
||||
val entriesList = ArrayList<DiskEntry>()
|
||||
dirToSearch.contents.entries.forEach {
|
||||
dirToSearch.contents.forEach {
|
||||
val entry = disk.entries[it]
|
||||
if (entry != null) entriesList.add(entry)
|
||||
}
|
||||
@@ -267,7 +267,7 @@ object VDUtil {
|
||||
* Search a entry using path
|
||||
* @return Pair of <The file, Parent file>, or null if not found
|
||||
*/
|
||||
fun getFile(disk: VirtualDisk, path: VDPath): EntrySearchResult? {
|
||||
fun getFile(disk: VirtualDisk, path: VDPath): DiskEntry? {
|
||||
val searchHierarchy = ArrayList<DiskEntry>()
|
||||
fun getCurrentEntry(): DiskEntry = searchHierarchy.last()
|
||||
//var currentDirectory = disk.root
|
||||
@@ -276,10 +276,7 @@ object VDUtil {
|
||||
|
||||
// path of root
|
||||
if (path.hierarchy.size == 0) {
|
||||
return EntrySearchResult(
|
||||
disk.entries[0]!!,
|
||||
disk.entries[0]!!
|
||||
)
|
||||
return disk.entries[0]!!
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -310,10 +307,7 @@ object VDUtil {
|
||||
}
|
||||
|
||||
// file found
|
||||
return EntrySearchResult(
|
||||
searchHierarchy[searchHierarchy.lastIndex],
|
||||
searchHierarchy[searchHierarchy.lastIndex - 1]
|
||||
)
|
||||
return searchHierarchy[searchHierarchy.lastIndex]
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -323,12 +317,12 @@ object VDUtil {
|
||||
*/
|
||||
private fun DiskEntry.getAsNormalFile(disk: VirtualDisk): EntryFile =
|
||||
this.contents as? EntryFile ?:
|
||||
if (this.contents is EntryDirectory)
|
||||
throw RuntimeException("this is directory")
|
||||
else if (this.contents is EntrySymlink)
|
||||
disk.entries[this.contents.target]!!.getAsNormalFile(disk)
|
||||
else
|
||||
throw RuntimeException("Unknown entry type")
|
||||
if (this.contents is EntryDirectory)
|
||||
throw RuntimeException("this is directory")
|
||||
else if (this.contents is EntrySymlink)
|
||||
disk.entries[this.contents.target]!!.getAsNormalFile(disk)
|
||||
else
|
||||
throw RuntimeException("Unknown entry type")
|
||||
/**
|
||||
* SYNOPSIS disk.getFile("bin/msh.lua")!!.first.getAsNormalFile(disk)
|
||||
*
|
||||
@@ -336,18 +330,18 @@ object VDUtil {
|
||||
*/
|
||||
private fun DiskEntry.getAsDirectory(disk: VirtualDisk): EntryDirectory =
|
||||
this.contents as? EntryDirectory ?:
|
||||
if (this.contents is EntrySymlink)
|
||||
disk.entries[this.contents.target]!!.getAsDirectory(disk)
|
||||
else if (this.contents is EntryFile)
|
||||
throw RuntimeException("this is not directory")
|
||||
else
|
||||
throw RuntimeException("Unknown entry type")
|
||||
if (this.contents is EntrySymlink)
|
||||
disk.entries[this.contents.target]!!.getAsDirectory(disk)
|
||||
else if (this.contents is EntryFile)
|
||||
throw RuntimeException("this is not directory")
|
||||
else
|
||||
throw RuntimeException("Unknown entry type")
|
||||
|
||||
/**
|
||||
* Search for the file and returns a instance of normal file.
|
||||
*/
|
||||
fun getAsNormalFile(disk: VirtualDisk, path: VDPath) =
|
||||
getFile(disk, path)!!.file.getAsNormalFile(disk)
|
||||
getFile(disk, path)!!.getAsNormalFile(disk)
|
||||
/**
|
||||
* Fetch the file and returns a instance of normal file.
|
||||
*/
|
||||
@@ -357,7 +351,7 @@ object VDUtil {
|
||||
* Search for the file and returns a instance of directory.
|
||||
*/
|
||||
fun getAsDirectory(disk: VirtualDisk, path: VDPath) =
|
||||
getFile(disk, path)!!.file.getAsDirectory(disk)
|
||||
getFile(disk, path)!!.getAsDirectory(disk)
|
||||
/**
|
||||
* Fetch the file and returns a instance of directory.
|
||||
*/
|
||||
@@ -367,11 +361,8 @@ object VDUtil {
|
||||
* Deletes file on the disk safely.
|
||||
*/
|
||||
fun deleteFile(disk: VirtualDisk, path: VDPath) {
|
||||
disk.checkReadOnly()
|
||||
|
||||
val fileSearchResult = getFile(disk, path)!!
|
||||
|
||||
return deleteFile(disk, fileSearchResult.file.entryID)
|
||||
return deleteFile(disk, fileSearchResult.entryID)
|
||||
}
|
||||
/**
|
||||
* Deletes file on the disk safely.
|
||||
@@ -386,29 +377,25 @@ object VDUtil {
|
||||
}
|
||||
|
||||
val parentID = file.parentEntryID
|
||||
val parentDir = disk.entries[parentID]
|
||||
val parentDir = getAsDirectory(disk, parentID)
|
||||
|
||||
fun rollback() {
|
||||
if (!disk.entries.contains(targetID)) {
|
||||
disk.entries[targetID] = file
|
||||
}
|
||||
if (!(parentDir!!.contents as EntryDirectory).entries.contains(targetID)) {
|
||||
(parentDir.contents as EntryDirectory).entries.add(targetID)
|
||||
if (!parentDir.contains(targetID)) {
|
||||
parentDir.add(targetID)
|
||||
}
|
||||
}
|
||||
|
||||
if (parentDir == null || parentDir.contents !is EntryDirectory) {
|
||||
throw FileNotFoundException("No such parent directory")
|
||||
}
|
||||
// check if directory "parentID" has "targetID" in the first place
|
||||
else if (!directoryContains(disk, parentID, targetID)) {
|
||||
if (!directoryContains(disk, parentID, targetID)) {
|
||||
throw FileNotFoundException("No such file to delete")
|
||||
}
|
||||
else if (targetID == 0) {
|
||||
throw IOException("Cannot delete root file system")
|
||||
}
|
||||
else if (file.contents is EntryDirectory && file.contents.entries.size > 0) {
|
||||
//throw IOException("Cannot delete directory that contains something")
|
||||
else if (file.contents is EntryDirectory && file.contents.entryCount > 0) {
|
||||
deleteDirRecurse(disk, targetID)
|
||||
}
|
||||
else {
|
||||
@@ -416,7 +403,7 @@ object VDUtil {
|
||||
// delete file record
|
||||
disk.entries.remove(targetID)
|
||||
// unlist file from parent directly
|
||||
(disk.entries[parentID]!!.contents as EntryDirectory).entries.remove(targetID)
|
||||
parentDir.remove(targetID)
|
||||
}
|
||||
catch (e: Exception) {
|
||||
rollback()
|
||||
@@ -428,7 +415,7 @@ object VDUtil {
|
||||
* Changes the name of the entry.
|
||||
*/
|
||||
fun renameFile(disk: VirtualDisk, path: VDPath, newName: String, charset: Charset) {
|
||||
val file = getFile(disk, path)?.file
|
||||
val file = getFile(disk, path)
|
||||
|
||||
if (file != null) {
|
||||
file.filename = newName.sanitisePath().toEntryName(DiskEntry.NAME_LENGTH, charset)
|
||||
@@ -451,23 +438,12 @@ object VDUtil {
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Add file to the specified directory. ParentID of the file will be overwritten.
|
||||
* Add file to the specified directory.
|
||||
* The file will get new EntryID and its ParentID will be overwritten.
|
||||
*/
|
||||
fun addFile(disk: VirtualDisk, parentPath: VDPath, file: DiskEntry) {
|
||||
disk.checkReadOnly()
|
||||
disk.checkCapacity(file.serialisedSize)
|
||||
|
||||
try {
|
||||
val parentID = getFile(disk, parentPath)!!.file.entryID
|
||||
// add record to the directory
|
||||
getAsDirectory(disk, parentPath).entries.add(file.entryID)
|
||||
// add entry on the disk
|
||||
disk.entries[file.entryID] = file
|
||||
file.parentEntryID = parentID
|
||||
}
|
||||
catch (e: KotlinNullPointerException) {
|
||||
throw FileNotFoundException("No such directory")
|
||||
}
|
||||
val targetDirID = getFile(disk, parentPath)!!.entryID
|
||||
return addFile(disk, targetDirID, file)
|
||||
}
|
||||
/**
|
||||
* Add file to the specified directory. ParentID of the file will be overwritten.
|
||||
@@ -477,10 +453,13 @@ object VDUtil {
|
||||
disk.checkCapacity(file.serialisedSize)
|
||||
|
||||
try {
|
||||
// generate new ID for the file
|
||||
file.entryID = disk.generateUniqueID()
|
||||
// add record to the directory
|
||||
getAsDirectory(disk, directoryID).entries.add(file.entryID)
|
||||
getAsDirectory(disk, directoryID).add(file.entryID)
|
||||
// add entry on the disk
|
||||
disk.entries[file.entryID] = file
|
||||
// make this boy recognise his new parent
|
||||
file.parentEntryID = directoryID
|
||||
}
|
||||
catch (e: KotlinNullPointerException) {
|
||||
@@ -491,28 +470,8 @@ object VDUtil {
|
||||
* Add subdirectory to the specified directory.
|
||||
*/
|
||||
fun addDir(disk: VirtualDisk, parentPath: VDPath, name: ByteArray) {
|
||||
disk.checkReadOnly()
|
||||
disk.checkCapacity(EntryDirectory.NEW_ENTRY_SIZE)
|
||||
|
||||
val newID = disk.generateUniqueID()
|
||||
|
||||
try {
|
||||
val parentID = getFile(disk, parentPath)!!.file.entryID
|
||||
// add record to the directory
|
||||
getAsDirectory(disk, parentPath).entries.add(newID)
|
||||
// add entry on the disk
|
||||
disk.entries[newID] = DiskEntry(
|
||||
newID,
|
||||
parentID,
|
||||
name,
|
||||
currentUnixtime,
|
||||
currentUnixtime,
|
||||
EntryDirectory()
|
||||
)
|
||||
}
|
||||
catch (e: KotlinNullPointerException) {
|
||||
throw FileNotFoundException("No such directory")
|
||||
}
|
||||
val parentID = getFile(disk, parentPath)!!.entryID
|
||||
return addDir(disk, parentID, name)
|
||||
}
|
||||
/**
|
||||
* Add file to the specified directory.
|
||||
@@ -525,7 +484,7 @@ object VDUtil {
|
||||
|
||||
try {
|
||||
// add record to the directory
|
||||
getAsDirectory(disk, directoryID).entries.add(newID)
|
||||
getAsDirectory(disk, directoryID).add(newID)
|
||||
// add entry on the disk
|
||||
disk.entries[newID] = DiskEntry(
|
||||
newID,
|
||||
@@ -553,7 +512,7 @@ object VDUtil {
|
||||
}
|
||||
// recurse
|
||||
else {
|
||||
entry.contents.entries.forEach {
|
||||
entry.contents.forEach {
|
||||
entriesToDelete.add(entry.entryID)
|
||||
recurse1(disk.entries[it])
|
||||
}
|
||||
@@ -562,7 +521,7 @@ object VDUtil {
|
||||
|
||||
val entry = disk.entries[directoryID]
|
||||
if (entry != null && entry.contents is EntryDirectory) {
|
||||
entry.contents.entries.forEach {
|
||||
entry.contents.forEach {
|
||||
entriesToDelete.add(directoryID)
|
||||
recurse1(disk.entries[it])
|
||||
}
|
||||
@@ -630,12 +589,10 @@ object VDUtil {
|
||||
fun moveFile(disk1: VirtualDisk, fromPath: VDPath, disk2: VirtualDisk, toPath: VDPath) {
|
||||
val file = getFile(disk1, fromPath)
|
||||
|
||||
if (file != null) {
|
||||
if (file.file.contents is EntryDirectory) {
|
||||
throw IOException("Cannot move directory")
|
||||
}
|
||||
// checking readOnly is redundant here
|
||||
|
||||
disk2.checkCapacity(file.file.contents.getSizeEntry())
|
||||
if (file != null) {
|
||||
disk2.checkCapacity(file.contents.getSizeEntry())
|
||||
|
||||
try {
|
||||
deleteFile(disk2, toPath)
|
||||
@@ -644,11 +601,11 @@ object VDUtil {
|
||||
|
||||
deleteFile(disk1, fromPath) // any uncaught no_from_file will be caught here
|
||||
try {
|
||||
addFile(disk2, toPath.getParent(), file.file)
|
||||
addFile(disk2, toPath.getParent(), file)
|
||||
}
|
||||
catch (e: FileNotFoundException) {
|
||||
// roll back delete on disk1
|
||||
addFile(disk1, file.parent.entryID, file.file)
|
||||
addFile(disk1, file.parentEntryID, file)
|
||||
throw FileNotFoundException("No such destination")
|
||||
}
|
||||
}
|
||||
@@ -740,7 +697,6 @@ object VDUtil {
|
||||
val path1 = this.replace('\\', '/')
|
||||
return path1
|
||||
}
|
||||
data class EntrySearchResult(val file: DiskEntry, val parent: DiskEntry)
|
||||
|
||||
fun resolveIfSymlink(disk: VirtualDisk, indexNumber: EntryID, recurse: Boolean = false): DiskEntry {
|
||||
var entry: DiskEntry? = disk.entries[indexNumber]
|
||||
@@ -769,7 +725,7 @@ object VDUtil {
|
||||
throw FileNotFoundException("Not a directory")
|
||||
}
|
||||
else {
|
||||
return dir.contents.entries.contains(targetID)
|
||||
return dir.contents.contains(targetID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -784,11 +740,16 @@ object VDUtil {
|
||||
return disk.entries.filter { disk.entries[it.value.parentEntryID] == null }.keys.toList()
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for null-pointing entries (phantoms) within every directory.
|
||||
*
|
||||
* @return List of search results, which is Pair(directory that contains null pointer, null pointer)
|
||||
*/
|
||||
fun gcSearchPhantomBaby(disk: VirtualDisk): List<Pair<EntryID, EntryID>> {
|
||||
// Pair<DirectoryID, ID of phantom in the directory>
|
||||
val phantoms = ArrayList<Pair<EntryID, EntryID>>()
|
||||
disk.entries.filter { it.value.contents is EntryDirectory }.values.forEach { directory ->
|
||||
(directory.contents as EntryDirectory).entries.forEach { dirEntryID ->
|
||||
(directory.contents as EntryDirectory).forEach { dirEntryID ->
|
||||
if (disk.entries[dirEntryID] == null) {
|
||||
phantoms.add(Pair(directory.entryID, dirEntryID))
|
||||
}
|
||||
@@ -811,7 +772,7 @@ object VDUtil {
|
||||
fun gcDumpAll(disk: VirtualDisk) {
|
||||
try {
|
||||
gcSearchPhantomBaby(disk).forEach {
|
||||
getAsDirectory(disk, it.first).entries.remove(it.second)
|
||||
getAsDirectory(disk, it.first).remove(it.second)
|
||||
}
|
||||
gcSearchOrphan(disk).forEach {
|
||||
disk.entries.remove(it)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.torvald.terrarum.virtualcomputer.tvd
|
||||
|
||||
import java.io.IOException
|
||||
import java.nio.charset.Charset
|
||||
import java.util.*
|
||||
import java.util.function.Consumer
|
||||
@@ -182,10 +183,30 @@ class EntryFile(var bytes: ByteArray64) : DiskEntryContent {
|
||||
return buffer
|
||||
}
|
||||
}
|
||||
class EntryDirectory(val entries: ArrayList<EntryID> = ArrayList<EntryID>()) : DiskEntryContent {
|
||||
class EntryDirectory(private val entries: ArrayList<EntryID> = ArrayList<EntryID>()) : DiskEntryContent {
|
||||
|
||||
override fun getSizePure() = entries.size * 4L
|
||||
override fun getSizeEntry() = getSizePure() + 2
|
||||
private fun checkCapacity(toAdd: Int = 1) {
|
||||
if (entries.size + toAdd > 65535)
|
||||
throw IOException("Directory entries limit exceeded.")
|
||||
}
|
||||
|
||||
fun add(entryID: EntryID) {
|
||||
checkCapacity()
|
||||
entries.add(entryID)
|
||||
}
|
||||
|
||||
fun remove(entryID: EntryID) {
|
||||
entries.removeAt(entryID)
|
||||
}
|
||||
|
||||
fun contains(entryID: EntryID) = entries.contains(entryID)
|
||||
|
||||
fun forEach(consumer: (EntryID) -> Unit) = entries.forEach(consumer)
|
||||
|
||||
val entryCount: Int
|
||||
get() = entries.size
|
||||
|
||||
override fun serialize(): AppendableByteBuffer {
|
||||
val buffer = AppendableByteBuffer(getSizeEntry())
|
||||
|
||||
Reference in New Issue
Block a user