mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-13 03:54:06 +09:00
working filesystem (tested: mkdir, open, file:writeLine/close, cp, mv, rm)
Former-commit-id: ce3fcae801291f770ed19dce4616b8ab61556f9b Former-commit-id: 999d637fac1c1c6a9ff855ebb8f7f37336519771
This commit is contained in:
Binary file not shown.
Binary file not shown.
@@ -100,14 +100,14 @@ constructor(gamename: String) : StateBasedGame(gamename) {
|
|||||||
|
|
||||||
gc.graphics.clear() // clean up any 'dust' in the buffer
|
gc.graphics.clear() // clean up any 'dust' in the buffer
|
||||||
|
|
||||||
//addState(StateVTTest())
|
addState(StateVTTest())
|
||||||
//addState(StateTestingSandbox())
|
//addState(StateTestingSandbox())
|
||||||
//addState(StateSplash())
|
//addState(StateSplash())
|
||||||
//addState(StateMonitorCheck())
|
//addState(StateMonitorCheck())
|
||||||
//addState(StateFontTester())
|
//addState(StateFontTester())
|
||||||
|
|
||||||
ingame = StateInGame()
|
//ingame = StateInGame()
|
||||||
addState(ingame)
|
//addState(ingame)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -412,6 +412,9 @@ constructor(gamename: String) : StateBasedGame(gamename) {
|
|||||||
}
|
}
|
||||||
return cfg!!
|
return cfg!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val currentSaveDir: File
|
||||||
|
get() = File(defaultSaveDir + "/test") // TODO TEST CODE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import net.torvald.spriteanimation.SpriteAnimation
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 16-06-17.
|
* Created by minjaesong on 16-06-17.
|
||||||
*/
|
*/
|
||||||
open class FixturesBase : ActorWithBody() {
|
open class FixtureBase : ActorWithBody() {
|
||||||
/**
|
/**
|
||||||
* 0: Open
|
* 0: Open
|
||||||
* 1: Blocked
|
* 1: Blocked
|
||||||
@@ -8,7 +8,7 @@ import java.util.*
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 16-06-17.
|
* Created by minjaesong on 16-06-17.
|
||||||
*/
|
*/
|
||||||
class FixturesTikiTorch : FixturesBase(), Luminous {
|
class FixtureTikiTorch : FixtureBase(), Luminous {
|
||||||
|
|
||||||
override var luminosity: Int
|
override var luminosity: Int
|
||||||
get() = TilePropCodex.getProp(TileNameCode.TORCH).luminosity
|
get() = TilePropCodex.getProp(TileNameCode.TORCH).luminosity
|
||||||
@@ -133,14 +133,14 @@ local function cHexToInt(c)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- str, str, str
|
-- str, str, str
|
||||||
term.blit = function(text, foreCol, backCol)
|
term.blit = function(text, foreCol, backCol)
|
||||||
assert(
|
assert(
|
||||||
type(text) == "string" and type(backCol) == "string" and type(foreCol) == "string",
|
type(text) == "string" and type(backCol) == "string" and type(foreCol) == "string",
|
||||||
"bad argument: (string, string, string expected, got "..type(text)..", "..type(foreCol)..", "..type(backCol)..")"
|
"bad argument: (string, string, string expected, got "..type(text)..", "..type(foreCol)..", "..type(backCol)..")"
|
||||||
)
|
)
|
||||||
if #text ~= #foreCol or #text ~= #backCol or #foreCol ~= #backCol then
|
if #text ~= #foreCol or #text ~= #backCol or #foreCol ~= #backCol then
|
||||||
error("rrguments must be the same length")
|
error("arguments must be the same length")
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1, #text do
|
for i = 1, #text do
|
||||||
@@ -162,7 +162,20 @@ term.setBackgroundColor = function(cccol) term.setBackCol(ccToGameCol[normaliseC
|
|||||||
term.getBackgroundColor = function() return term.getBackCol() end
|
term.getBackgroundColor = function() return term.getBackCol() end
|
||||||
|
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
-- FILESYSTEM API --
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
fs.makeDir = function(p) fs.mkdir(p) end
|
||||||
|
fs.move = function(a, b) fs.mv(a, b) end
|
||||||
|
fs.copy = function(a, b) fs.cp(a, b) end
|
||||||
|
fs.delete = function(p) fs.rm(p) end
|
||||||
|
fs.combine = function(a, b) return fs.concat(a, b) end
|
||||||
|
fs.getDir = function(p) return fs.parent(p) end
|
||||||
|
|
||||||
|
|
||||||
|
------------------
|
||||||
|
-- DOWN AND OUT --
|
||||||
|
------------------
|
||||||
|
|
||||||
if _COMPUTER.verbose then print("ComputerCraft compatibility layer successfully loaded.") end
|
if _COMPUTER.verbose then print("ComputerCraft compatibility layer successfully loaded.") end
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ require("ROMLIB")
|
|||||||
|
|
||||||
-- load bios, if any
|
-- load bios, if any
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- load Lua prompt, if bios is not found
|
-- load Lua prompt, if bios is not found
|
||||||
print("Rom basic " .. _COMPUTER.DC2 .. _VERSION .. _COMPUTER.DC4)
|
print("Rom basic " .. _COMPUTER.DC2 .. _VERSION .. _COMPUTER.DC4)
|
||||||
-- print(_COMPUTER.DC2 .. freemem .. _COMPUTER.DC4 .. " bytes free"
|
-- print(_COMPUTER.DC2 .. freemem .. _COMPUTER.DC4 .. " bytes free"
|
||||||
|
|||||||
@@ -4,19 +4,24 @@ import li.cil.repack.org.luaj.vm2.Globals
|
|||||||
import li.cil.repack.org.luaj.vm2.LuaError
|
import li.cil.repack.org.luaj.vm2.LuaError
|
||||||
import li.cil.repack.org.luaj.vm2.LuaValue
|
import li.cil.repack.org.luaj.vm2.LuaValue
|
||||||
import li.cil.repack.org.luaj.vm2.lib.jse.JsePlatform
|
import li.cil.repack.org.luaj.vm2.lib.jse.JsePlatform
|
||||||
import net.torvald.terrarum.virtualcomputer.lualib.TermLib
|
import net.torvald.terrarum.KVHashMap
|
||||||
|
import net.torvald.terrarum.gameactors.ActorValue
|
||||||
|
import net.torvald.terrarum.virtualcomputer.luaapi.Filesystem
|
||||||
|
import net.torvald.terrarum.virtualcomputer.luaapi.Term
|
||||||
import net.torvald.terrarum.virtualcomputer.terminal.*
|
import net.torvald.terrarum.virtualcomputer.terminal.*
|
||||||
|
import net.torvald.terrarum.virtualcomputer.worldobject.FixtureComputerBase
|
||||||
import org.newdawn.slick.GameContainer
|
import org.newdawn.slick.GameContainer
|
||||||
import java.io.*
|
import java.io.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A part that makes "computer fixtures" actually work
|
* A part that makes "computer fixture" actually work
|
||||||
|
*
|
||||||
|
* @param avFixtureComputer : actor values for FixtureComputerBase
|
||||||
*
|
*
|
||||||
* @param term : terminal that is connected to the computer fixtures, null if not connected any.
|
* @param term : terminal that is connected to the computer fixtures, null if not connected any.
|
||||||
*
|
|
||||||
* Created by minjaesong on 16-09-10.
|
* Created by minjaesong on 16-09-10.
|
||||||
*/
|
*/
|
||||||
class BaseTerrarumComputer(term: Teletype?) {
|
class BaseTerrarumComputer(term: Teletype? = null) {
|
||||||
|
|
||||||
val luaJ_globals: Globals = JsePlatform.standardGlobals()
|
val luaJ_globals: Globals = JsePlatform.standardGlobals()
|
||||||
|
|
||||||
@@ -27,7 +32,35 @@ class BaseTerrarumComputer(term: Teletype?) {
|
|||||||
var termIn: InputStream? = null
|
var termIn: InputStream? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
val UUID = "testsession"//java.util.UUID.randomUUID().toString()
|
||||||
|
|
||||||
|
val computerValue = KVHashMap()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
computerValue["memslot0"] = -1 // -1 indicates mem slot is empty
|
||||||
|
computerValue["memslot1"] = -1 // put index of item here
|
||||||
|
computerValue["memslot2"] = -1 // ditto.
|
||||||
|
computerValue["memslot3"] = -1 // do.
|
||||||
|
|
||||||
|
computerValue["processor"] = -1 // do.
|
||||||
|
|
||||||
|
// as in "dev/hda"; refers hard disk drive (and no partitioning)
|
||||||
|
computerValue["hda"] = "testhda" // 'UUID rendered as String' or "none"
|
||||||
|
computerValue["hdb"] = "none"
|
||||||
|
computerValue["hdc"] = "none"
|
||||||
|
computerValue["hdd"] = "none"
|
||||||
|
// as in "dev/fd1"; refers floppy disk drive
|
||||||
|
computerValue["fd1"] = "none"
|
||||||
|
computerValue["fd2"] = "none"
|
||||||
|
computerValue["fd3"] = "none"
|
||||||
|
computerValue["fd4"] = "none"
|
||||||
|
// SCSI connected optical drive
|
||||||
|
computerValue["sda"] = "none"
|
||||||
|
|
||||||
|
// boot device
|
||||||
|
computerValue["boot"] = computerValue.getAsString("hda")!!
|
||||||
|
|
||||||
|
|
||||||
if (term != null) {
|
if (term != null) {
|
||||||
termOut = TerminalPrintStream(term)
|
termOut = TerminalPrintStream(term)
|
||||||
termErr = TerminalPrintStream(term)
|
termErr = TerminalPrintStream(term)
|
||||||
@@ -38,7 +71,8 @@ class BaseTerrarumComputer(term: Teletype?) {
|
|||||||
luaJ_globals.STDIN = termIn
|
luaJ_globals.STDIN = termIn
|
||||||
|
|
||||||
// load libraries
|
// load libraries
|
||||||
TermLib(luaJ_globals, term)
|
Term(luaJ_globals, term)
|
||||||
|
Filesystem(luaJ_globals, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ROM BASIC
|
// ROM BASIC
|
||||||
|
|||||||
390
src/net/torvald/terrarum/virtualcomputer/luaapi/Filesystem.kt
Normal file
390
src/net/torvald/terrarum/virtualcomputer/luaapi/Filesystem.kt
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
package net.torvald.terrarum.virtualcomputer.luaapi
|
||||||
|
|
||||||
|
import li.cil.repack.org.luaj.vm2.*
|
||||||
|
import li.cil.repack.org.luaj.vm2.lib.OneArgFunction
|
||||||
|
import li.cil.repack.org.luaj.vm2.lib.TwoArgFunction
|
||||||
|
import li.cil.repack.org.luaj.vm2.lib.ZeroArgFunction
|
||||||
|
import net.torvald.terrarum.Terrarum
|
||||||
|
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
|
||||||
|
import java.io.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* computer directory:
|
||||||
|
* .../computers/
|
||||||
|
* media/hda/ -> .../computers/<uuid for the hda>/
|
||||||
|
*
|
||||||
|
* Created by minjaesong on 16-09-17.
|
||||||
|
*/
|
||||||
|
internal class Filesystem(globals: Globals, computer: BaseTerrarumComputer) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
// load things. WARNING: THIS IS MANUAL!
|
||||||
|
globals["fs"] = LuaValue.tableOf()
|
||||||
|
globals["fs"]["list"] = ListFiles(computer)
|
||||||
|
globals["fs"]["exists"] = FileExists(computer)
|
||||||
|
globals["fs"]["isDir"] = IsDirectory(computer)
|
||||||
|
globals["fs"]["isReadOnly"] = IsReadOnly(computer)
|
||||||
|
globals["fs"]["listFiles"] = ListFiles(computer)
|
||||||
|
globals["fs"]["mkdir"] = Mkdir(computer)
|
||||||
|
globals["fs"]["mv"] = Mv(computer)
|
||||||
|
globals["fs"]["cp"] = Cp(computer)
|
||||||
|
globals["fs"]["rm"] = Rm(computer)
|
||||||
|
globals["fs"]["concat"] = ConcatPath(computer)
|
||||||
|
globals["fs"]["open"] = OpenFile(computer)
|
||||||
|
globals["fs"]["parent"] = GetParentDir(computer)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val isCaseInsensitive: Boolean
|
||||||
|
get() {
|
||||||
|
// TODO add: force case insensitive in config
|
||||||
|
try {
|
||||||
|
val uuid = UUID.randomUUID().toString()
|
||||||
|
val lowerCase = File(Terrarum.currentSaveDir, uuid + "oc_rox")
|
||||||
|
val upperCase = File(Terrarum.currentSaveDir, uuid + "OC_ROX")
|
||||||
|
// This should NEVER happen but could also lead to VERY weird bugs, so we
|
||||||
|
// make sure the files don't exist.
|
||||||
|
lowerCase.exists() && lowerCase.delete()
|
||||||
|
upperCase.exists() && upperCase.delete()
|
||||||
|
lowerCase.createNewFile()
|
||||||
|
val insensitive = upperCase.exists()
|
||||||
|
lowerCase.delete()
|
||||||
|
return insensitive
|
||||||
|
}
|
||||||
|
catch (e: IOException) {
|
||||||
|
println("[Filesystem] Couldn't determine if file system is case sensitive, falling back to insensitive.")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Worst-case: we're on Windows or using a FAT32 partition mounted in *nix.
|
||||||
|
// Note: we allow / as the path separator and expect all \s to be converted
|
||||||
|
// accordingly before the path is passed to the file system.
|
||||||
|
private val invalidChars = Regex("""[\\:*?"<>|]""") // original OC uses Set(); we use regex
|
||||||
|
|
||||||
|
fun isValidFilename(name: String) = !name.contains(invalidChars)
|
||||||
|
|
||||||
|
fun validatePath(path: String): String {
|
||||||
|
if (!isValidFilename(path)) {
|
||||||
|
throw IOException("path contains invalid characters")
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
/** actual directory: <appdata>/Saves/<savename>/computers/<drivename>/
|
||||||
|
* directs media/ directory to /<uuid> directory
|
||||||
|
*/
|
||||||
|
fun BaseTerrarumComputer.getRealPath(luapath: LuaValue): String {
|
||||||
|
// direct mounted paths to real path
|
||||||
|
val computerDir = Terrarum.currentSaveDir.absolutePath + "/computers/"
|
||||||
|
/* if not begins with "(/?)media/", direct to boot
|
||||||
|
* else, to corresponding drives
|
||||||
|
*
|
||||||
|
* List of device names (these are auto-mounted. why? primitivism :p):
|
||||||
|
* = hda - hdd: hard disks
|
||||||
|
* = fd1 - fd4: floppy drives
|
||||||
|
* = sda: whatever external drives, usually a CD
|
||||||
|
* = boot: current boot device
|
||||||
|
*/
|
||||||
|
|
||||||
|
// remove first '/' in path
|
||||||
|
var path = luapath.checkjstring()
|
||||||
|
if (path.startsWith('/')) path = path.substring(1)
|
||||||
|
// replace '\' with '/'
|
||||||
|
path.replace('\\', '/')
|
||||||
|
|
||||||
|
if (path.startsWith("media/")) {
|
||||||
|
val device = path.substring(6, 9)
|
||||||
|
val subPath = path.substring(9)
|
||||||
|
return computerDir + this.computerValue.getAsString("device") + subPath
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return computerDir + this.computerValue.getAsString("boot") + "/" + path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun combinePath(base: String, local: String): String {
|
||||||
|
return "$base$local".replace("//", "/").replace("\\\\", "\\")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cname == UUID of the drive
|
||||||
|
*
|
||||||
|
* actual directory: <appdata>/Saves/<savename>/computers/<drivename>/
|
||||||
|
*/
|
||||||
|
class ListFiles(val computer: BaseTerrarumComputer): OneArgFunction() {
|
||||||
|
override fun call(path: LuaValue): LuaValue {
|
||||||
|
val table = LuaTable()
|
||||||
|
val file = File(computer.getRealPath(path))
|
||||||
|
file.list().forEachIndexed { i, s -> table.insert(i, LuaValue.valueOf(s)) }
|
||||||
|
return table
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FileExists(val computer: BaseTerrarumComputer): OneArgFunction() {
|
||||||
|
override fun call(path: LuaValue): LuaValue {
|
||||||
|
return LuaValue.valueOf(File(computer.getRealPath(path)).exists())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IsDirectory(val computer: BaseTerrarumComputer): OneArgFunction() {
|
||||||
|
override fun call(path: LuaValue): LuaValue {
|
||||||
|
return LuaValue.valueOf(File(computer.getRealPath(path)).isDirectory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IsFile(val computer: BaseTerrarumComputer): OneArgFunction() {
|
||||||
|
override fun call(path: LuaValue): LuaValue {
|
||||||
|
return LuaValue.valueOf(File(computer.getRealPath(path)).isFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IsReadOnly(val computer: BaseTerrarumComputer): OneArgFunction() {
|
||||||
|
override fun call(path: LuaValue): LuaValue {
|
||||||
|
return LuaValue.valueOf(!File(computer.getRealPath(path)).canWrite())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** we have 4GB file size limit */
|
||||||
|
class GetSize(val computer: BaseTerrarumComputer): OneArgFunction() {
|
||||||
|
override fun call(path: LuaValue): LuaValue {
|
||||||
|
return LuaValue.valueOf(File(computer.getRealPath(path)).length().toInt())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO class GetFreeSpace
|
||||||
|
|
||||||
|
/**
|
||||||
|
* difference with ComputerCraft: it returns boolean, true on successful.
|
||||||
|
*/
|
||||||
|
class Mkdir(val computer: BaseTerrarumComputer): OneArgFunction() {
|
||||||
|
override fun call(path: LuaValue): LuaValue {
|
||||||
|
return LuaValue.valueOf(File(computer.getRealPath(path)).mkdir())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* moves a directory, overwrites the target
|
||||||
|
*/
|
||||||
|
class Mv(val computer: BaseTerrarumComputer): TwoArgFunction() {
|
||||||
|
override fun call(from: LuaValue, to: LuaValue): LuaValue {
|
||||||
|
val fromFile = File(computer.getRealPath(from))
|
||||||
|
fromFile.copyRecursively(
|
||||||
|
File(computer.getRealPath(to)), overwrite = true
|
||||||
|
)
|
||||||
|
fromFile.deleteRecursively()
|
||||||
|
return LuaValue.NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* copies a directory, overwrites the target
|
||||||
|
* difference with ComputerCraft: it returns boolean, true on successful.
|
||||||
|
*/
|
||||||
|
class Cp(val computer: BaseTerrarumComputer): TwoArgFunction() {
|
||||||
|
override fun call(from: LuaValue, to: LuaValue): LuaValue {
|
||||||
|
return LuaValue.valueOf(
|
||||||
|
File(computer.getRealPath(from)).copyRecursively(
|
||||||
|
File(computer.getRealPath(to)), overwrite = true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* difference with ComputerCraft: it returns boolean, true on successful.
|
||||||
|
*/
|
||||||
|
class Rm(val computer: BaseTerrarumComputer): OneArgFunction() {
|
||||||
|
override fun call(path: LuaValue): LuaValue {
|
||||||
|
return LuaValue.valueOf(
|
||||||
|
File(computer.getRealPath(path)).deleteRecursively()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConcatPath(val computer: BaseTerrarumComputer): TwoArgFunction() {
|
||||||
|
override fun call(base: LuaValue, local: LuaValue): LuaValue {
|
||||||
|
val combinedPath = combinePath(base.checkjstring(), local.checkjstring())
|
||||||
|
return LuaValue.valueOf(combinedPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mode: r, rb, w, wb, a, ab
|
||||||
|
*
|
||||||
|
* Difference: TEXT MODE assumes CP437 instead of UTF-8!
|
||||||
|
*
|
||||||
|
* When you have opened a file you must always close the file handle, or else data may not be saved.
|
||||||
|
*
|
||||||
|
* FILE class in CC:
|
||||||
|
* (when you look thru them using file = fs.open("./test", "w")
|
||||||
|
*
|
||||||
|
* file = {
|
||||||
|
* close = function()
|
||||||
|
* -- write mode
|
||||||
|
* write = function(string)
|
||||||
|
* flush = function() -- write, keep the handle
|
||||||
|
* writeLine = function(string) -- text mode
|
||||||
|
* -- read mode
|
||||||
|
* readLine = function() -- text mode
|
||||||
|
* readAll = function()
|
||||||
|
* -- binary read mode
|
||||||
|
* read = function() -- read single byte. return: number or nil
|
||||||
|
* -- binary write mode
|
||||||
|
* write = function(byte)
|
||||||
|
* writeBytes = function(string as bytearray)
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
class OpenFile(val computer: BaseTerrarumComputer): TwoArgFunction() {
|
||||||
|
override fun call(path: LuaValue, mode: LuaValue): LuaValue {
|
||||||
|
val mode = mode.checkjstring().toLowerCase()
|
||||||
|
val luaClass = LuaTable()
|
||||||
|
val file = File(computer.getRealPath(path))
|
||||||
|
|
||||||
|
if (mode.contains("[aw]") && !file.canWrite())
|
||||||
|
throw LuaError("Cannot open file for " +
|
||||||
|
"${if (mode.startsWith('w')) "read" else "append"} mode" +
|
||||||
|
": is readonly.")
|
||||||
|
|
||||||
|
when (mode) {
|
||||||
|
"r" -> {
|
||||||
|
val fr = FileReader(file)
|
||||||
|
luaClass["close"] = FileClassClose(fr)
|
||||||
|
luaClass["readLine"] = FileClassReadLine(fr)
|
||||||
|
luaClass["readAll"] = FileClassReadAll(fr)
|
||||||
|
}
|
||||||
|
"rb" -> {
|
||||||
|
val fis = FileInputStream(file)
|
||||||
|
luaClass["close"] = FileClassClose(fis)
|
||||||
|
luaClass["read"] = FileClassReadByte(fis)
|
||||||
|
}
|
||||||
|
"w", "a" -> {
|
||||||
|
val fw = FileWriter(file, (mode.startsWith('a')))
|
||||||
|
luaClass["close"] = FileClassClose(fw)
|
||||||
|
luaClass["write"] = FileClassPrintText(fw)
|
||||||
|
luaClass["writeLine"] = FileClassPrintlnText(fw)
|
||||||
|
luaClass["flush"] = FileClassFlush(fw)
|
||||||
|
}
|
||||||
|
"wb", "ab" -> {
|
||||||
|
val fos = FileOutputStream(file, (mode.startsWith('a')))
|
||||||
|
luaClass["close"] = FileClassClose(fos)
|
||||||
|
luaClass["write"] = FileClassWriteByte(fos)
|
||||||
|
luaClass["writeBytes"] = FileClassWriteBytes(fos)
|
||||||
|
luaClass["flush"] = FileClassFlush(fos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return luaClass
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GetParentDir(val computer: BaseTerrarumComputer): OneArgFunction() {
|
||||||
|
override fun call(path: LuaValue): LuaValue {
|
||||||
|
var pathSB = StringBuilder(path.checkjstring())
|
||||||
|
|
||||||
|
// backward travel, drop chars until '/' has encountered
|
||||||
|
while (!pathSB.endsWith('/') && !pathSB.endsWith('\\'))
|
||||||
|
pathSB.deleteCharAt(pathSB.lastIndex - 1)
|
||||||
|
|
||||||
|
// drop trailing '/'
|
||||||
|
if (pathSB.endsWith('/') || pathSB.endsWith('\\'))
|
||||||
|
pathSB.deleteCharAt(pathSB.lastIndex - 1)
|
||||||
|
|
||||||
|
return LuaValue.valueOf(pathSB.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////
|
||||||
|
// OpenFile implementations //
|
||||||
|
//////////////////////////////
|
||||||
|
|
||||||
|
private class FileClassClose(val fo: Any): ZeroArgFunction() {
|
||||||
|
override fun call(): LuaValue {
|
||||||
|
if (fo is FileOutputStream)
|
||||||
|
fo.close()
|
||||||
|
else if (fo is FileWriter)
|
||||||
|
fo.close()
|
||||||
|
else if (fo is FileReader)
|
||||||
|
fo.close()
|
||||||
|
else if (fo is FileInputStream)
|
||||||
|
fo.close()
|
||||||
|
else
|
||||||
|
throw IllegalArgumentException("Unacceptable file output: must be either Input/OutputStream or Reader/Writer.")
|
||||||
|
|
||||||
|
return LuaValue.NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FileClassWriteByte(val fos: FileOutputStream): OneArgFunction() {
|
||||||
|
override fun call(byte: LuaValue): LuaValue {
|
||||||
|
fos.write(byte.checkint())
|
||||||
|
|
||||||
|
return LuaValue.NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FileClassWriteBytes(val fos: FileOutputStream): OneArgFunction() {
|
||||||
|
override fun call(byteString: LuaValue): LuaValue {
|
||||||
|
val byteString = byteString.checkjstring()
|
||||||
|
val bytearr = ByteArray(byteString.length, { byteString[it].toByte() })
|
||||||
|
fos.write(bytearr)
|
||||||
|
|
||||||
|
return LuaValue.NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FileClassPrintText(val fw: FileWriter): OneArgFunction() {
|
||||||
|
override fun call(string: LuaValue): LuaValue {
|
||||||
|
val text = string.checkjstring()
|
||||||
|
fw.write(text)
|
||||||
|
return LuaValue.NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FileClassPrintlnText(val fw: FileWriter): OneArgFunction() {
|
||||||
|
override fun call(string: LuaValue): LuaValue {
|
||||||
|
val text = string.checkjstring() + "\n"
|
||||||
|
fw.write(text)
|
||||||
|
return LuaValue.NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FileClassFlush(val fo: Any): ZeroArgFunction() {
|
||||||
|
override fun call(): LuaValue {
|
||||||
|
if (fo is FileOutputStream)
|
||||||
|
fo.flush()
|
||||||
|
else if (fo is FileWriter)
|
||||||
|
fo.flush()
|
||||||
|
else
|
||||||
|
throw IllegalArgumentException("Unacceptable file output: must be either OutputStream or Writer.")
|
||||||
|
|
||||||
|
return LuaValue.NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FileClassReadByte(val fis: FileInputStream): ZeroArgFunction() {
|
||||||
|
override fun call(): LuaValue {
|
||||||
|
val readByte = fis.read()
|
||||||
|
return if (readByte == -1) LuaValue.NIL else LuaValue.valueOf(readByte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FileClassReadAll(val fr: FileReader): ZeroArgFunction() {
|
||||||
|
override fun call(): LuaValue {
|
||||||
|
return LuaValue.valueOf(fr.readText())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FileClassReadLine(val fr: FileReader): ZeroArgFunction() {
|
||||||
|
val scanner = Scanner(fr.readText()) // keeps the scanner status persistent
|
||||||
|
|
||||||
|
override fun call(): LuaValue {
|
||||||
|
return if (scanner.hasNextLine()) LuaValue.valueOf(scanner.nextLine())
|
||||||
|
else LuaValue.NIL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package net.torvald.terrarum.virtualcomputer.luaapi
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 16-09-17.
|
||||||
|
*/
|
||||||
|
class FilesystemFactory {
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package net.torvald.terrarum.virtualcomputer.lualib
|
package net.torvald.terrarum.virtualcomputer.luaapi
|
||||||
|
|
||||||
|
import li.cil.repack.org.luaj.vm2.Globals
|
||||||
import li.cil.repack.org.luaj.vm2.LuaValue
|
import li.cil.repack.org.luaj.vm2.LuaValue
|
||||||
import li.cil.repack.org.luaj.vm2.lib.OneArgFunction
|
import li.cil.repack.org.luaj.vm2.lib.OneArgFunction
|
||||||
import net.torvald.terrarum.gameworld.toUint
|
import net.torvald.terrarum.gameworld.toUint
|
||||||
@@ -10,7 +11,19 @@ import java.security.SecureRandom
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 16-09-15.
|
* Created by minjaesong on 16-09-15.
|
||||||
*/
|
*/
|
||||||
class SecurityLib {
|
internal class Security(globals: Globals) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
// load things. WARNING: THIS IS MANUAL!
|
||||||
|
globals["security"] = LuaValue.tableOf()
|
||||||
|
globals["security"]["toSHA256"] = SHA256sum()
|
||||||
|
globals["security"]["toSHA1"] = SHA1sum()
|
||||||
|
globals["security"]["toMD5"] = MD5sum()
|
||||||
|
globals["security"]["randomBytes"] = SecureRandomHex()
|
||||||
|
globals["security"]["decodeBase64"] = DecodeBase64()
|
||||||
|
globals["security"]["encodeBase64"] = EncodeBase64()
|
||||||
|
}
|
||||||
|
|
||||||
/** @return byteArray as String */
|
/** @return byteArray as String */
|
||||||
class SHA256sum : OneArgFunction() {
|
class SHA256sum : OneArgFunction() {
|
||||||
override fun call(p0: LuaValue): LuaValue {
|
override fun call(p0: LuaValue): LuaValue {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.torvald.terrarum.virtualcomputer.lualib
|
package net.torvald.terrarum.virtualcomputer.luaapi
|
||||||
|
|
||||||
import li.cil.repack.org.luaj.vm2.*
|
import li.cil.repack.org.luaj.vm2.*
|
||||||
import li.cil.repack.org.luaj.vm2.lib.*
|
import li.cil.repack.org.luaj.vm2.lib.*
|
||||||
@@ -10,37 +10,37 @@ import net.torvald.terrarum.virtualcomputer.terminal.Terminal
|
|||||||
*
|
*
|
||||||
* Created by minjaesong on 16-09-12.
|
* Created by minjaesong on 16-09-12.
|
||||||
*/
|
*/
|
||||||
internal class TermLib(globals: Globals, term: Teletype) {
|
internal class Term(globals: Globals, term: Teletype) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
// load things. WARNING: THIS IS MANUAL!
|
// load things. WARNING: THIS IS MANUAL!
|
||||||
globals["term"] = LuaValue.tableOf()
|
globals["term"] = LuaValue.tableOf()
|
||||||
globals["term"]["write"] = TermLib.WriteString(term)
|
globals["term"]["write"] = Term.WriteString(term)
|
||||||
globals["term"]["print"] = TermLib.PrintString(term)
|
globals["term"]["print"] = Term.PrintString(term)
|
||||||
globals["term"]["newLine"] = TermLib.NewLine(term)
|
globals["term"]["newLine"] = Term.NewLine(term)
|
||||||
globals["term"]["moveCursor"] = TermLib.MoveCursor(term) // TTY function
|
globals["term"]["moveCursor"] = Term.MoveCursor(term) // TTY function
|
||||||
globals["term"]["width"] = TermLib.GetWidth(term)
|
globals["term"]["width"] = Term.GetWidth(term)
|
||||||
globals["term"]["scroll"] = TermLib.Scroll(term)
|
globals["term"]["scroll"] = Term.Scroll(term)
|
||||||
globals["term"]["isTeletype"] = TermLib.IsTeletype(term)
|
globals["term"]["isTeletype"] = Term.IsTeletype(term)
|
||||||
|
|
||||||
if (term is Terminal) {
|
if (term is Terminal) {
|
||||||
globals["term"]["emitRaw"] = TermLib.EmitRaw(term)
|
globals["term"]["emitRaw"] = Term.EmitRaw(term)
|
||||||
globals["term"]["emit"] = TermLib.Emit(term)
|
globals["term"]["emit"] = Term.Emit(term)
|
||||||
globals["term"]["resetColor"] = TermLib.ResetColour(term)
|
globals["term"]["resetColor"] = Term.ResetColour(term)
|
||||||
globals["term"]["resetColour"] = TermLib.ResetColour(term)
|
globals["term"]["resetColour"] = Term.ResetColour(term)
|
||||||
globals["term"]["clear"] = TermLib.Clear(term)
|
globals["term"]["clear"] = Term.Clear(term)
|
||||||
globals["term"]["clearLine"] = TermLib.ClearLine(term)
|
globals["term"]["clearLine"] = Term.ClearLine(term)
|
||||||
globals["term"]["moveCursor"] = TermLib.SetCursorPos(term)
|
globals["term"]["moveCursor"] = Term.SetCursorPos(term)
|
||||||
globals["term"]["getCursor"] = TermLib.GetCursorPos(term)
|
globals["term"]["getCursor"] = Term.GetCursorPos(term)
|
||||||
globals["term"]["getX"] = TermLib.GetCursorX(term)
|
globals["term"]["getX"] = Term.GetCursorX(term)
|
||||||
globals["term"]["getY"] = TermLib.GetCursorY(term)
|
globals["term"]["getY"] = Term.GetCursorY(term)
|
||||||
globals["term"]["blink"] = TermLib.SetCursorBlink(term)
|
globals["term"]["blink"] = Term.SetCursorBlink(term)
|
||||||
globals["term"]["size"] = TermLib.GetSize(term)
|
globals["term"]["size"] = Term.GetSize(term)
|
||||||
globals["term"]["isCol"] = TermLib.IsColour(term)
|
globals["term"]["isCol"] = Term.IsColour(term)
|
||||||
globals["term"]["setForeCol"] = TermLib.SetForeColour(term)
|
globals["term"]["setForeCol"] = Term.SetForeColour(term)
|
||||||
globals["term"]["setBackCol"] = TermLib.SetBackColour(term)
|
globals["term"]["setBackCol"] = Term.SetBackColour(term)
|
||||||
globals["term"]["foreCol"] = TermLib.GetForeColour(term)
|
globals["term"]["foreCol"] = Term.GetForeColour(term)
|
||||||
globals["term"]["backCol"] = TermLib.GetBackColour(term)
|
globals["term"]["backCol"] = Term.GetBackColour(term)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package net.torvald.terrarum.virtualcomputer.worldobject
|
package net.torvald.terrarum.virtualcomputer.worldobject
|
||||||
|
|
||||||
import net.torvald.terrarum.gameactors.AVKey
|
import net.torvald.terrarum.gameactors.AVKey
|
||||||
import net.torvald.terrarum.gameactors.FixturesBase
|
import net.torvald.terrarum.gameactors.FixtureBase
|
||||||
import net.torvald.terrarum.virtualcomputer.terminal.SimpleTextTerminal
|
import net.torvald.terrarum.virtualcomputer.terminal.SimpleTextTerminal
|
||||||
import net.torvald.terrarum.virtualcomputer.terminal.Terminal
|
import net.torvald.terrarum.virtualcomputer.terminal.Terminal
|
||||||
import net.torvald.terrarum.virtualcomputer.worldobject.ui.UITextTerminal
|
import net.torvald.terrarum.virtualcomputer.worldobject.ui.UITextTerminal
|
||||||
@@ -11,7 +11,7 @@ import java.util.*
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 16-09-08.
|
* Created by minjaesong on 16-09-08.
|
||||||
*/
|
*/
|
||||||
class FixturesBasicTerminal(phosphor: Color) : FixturesBase() {
|
class FixtureBasicTerminal(phosphor: Color) : FixtureBase() {
|
||||||
|
|
||||||
val vt: Terminal = SimpleTextTerminal(phosphor, 80, 25)
|
val vt: Terminal = SimpleTextTerminal(phosphor, 80, 25)
|
||||||
val ui = UITextTerminal(vt)
|
val ui = UITextTerminal(vt)
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package net.torvald.terrarum.virtualcomputer.worldobject
|
package net.torvald.terrarum.virtualcomputer.worldobject
|
||||||
|
|
||||||
import net.torvald.terrarum.gameactors.FixturesBase
|
import net.torvald.terrarum.gameactors.FixtureBase
|
||||||
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
|
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
|
||||||
import net.torvald.terrarum.virtualcomputer.terminal.SimpleTextTerminal
|
import net.torvald.terrarum.virtualcomputer.terminal.SimpleTextTerminal
|
||||||
import net.torvald.terrarum.virtualcomputer.terminal.Terminal
|
import net.torvald.terrarum.virtualcomputer.terminal.Terminal
|
||||||
@@ -12,51 +12,30 @@ import java.util.*
|
|||||||
/**
|
/**
|
||||||
* Created by minjaesong on 16-09-08.
|
* Created by minjaesong on 16-09-08.
|
||||||
*/
|
*/
|
||||||
open class FixturesComputerBase() : FixturesBase() {
|
open class FixtureComputerBase() : FixtureBase() {
|
||||||
|
|
||||||
val processorCycle: Int // number of Lua statement to process per tick (1/100 s)
|
val processorCycle: Int // number of Lua statement to process per tick (1/100 s)
|
||||||
get() = ComputerPartsCodex.getProcessorCycles(actorValue.getAsInt("processor") ?: -1)
|
get() = ComputerPartsCodex.getProcessorCycles(computerInside!!.computerValue.getAsInt("processor") ?: -1)
|
||||||
val memSize: Int // max: 8 GB
|
val memSize: Int // max: 8 GB
|
||||||
get() {
|
get() {
|
||||||
var size = 0
|
var size = 0
|
||||||
for (i in 0..3)
|
for (i in 0..3)
|
||||||
size += ComputerPartsCodex.getRamSize(actorValue.getAsInt("memSlot$i") ?: -1)
|
size += ComputerPartsCodex.getRamSize(computerInside!!.computerValue.getAsInt("memSlot$i") ?: -1)
|
||||||
|
|
||||||
return size
|
return size
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Connected terminal */
|
/** Connected terminal */
|
||||||
var terminal: FixturesBasicTerminal? = null
|
var terminal: FixtureBasicTerminal? = null
|
||||||
|
|
||||||
var computerInside: BaseTerrarumComputer? = null
|
var computerInside: BaseTerrarumComputer? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
actorValue["memslot0"] = -1 // -1 indicates mem slot is empty
|
// UUID of the "brain"
|
||||||
actorValue["memslot1"] = -1 // put index of item here
|
actorValue["computerid"] = "none"
|
||||||
actorValue["memslot2"] = -1 // ditto.
|
|
||||||
actorValue["memslot3"] = -1 // do.
|
|
||||||
|
|
||||||
actorValue["processor"] = -1 // do.
|
|
||||||
|
|
||||||
// as in "dev/hda"; refers hard disk drive (and no partitioning)
|
|
||||||
actorValue["hda"] = "none" // 'UUID rendered as String' or "none"
|
|
||||||
actorValue["hdb"] = "none"
|
|
||||||
actorValue["hdc"] = "none"
|
|
||||||
actorValue["hdd"] = "none"
|
|
||||||
// as in "dev/fd1"; refers floppy disk drive
|
|
||||||
actorValue["fd1"] = "none"
|
|
||||||
actorValue["fd2"] = "none"
|
|
||||||
actorValue["fd3"] = "none"
|
|
||||||
actorValue["fd4"] = "none"
|
|
||||||
// SCSI connected optical drive
|
|
||||||
actorValue["sda"] = "none"
|
|
||||||
|
|
||||||
// UUID of this device
|
|
||||||
actorValue["uuid"] = UUID.randomUUID().toString()
|
|
||||||
|
|
||||||
collisionFlag = COLLISION_PLATFORM
|
collisionFlag = COLLISION_PLATFORM
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////
|
////////////////////////////////////
|
||||||
@@ -66,6 +45,7 @@ open class FixturesComputerBase() : FixturesBase() {
|
|||||||
fun attachTerminal(uuid: String) {
|
fun attachTerminal(uuid: String) {
|
||||||
val fetchedTerminal = getTerminalByUUID(uuid)
|
val fetchedTerminal = getTerminalByUUID(uuid)
|
||||||
computerInside = BaseTerrarumComputer(fetchedTerminal)
|
computerInside = BaseTerrarumComputer(fetchedTerminal)
|
||||||
|
actorValue["computerid"] = computerInside!!.UUID
|
||||||
}
|
}
|
||||||
|
|
||||||
fun detatchTerminal() {
|
fun detatchTerminal() {
|
||||||
Reference in New Issue
Block a user