mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-10 10:34:06 +09:00
OS library implementation
Former-commit-id: b4f7f283080ead5e92c273015bfe2559cbe99e47 Former-commit-id: adaa0af80068a916e534f677f6e5ffe1f3072241
This commit is contained in:
@@ -6,10 +6,32 @@
|
||||
Some codes were taken from OpenComputers, which is distributed under MIT
|
||||
--]]
|
||||
|
||||
-- global functions
|
||||
_G.runscript = function(s, src, ...)
|
||||
if s:byte(1) == 27 then error("Bytecode execution is prohibited.") end
|
||||
|
||||
local code, reason = load(s, src)
|
||||
|
||||
if code then
|
||||
xpcall(code(...), eprint)
|
||||
else
|
||||
print(DLE..tostring(reason)) -- it catches syntax errors
|
||||
end
|
||||
end
|
||||
|
||||
fs.dofile = function(p, ...)
|
||||
local f = fs.open(p, "r")
|
||||
local s = f.readAll()
|
||||
_G.runscript(s, "="..p, ...)
|
||||
end
|
||||
|
||||
-- EFI is expected to locate in "boot/efi"
|
||||
if fs.exists("boot/efi") then fs.dofile("boot/efi") end
|
||||
|
||||
computer.realTime = function() return 0 end
|
||||
|
||||
-- global variables
|
||||
_G._VERSION = "Luaj-jse 3.0.1 (Lua 5.2.3)"
|
||||
_G._VERSION = _VERSION.." (Lua 5.2.3)"
|
||||
_G.EMDASH = string.char(0xC4)
|
||||
_G.UNCHECKED = string.char(0x9C) -- box unchecked
|
||||
_G.CHECKED = string.char(0x9D) -- box checked
|
||||
@@ -969,18 +991,6 @@ sandbox._G = sandbox
|
||||
-- path for any ingame libraries
|
||||
package.path = "/net/torvald/terrarum/virtualcomputer/assets/lua/?.lua;" .. package.path
|
||||
|
||||
-- global functions
|
||||
_G.runscript = function(s, src, ...)
|
||||
if s:byte(1) == 27 then error("Bytecode execution is prohibited.") end
|
||||
|
||||
local code, reason = load(s, src)
|
||||
|
||||
if code then
|
||||
xpcall(code(...), eprint)
|
||||
else
|
||||
print(DLE..tostring(reason)) -- it catches syntax errors
|
||||
end
|
||||
end
|
||||
_G.__scanMode__ = "UNINIT" -- part of inputstream implementation
|
||||
|
||||
local screenbufferdim = term.width() * term.height()
|
||||
@@ -989,14 +999,15 @@ if term.isCol() then screencolours = 8
|
||||
elseif term.isTeletype() then screencolours = 1 end
|
||||
local screenbuffersize = screenbufferdim * screencolours / 8
|
||||
|
||||
computer.prompt = DC3.."> "..DC4
|
||||
computer.verbose = true -- print debug info
|
||||
computer.loadedCLayer = {} -- list of loaded compatibility layers
|
||||
computer.bootloader = "/boot/efi"
|
||||
computer.OEM = ""
|
||||
if not computer.prompt then computer.prompt = DC3.."> "..DC4 end
|
||||
if not computer.verbose then computer.verbose = true end -- print debug info
|
||||
if not computer.loadedCLayer then computer.loadedCLayer = {} end -- list of loaded compatibility layers
|
||||
-- if no bootloader is pre-defined via EFI, use default one
|
||||
if not computer.bootloader then computer.bootloader = "/boot/bootloader" end
|
||||
if not computer.OEM then computer.OEM = "" end
|
||||
computer.beep = emittone
|
||||
computer.totalMemory = _G.totalMemory
|
||||
computer.bellpitch = 1000
|
||||
if not computer.bellpitch then computer.bellpitch = 1000 end
|
||||
local getMemory = function()
|
||||
collectgarbage()
|
||||
return collectgarbage("count") * 1024 - 6.5*1048576 + screenbuffersize
|
||||
@@ -1021,7 +1032,7 @@ print("Rom basic "..DC2.._VERSION..DC4)
|
||||
print("Copyright (C) 1994-2013 Lua.org, PUC-Rio")
|
||||
print("Ok")
|
||||
|
||||
while not native.isHalted() do
|
||||
while not machine.isHalted() do
|
||||
term.setCursorBlink(true)
|
||||
io.write(computer.prompt)
|
||||
local s = __scanforline__()
|
||||
@@ -1039,5 +1050,5 @@ while not native.isHalted() do
|
||||
end
|
||||
|
||||
::quit::
|
||||
native.closeInputString()
|
||||
machine.closeInputString()
|
||||
return
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
|
||||
_G.io = {}
|
||||
|
||||
fs.dofile = function(p, ...)
|
||||
--[[fs.dofile = function(p, ...)
|
||||
local f = fs.open(p, "r")
|
||||
local s = f.readAll()
|
||||
_G.runscript(s, "="..p, ...)
|
||||
end
|
||||
end]] -- implementation moved to BOOT.lua
|
||||
|
||||
_G.loadstring = _G.load
|
||||
|
||||
@@ -46,12 +46,12 @@ override fun keyPressed(key: Int, c: Char) {
|
||||
and THIS exact part will close the input for this function.
|
||||
]]
|
||||
_G.__scanforline__ = function(echo) -- pass '1' to not echo; pass nothing to echo
|
||||
native.closeInputString()
|
||||
native.openInput(echo or 0)
|
||||
machine.closeInputString()
|
||||
machine.openInput(echo or 0)
|
||||
_G.__scanMode__ = "line"
|
||||
local s
|
||||
repeat -- we can do this ONLY IF lua execution process is SEPARATE THREAD
|
||||
s = native.getLastStreamInput()
|
||||
s = machine.getLastStreamInput()
|
||||
until s
|
||||
-- input is closed when RETURN is hit. See above comments.
|
||||
return s
|
||||
@@ -59,12 +59,12 @@ end
|
||||
|
||||
-- use Keys API to identify the keycode
|
||||
--[[_G.__scanforkey__ = function(echo) -- pass '1' to not echo; pass nothing to echo
|
||||
native.closeInputString()
|
||||
native.openInput(echo or 0)
|
||||
machine.closeInputString()
|
||||
machine.openInput(echo or 0)
|
||||
_G.__scanMode__ = "a_key"
|
||||
local key
|
||||
repeat -- we can do this ONLY IF lua execution process is SEPARATE THREAD
|
||||
key = native.getLastKeyPress()
|
||||
key = machine.getLastKeyPress()
|
||||
until key
|
||||
-- input is closed when any key is hit. See above comments.
|
||||
return key
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
package net.torvald.terrarum.virtualcomputer.computer
|
||||
|
||||
import com.jme3.math.FastMath
|
||||
import li.cil.repack.org.luaj.vm2.Globals
|
||||
import li.cil.repack.org.luaj.vm2.LuaError
|
||||
import li.cil.repack.org.luaj.vm2.LuaTable
|
||||
import li.cil.repack.org.luaj.vm2.LuaValue
|
||||
import li.cil.repack.org.luaj.vm2.lib.TwoArgFunction
|
||||
import li.cil.repack.org.luaj.vm2.lib.ZeroArgFunction
|
||||
import li.cil.repack.org.luaj.vm2.lib.jse.JsePlatform
|
||||
import org.luaj.vm2.Globals
|
||||
import org.luaj.vm2.LuaError
|
||||
import org.luaj.vm2.LuaTable
|
||||
import org.luaj.vm2.LuaValue
|
||||
import org.luaj.vm2.lib.TwoArgFunction
|
||||
import org.luaj.vm2.lib.ZeroArgFunction
|
||||
import org.luaj.vm2.lib.jse.JsePlatform
|
||||
import net.torvald.terrarum.KVHashMap
|
||||
import net.torvald.terrarum.gameactors.ActorValue
|
||||
import net.torvald.terrarum.gameactors.roundInt
|
||||
import net.torvald.terrarum.virtualcomputer.luaapi.*
|
||||
import net.torvald.terrarum.virtualcomputer.terminal.*
|
||||
import net.torvald.terrarum.virtualcomputer.worldobject.ComputerPartsCodex
|
||||
import net.torvald.terrarum.virtualcomputer.worldobject.FixtureComputerBase
|
||||
import org.lwjgl.BufferUtils
|
||||
import org.lwjgl.openal.AL
|
||||
import org.lwjgl.openal.AL10
|
||||
@@ -73,6 +71,12 @@ class BaseTerrarumComputer() {
|
||||
lateinit var term: Teletype
|
||||
private set
|
||||
|
||||
// os-related functions. These are called "machine" library-wise.
|
||||
private val startupTimestamp: Long = System.currentTimeMillis()
|
||||
/** Time elapsed since the power is on. */
|
||||
val milliTime: Int
|
||||
get() = (System.currentTimeMillis() - startupTimestamp).toInt()
|
||||
|
||||
init {
|
||||
computerValue["memslot0"] = 4864 // -1 indicates mem slot is empty
|
||||
computerValue["memslot1"] = -1 // put index of item here
|
||||
@@ -96,7 +100,6 @@ class BaseTerrarumComputer() {
|
||||
|
||||
// boot device
|
||||
computerValue["boot"] = computerValue.getAsString("hda")!!
|
||||
|
||||
}
|
||||
|
||||
fun attachTerminal(term: Teletype) {
|
||||
@@ -125,6 +128,7 @@ class BaseTerrarumComputer() {
|
||||
Input(luaJ_globals, this)
|
||||
Http(luaJ_globals, this)
|
||||
PcSpeakerDriver(luaJ_globals, this)
|
||||
WorldInformationProvider(luaJ_globals)
|
||||
|
||||
|
||||
// secure the sandbox
|
||||
@@ -141,6 +145,7 @@ class BaseTerrarumComputer() {
|
||||
luaJ_globals["totalMemory"] = LuaFunGetTotalMem(this)
|
||||
|
||||
luaJ_globals["computer"] = LuaTable()
|
||||
// rest of the "computer" APIs should be implemented in BOOT.lua
|
||||
if (DEBUG) luaJ_globals["emittone"] = ComputerEmitTone(this)
|
||||
}
|
||||
|
||||
@@ -167,8 +172,6 @@ class BaseTerrarumComputer() {
|
||||
}
|
||||
|
||||
driveBeepQueueManager(delta)
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun keyPressed(key: Int, c: Char) {
|
||||
@@ -267,19 +270,19 @@ class BaseTerrarumComputer() {
|
||||
private var beepQueueFired = false
|
||||
|
||||
private fun driveBeepQueueManager(delta: Int) {
|
||||
// start beep queue
|
||||
// start emitTone queue
|
||||
if (beepQueue.size > 0 && beepCursor == -1) {
|
||||
beepCursor = 0
|
||||
}
|
||||
|
||||
// continue beep queue
|
||||
// continue emitTone queue
|
||||
if (beepCursor >= 0 && beepQueueLineExecTimer >= beepQueueGetLenOfPtn(beepCursor)) {
|
||||
beepQueueLineExecTimer -= beepQueueGetLenOfPtn(beepCursor)
|
||||
beepCursor += 1
|
||||
beepQueueFired = false
|
||||
}
|
||||
|
||||
// complete beep queue
|
||||
// complete emitTone queue
|
||||
if (beepCursor >= beepQueue.size) {
|
||||
clearBeepQueue()
|
||||
if (DEBUG) println("!! Beep queue clear")
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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 org.luaj.vm2.*
|
||||
import org.luaj.vm2.lib.OneArgFunction
|
||||
import org.luaj.vm2.lib.TwoArgFunction
|
||||
import org.luaj.vm2.lib.ZeroArgFunction
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
|
||||
import net.torvald.terrarum.virtualcomputer.luaapi.Term.Companion.checkIBM437
|
||||
|
||||
@@ -1,36 +1,35 @@
|
||||
package net.torvald.terrarum.virtualcomputer.luaapi
|
||||
|
||||
import li.cil.repack.org.luaj.vm2.Globals
|
||||
import li.cil.repack.org.luaj.vm2.LuaFunction
|
||||
import li.cil.repack.org.luaj.vm2.LuaTable
|
||||
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.ZeroArgFunction
|
||||
import org.luaj.vm2.lib.OneArgFunction
|
||||
import org.luaj.vm2.lib.ZeroArgFunction
|
||||
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
|
||||
import net.torvald.terrarum.virtualcomputer.luaapi.Term.Companion.checkIBM437
|
||||
import net.torvald.terrarum.virtualcomputer.terminal.Teletype
|
||||
import org.luaj.vm2.*
|
||||
|
||||
/**
|
||||
* Provide Lua an access to computer object that is in Java
|
||||
*
|
||||
* The "machine" refers to the computer fixture itself in the game world.
|
||||
*
|
||||
* Created by minjaesong on 16-09-19.
|
||||
*/
|
||||
internal class HostAccessProvider(globals: Globals, computer: BaseTerrarumComputer) {
|
||||
|
||||
init {
|
||||
globals["native"] = LuaTable()
|
||||
globals["native"]["println"] = PrintLn()
|
||||
globals["native"]["isHalted"] = IsHalted(computer)
|
||||
globals["machine"] = LuaTable()
|
||||
globals["machine"]["println"] = PrintLn()
|
||||
globals["machine"]["isHalted"] = IsHalted(computer)
|
||||
|
||||
globals["native"]["closeInputString"] = NativeCloseInputString(computer.term)
|
||||
globals["native"]["closeInputKey"] = NativeCloseInputKey(computer.term)
|
||||
globals["native"]["openInput"] = NativeOpenInput(computer.term)
|
||||
globals["native"]["getLastStreamInput"] = NativeGetLastStreamInput(computer.term)
|
||||
globals["native"]["getLastKeyPress"] = NativeGetLastKeyPress(computer.term)
|
||||
globals["machine"]["closeInputString"] = NativeCloseInputString(computer.term)
|
||||
globals["machine"]["closeInputKey"] = NativeCloseInputKey(computer.term)
|
||||
globals["machine"]["openInput"] = NativeOpenInput(computer.term)
|
||||
globals["machine"]["getLastStreamInput"] = NativeGetLastStreamInput(computer.term)
|
||||
globals["machine"]["getLastKeyPress"] = NativeGetLastKeyPress(computer.term)
|
||||
|
||||
// while lua's dofile/require is fixiated to fs, this command allows
|
||||
// libraries in JAR to be loaded.
|
||||
//globals["native"]["loadBuiltInLib"] = NativeLoadBuiltInLib()
|
||||
globals["machine"]["milliTime"] = NativeGetMilliTime(computer)
|
||||
|
||||
globals["machine"]["sleep"] = NativeBusySleep(computer)
|
||||
|
||||
globals["__haltsystemexplicit__"] = HaltComputer(computer)
|
||||
}
|
||||
@@ -98,4 +97,21 @@ internal class HostAccessProvider(globals: Globals, computer: BaseTerrarumComput
|
||||
return LuaValue.NONE
|
||||
}
|
||||
}
|
||||
|
||||
/** Time elapsed since the power is on. */
|
||||
class NativeGetMilliTime(val computer: BaseTerrarumComputer) : ZeroArgFunction() {
|
||||
override fun call(): LuaValue {
|
||||
return LuaValue.valueOf(computer.milliTime)
|
||||
}
|
||||
}
|
||||
|
||||
class NativeBusySleep(val computer: BaseTerrarumComputer) : OneArgFunction() {
|
||||
override fun call(mills: LuaValue): LuaValue {
|
||||
val starttime = computer.milliTime
|
||||
val sleeptime = mills.checkint()
|
||||
if (sleeptime > 1000) throw LuaError("Cannot busy-sleep more than a second.")
|
||||
while (computer.milliTime - starttime < sleeptime) { }
|
||||
return LuaValue.NONE
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.torvald.terrarum.virtualcomputer.luaapi
|
||||
|
||||
import li.cil.repack.org.luaj.vm2.Globals
|
||||
import org.luaj.vm2.Globals
|
||||
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package net.torvald.terrarum.virtualcomputer.luaapi
|
||||
|
||||
import li.cil.repack.org.luaj.vm2.Globals
|
||||
import li.cil.repack.org.luaj.vm2.LuaTable
|
||||
import li.cil.repack.org.luaj.vm2.LuaValue
|
||||
import li.cil.repack.org.luaj.vm2.lib.OneArgFunction
|
||||
import org.luaj.vm2.Globals
|
||||
import org.luaj.vm2.LuaTable
|
||||
import org.luaj.vm2.LuaValue
|
||||
import org.luaj.vm2.lib.OneArgFunction
|
||||
import net.torvald.terrarum.gamecontroller.Key
|
||||
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package net.torvald.terrarum.virtualcomputer.luaapi
|
||||
|
||||
import li.cil.repack.org.luaj.vm2.Globals
|
||||
import li.cil.repack.org.luaj.vm2.LuaTable
|
||||
import li.cil.repack.org.luaj.vm2.LuaValue
|
||||
import li.cil.repack.org.luaj.vm2.lib.TwoArgFunction
|
||||
import li.cil.repack.org.luaj.vm2.lib.ZeroArgFunction
|
||||
import org.luaj.vm2.Globals
|
||||
import org.luaj.vm2.LuaTable
|
||||
import org.luaj.vm2.LuaValue
|
||||
import org.luaj.vm2.lib.TwoArgFunction
|
||||
import org.luaj.vm2.lib.ZeroArgFunction
|
||||
import net.torvald.terrarum.virtualcomputer.computer.BaseTerrarumComputer
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
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.lib.OneArgFunction
|
||||
import org.luaj.vm2.Globals
|
||||
import org.luaj.vm2.LuaValue
|
||||
import org.luaj.vm2.lib.OneArgFunction
|
||||
import net.torvald.terrarum.gameworld.toUint
|
||||
import org.apache.commons.codec.binary.Base64
|
||||
import org.apache.commons.codec.digest.DigestUtils
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package net.torvald.terrarum.virtualcomputer.luaapi
|
||||
|
||||
import li.cil.repack.org.luaj.vm2.*
|
||||
import li.cil.repack.org.luaj.vm2.lib.*
|
||||
import org.luaj.vm2.*
|
||||
import org.luaj.vm2.lib.*
|
||||
import net.torvald.terrarum.virtualcomputer.terminal.Teletype
|
||||
import net.torvald.terrarum.virtualcomputer.terminal.Terminal
|
||||
import java.nio.charset.Charset
|
||||
|
||||
/**
|
||||
* Controls terminal as if it was a monitor
|
||||
* (not sending control sequences but just drives it, as if it was not a terminal @ 9600 baud)
|
||||
* (not sending control sequences but just drives it directly)
|
||||
*
|
||||
* Created by minjaesong on 16-09-12.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package net.torvald.terrarum.virtualcomputer.luaapi
|
||||
|
||||
import org.luaj.vm2.Globals
|
||||
import org.luaj.vm2.LuaFunction
|
||||
import net.torvald.terrarum.Terrarum
|
||||
import net.torvald.terrarum.gameworld.WorldTime
|
||||
import org.luaj.vm2.LuaTable
|
||||
import org.luaj.vm2.LuaValue
|
||||
import org.luaj.vm2.lib.ZeroArgFunction
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Implementation of lua's os.date, to return world info of the game world.
|
||||
*
|
||||
* Created by minjaesong on 16-09-28.
|
||||
*/
|
||||
class WorldInformationProvider(globals: Globals) {
|
||||
|
||||
init {
|
||||
globals["os"]["time"] = LuaValue.NIL // history is LONG! Our 32-bit Lua's epoch is destined to break down...
|
||||
globals["os"]["date"] = OsDateImpl()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun getWorldTimeInLuaFormat() : LuaTable {
|
||||
val t = LuaTable()
|
||||
if (Terrarum.gameStarted) {
|
||||
val time = Terrarum.ingame.world.time
|
||||
|
||||
// int Terrarum World Time format
|
||||
t["hour"] = time.hours
|
||||
t["min"] = time.minutes
|
||||
t["wday"] = time.dayOfWeek
|
||||
t["year"] = time.years
|
||||
t["yday"] = time.yearlyDays
|
||||
t["month"] = time.months
|
||||
t["sec"] = time.seconds
|
||||
t["day"] = time.days
|
||||
}
|
||||
else {
|
||||
t["hour"] = 0
|
||||
t["min"] = 0
|
||||
t["wday"] = 1
|
||||
t["year"] = 0
|
||||
t["yday"] = 1
|
||||
t["month"] = 1
|
||||
t["sec"] = 0
|
||||
t["day"] = 1
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
val defaultDateFormat = "%a %d %B %Y %X"
|
||||
|
||||
/** evaluate single C date format */
|
||||
fun String.evalAsDate(): String {
|
||||
if (Terrarum.gameStarted) {
|
||||
val time = Terrarum.ingame.world.time
|
||||
return when (this) {
|
||||
"%a" -> time.getDayNameShort()
|
||||
"%A" -> time.getDayNameFull()
|
||||
"%b" -> time.getMonthNameShort()
|
||||
"%B" -> time.getMonthNameFull()
|
||||
"%c" -> "%x".evalAsDate() + " " + "%X".evalAsDate()
|
||||
"%d" -> time.days.toString()
|
||||
"%H" -> time.hours.toString()
|
||||
"%I" -> throw IllegalArgumentException("%I: AM/PM concept does not exists.")
|
||||
"%M" -> time.minutes.toString()
|
||||
"%m" -> time.months.toString()
|
||||
"%p" -> throw IllegalArgumentException("%p: AM/PM concept does not exists.")
|
||||
"%S" -> time.seconds.toString()
|
||||
"%w" -> time.dayOfWeek.toString()
|
||||
"%x" -> "${String.format("%02d", time.years)}-${String.format("%02d", time.months)}-${String.format("%02d", time.days)}"
|
||||
"%X" -> "${String.format("%02d", time.hours)}:${String.format("%02d", time.minutes)}:${String.format("%02d", time.seconds)}"
|
||||
"%Y" -> time.years.toString()
|
||||
"%y" -> time.years.mod(100).toString()
|
||||
"%%" -> "%"
|
||||
else -> throw IllegalArgumentException("Unknown format string: $this")
|
||||
}
|
||||
}
|
||||
else {
|
||||
return when (this) {
|
||||
"%a" -> "---"
|
||||
"%A" -> "------"
|
||||
"%b" -> "----"
|
||||
"%B" -> "--------"
|
||||
"%c" -> "%x".evalAsDate() + " " + "%X".evalAsDate()
|
||||
"%d" -> "0"
|
||||
"%H" -> "0"
|
||||
"%I" -> throw IllegalArgumentException("%I: AM/PM concept does not exists.")
|
||||
"%M" -> "0"
|
||||
"%m" -> "0"
|
||||
"%p" -> throw IllegalArgumentException("%p: AM/PM concept does not exists.")
|
||||
"%S" -> "0"
|
||||
"%w" -> "0"
|
||||
"%x" -> "00-00-00"
|
||||
"%X" -> "00:00:00"
|
||||
"%Y" -> "0"
|
||||
"%y" -> "00"
|
||||
"%%" -> "%"
|
||||
else -> throw IllegalArgumentException("Unknown format string: $this")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val acceptedDateFormats = arrayOf("%a", "%A", "%b", "%B", "%c", "%d", "%H", "%I", "%M", "%m", "%p", "%S", "%w", "%x", "%X", "%Y", "%y", "%%" )
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes: cannot get a representation of arbitrary time.
|
||||
*/
|
||||
class OsDateImpl() : LuaFunction() {
|
||||
// no args
|
||||
override fun call(): LuaValue {
|
||||
return call(defaultDateFormat)
|
||||
}
|
||||
|
||||
override fun call(format: LuaValue): LuaValue {
|
||||
var arg = format.checkjstring()
|
||||
acceptedDateFormats.forEach {
|
||||
if (arg.contains(it))
|
||||
arg = arg.replace(it, it.evalAsDate(), ignoreCase = false)
|
||||
}
|
||||
return LuaValue.valueOf(arg)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,194 +0,0 @@
|
||||
/*
|
||||
* $Id: LuaConsole.java 79 2012-01-08 11:08:32Z andre@naef.com $
|
||||
* See LICENSE.txt for license terms.
|
||||
*/
|
||||
|
||||
package net.torvald.terrarum.virtualcomputer.terminal;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
|
||||
import li.cil.repack.com.naef.jnlua.LuaException;
|
||||
import li.cil.repack.com.naef.jnlua.LuaRuntimeException;
|
||||
import li.cil.repack.com.naef.jnlua.LuaState;
|
||||
|
||||
/**
|
||||
* A simple Lua console.
|
||||
*
|
||||
* <p>
|
||||
* The console collects input until a line with the sole content of the word
|
||||
* <i>go</i> is encountered. At that point, the collected input is run as a Lua
|
||||
* chunk. If the Lua chunk loads and runs successfully, the console displays the
|
||||
* returned values of the chunk as well as the execution time based on a
|
||||
* <code>System.nanoTime()</code> measurement. Otherwise, the console shows the
|
||||
* error that has occurred.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Expressions can be printed by prepending <i>=</i> to the expression at the
|
||||
* beginning of a chunk. The console translates <i>=</i> into
|
||||
* <code>return</code> followed by a space and executes the chunk immediately.
|
||||
* No separate <i>go</i> is required. Therefore, expressions printed this way
|
||||
* must be entered on a single line.
|
||||
* </p>
|
||||
*/
|
||||
public class LuaConsole {
|
||||
// -- Static
|
||||
private static final String[] EMPTY_ARGS = new String[0];
|
||||
|
||||
/**
|
||||
* Main routine.
|
||||
*
|
||||
* @param args
|
||||
* the command line arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
LuaConsole luaConsole = new LuaConsole(args);
|
||||
luaConsole.run();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
// -- State
|
||||
private LuaState luaState;
|
||||
|
||||
// -- Construction
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
public LuaConsole() {
|
||||
this(EMPTY_ARGS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance with the specified command line arguments. The
|
||||
* arguments are passed to Lua as the <code>argv</code> global variable.
|
||||
*
|
||||
* @param args
|
||||
*/
|
||||
public LuaConsole(String[] args) {
|
||||
luaState = new LuaState();
|
||||
|
||||
// Process arguments
|
||||
luaState.newTable(args.length, 0);
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
luaState.pushString(args[i]);
|
||||
luaState.rawSet(-2, i + 1);
|
||||
}
|
||||
luaState.setGlobal("argv");
|
||||
|
||||
// Open standard libraries
|
||||
luaState.openLibs();
|
||||
|
||||
// Set buffer mode
|
||||
luaState.load("io.stdout:setvbuf(\"no\")", "=consoleInitStdout");
|
||||
luaState.call(0, 0);
|
||||
luaState.load("io.stderr:setvbuf(\"no\")", "=consoleInitStderr");
|
||||
luaState.call(0, 0);
|
||||
}
|
||||
|
||||
// -- Properties
|
||||
/**
|
||||
* Returns the Lua state of this console.
|
||||
*
|
||||
* @return the Lua state
|
||||
*/
|
||||
public LuaState getLuaState() {
|
||||
return luaState;
|
||||
}
|
||||
|
||||
// -- Operations
|
||||
/**
|
||||
* Runs the console.
|
||||
*/
|
||||
public void run() {
|
||||
// Banner
|
||||
System.out.println(String.format("JNLua %s Console using Lua %s.",
|
||||
LuaState.VERSION, LuaState.LUA_VERSION));
|
||||
System.out.print("Type 'go' on an empty line to evaluate a chunk. ");
|
||||
System.out.println("Type =<expression> to print an expression.");
|
||||
|
||||
// Prepare reader
|
||||
BufferedReader bufferedReader = new BufferedReader(
|
||||
new InputStreamReader(System.in));
|
||||
try {
|
||||
// Process chunks
|
||||
chunk: while (true) {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
OutputStreamWriter outWriter = new OutputStreamWriter(out,
|
||||
"UTF-8");
|
||||
boolean firstLine = true;
|
||||
|
||||
// Process lines
|
||||
while (true) {
|
||||
String line = bufferedReader.readLine();
|
||||
if (line == null) {
|
||||
break chunk;
|
||||
}
|
||||
if (line.equals("go")) {
|
||||
outWriter.flush();
|
||||
InputStream in = new ByteArrayInputStream(out
|
||||
.toByteArray());
|
||||
runChunk(in);
|
||||
continue chunk;
|
||||
}
|
||||
if (firstLine && line.startsWith("=")) {
|
||||
outWriter.write("return " + line.substring(1));
|
||||
outWriter.flush();
|
||||
InputStream in = new ByteArrayInputStream(out
|
||||
.toByteArray());
|
||||
runChunk(in);
|
||||
continue chunk;
|
||||
}
|
||||
outWriter.write(line);
|
||||
outWriter.write('\n');
|
||||
firstLine = false;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
System.out.print("IO error: ");
|
||||
System.out.print(e.getMessage());
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs a chunk of Lua code from an input stream.
|
||||
*/
|
||||
protected void runChunk(InputStream in) throws IOException {
|
||||
try {
|
||||
long start = System.nanoTime();
|
||||
luaState.setTop(0);
|
||||
luaState.load(in, "=console", "t");
|
||||
luaState.call(0, LuaState.MULTRET);
|
||||
long stop = System.nanoTime();
|
||||
for (int i = 1; i <= luaState.getTop(); i++) {
|
||||
if (i > 1) {
|
||||
System.out.print(", ");
|
||||
}
|
||||
switch (luaState.type(i)) {
|
||||
case BOOLEAN:
|
||||
System.out.print(Boolean.valueOf(luaState.toBoolean(i)));
|
||||
break;
|
||||
case NUMBER:
|
||||
case STRING:
|
||||
System.out.print(luaState.toString(i));
|
||||
break;
|
||||
default:
|
||||
System.out.print(luaState.typeName(i));
|
||||
}
|
||||
}
|
||||
System.out.print("\t#msec=");
|
||||
System.out.print(String.format("%.3f", (stop - start) / 1000000.0));
|
||||
System.out.println();
|
||||
} catch (LuaRuntimeException e) {
|
||||
e.printLuaStackTrace();
|
||||
} catch (LuaException e) {
|
||||
System.err.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -223,7 +223,7 @@ open class SimpleTextTerminal(
|
||||
}
|
||||
else {
|
||||
when (c) {
|
||||
ASCII_BEL -> beep()
|
||||
ASCII_BEL -> bell(".")
|
||||
ASCII_BS -> { cursorX -= 1; wrap() }
|
||||
ASCII_TAB -> { cursorX = (cursorX).div(TABSIZE).times(TABSIZE) + TABSIZE }
|
||||
ASCII_LF -> newLine()
|
||||
@@ -318,13 +318,13 @@ open class SimpleTextTerminal(
|
||||
* @param duration: milliseconds
|
||||
* @param freg: Frequency (float)
|
||||
*/
|
||||
override fun beep(duration: Int, freq: Float) {
|
||||
override fun emitTone(duration: Int, freq: Float) {
|
||||
// println("!! Beep playing row $beepCursor, d ${Math.min(duration, maxDuration)} f $freq")
|
||||
host.clearBeepQueue()
|
||||
host.enqueueBeep(duration, freq)
|
||||
}
|
||||
|
||||
/** for "beep code" on modern BIOS. */
|
||||
/** for "emitTone code" on modern BIOS. */
|
||||
override fun bell(pattern: String) {
|
||||
host.clearBeepQueue()
|
||||
|
||||
@@ -336,7 +336,7 @@ open class SimpleTextTerminal(
|
||||
|
||||
for (c in pattern) {
|
||||
when (c) {
|
||||
'.' -> { host.enqueueBeep(50, freq); host.enqueueBeep(50, 0f) }
|
||||
'.' -> { host.enqueueBeep(80, freq); host.enqueueBeep(50, 0f) }
|
||||
'-' -> { host.enqueueBeep(200, freq); host.enqueueBeep(50, 0f) }
|
||||
'=' -> { host.enqueueBeep(500, freq); host.enqueueBeep(50, 0f) }
|
||||
' ' -> { host.enqueueBeep(200, 0f) }
|
||||
|
||||
@@ -61,13 +61,8 @@ interface Terminal : Teletype {
|
||||
* @param duration: milliseconds
|
||||
* @param freg: Frequency (float)
|
||||
*/
|
||||
fun beep(duration: Int = 80, freq: Float = 1000f)
|
||||
/**
|
||||
* Pattern: - .
|
||||
* . 80 ms
|
||||
* - 200 ms
|
||||
* ( ) 80 ms
|
||||
*/
|
||||
fun emitTone(duration: Int, freq: Float)
|
||||
|
||||
override fun bell(pattern: String)
|
||||
/** Requires keyPressed() event to be processed.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user