computer with term lib: somewhat works; new cobblestone texture

Former-commit-id: 8a1a21cc1ea874ec1c243cae7b1e920bdab3be4f
Former-commit-id: ee7aeb05896a36960050f0656764ccf477e5f90d
This commit is contained in:
Song Minjae
2016-09-14 20:28:43 +09:00
parent d8b70887a9
commit abf167d6b8
77 changed files with 1389 additions and 418 deletions

View File

@@ -0,0 +1,51 @@
package net.torvald.terrarum.virtualcomputer.terminal
import net.torvald.aa.ColouredFastFont
import org.newdawn.slick.Color
import org.newdawn.slick.GameContainer
import org.newdawn.slick.Graphics
import org.newdawn.slick.Image
/**
* Created by minjaesong on 16-09-12.
*/
class ColouredTextTerminal(override val width: Int, override val height: Int
) : SimpleTextTerminal(Color.white, width, height) {
override val colours = arrayOf(
Color(0x00, 0x00, 0x00), // black
Color(0xff, 0xff, 0xff), // white
Color(0x55, 0x55, 0x55), // dim grey
Color(0xaa, 0xaa, 0xaa), // light grey
Color(0xff, 0xff, 0x00), // yellow
Color(0xff, 0x66, 0x00), // orange
Color(0xdd, 0x00, 0x00), // red
Color(0xff, 0x00, 0x99), // magenta
Color(0x33, 0x00, 0x99), // purple
Color(0x00, 0x00, 0xcc), // blue
Color(0x00, 0x99, 0xff), // cyan
Color(0x66, 0xff, 0x33), // lime
Color(0x00, 0xaa, 0x00), // green
Color(0x00, 0x66, 0x00), // dark green
Color(0x66, 0x33, 0x00), // brown
Color(0x99, 0x66, 0x33) // tan
) // THESE ARE THE STANDARD
override val coloursCount = colours.size
override val backDefault = 0
override val foreDefault = 3
override var backColour = backDefault
override var foreColour = foreDefault
override val fontRef = "./assets/graphics/fonts/CGA.png"
override val fontImg = Image(fontRef)
override val fontW = fontImg.width / 16
override val fontH = fontImg.height / 16
override val font = ColouredFastFont(this, fontRef, fontW, fontH)
override val colourScreen = Color.black
}

View File

@@ -0,0 +1,194 @@
/*
* $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());
}
}
}

View File

@@ -0,0 +1,411 @@
package net.torvald.terrarum.virtualcomputer.terminal
import net.torvald.aa.AAFrame
import net.torvald.aa.ColouredFastFont
import net.torvald.terrarum.blendNormal
import net.torvald.terrarum.blendMul
import net.torvald.terrarum.blendScreen
import org.lwjgl.BufferUtils
import org.lwjgl.openal.AL
import org.lwjgl.openal.AL10
import org.lwjgl.openal.AL11
import org.newdawn.slick.*
import java.nio.ByteBuffer
/**
* Default text terminal, four text colours (black, grey, lgrey, white).
*
* Created by minjaesong on 16-09-07.
*/
open class SimpleTextTerminal(
val phosphor: Color, override val width: Int, override val height: Int
) : Terminal {
/**
* Terminals must support AT LEAST 4 colours.
* Color index 0 must be default background, index 3 must be default foreground
*/
open protected val colours = arrayOf(
Color(0x00, 0x00, 0x00), // black
Color(0xff, 0xff, 0xff), // white
Color(0x55, 0x55, 0x55), // dim grey
Color(0xaa, 0xaa, 0xaa) // light grey
) // THESE ARE THE STANDARD
override val coloursCount = colours.size
open protected val backDefault = 0 // STANDARD
open protected val foreDefault = 3 // STANDARD
override var backColour = backDefault
override var foreColour = foreDefault
private val colourKey: Int
get() = backColour.shl(4).plus(foreColour).and(0xFF)
override var cursorX = 0
override var cursorY = 0
override var cursorBlink = true
val screenBuffer = AAFrame(width, height)
open protected val fontRef = "./assets/graphics/fonts/MDA.png"
open protected val fontImg = Image(fontRef)
open protected val fontW = fontImg.width / 16
open protected val fontH = fontImg.height / 16
open protected val font = ColouredFastFont(this, fontRef, fontW, fontH)
override val displayW = fontW * width
override val displayH = fontH * height
private val TABSIZE = 4
private val ASCII_NUL = 0.toChar()
private var cursorBlinkTimer = 0
private val cursorBlinkLen = 250
private var cursorBlinkOn = true
override fun getColor(index: Int): Color = colours[index]
override fun update(gc: GameContainer, delta: Int) {
cursorBlinkTimer = cursorBlinkTimer.plus(delta)
if (cursorBlinkTimer > cursorBlinkLen) {
cursorBlinkTimer -= cursorBlinkLen
cursorBlinkOn = !cursorBlinkOn
}
wrap()
// beep AL-related
if (beepSource != null && AL10.alGetSourcei(beepSource!!, AL10.AL_SOURCE_STATE) != AL10.AL_PLAYING) {
AL10.alDeleteSources(beepSource!!)
AL10.alDeleteBuffers(beepBuffer!!)
beepSource = null
beepBuffer == null
}
}
private fun wrap() {
// wrap cursor
if (cursorX < 0 && cursorY <= 0) {
setCursor(0, 0)
}
else if (cursorX >= width) {
setCursor(0, cursorY + 1)
}
else if (cursorX < 0) {
setCursor(width - 1, cursorY - 1)
}
// auto scroll up
if (cursorY >= height) {
scroll()
}
}
open protected val colourScreen = Color(0x191919)
/**
* pass UIcanvas to the parameter "g"
*/
override fun render(gc: GameContainer, g: Graphics) {
g.font = font
blendNormal()
for (y in 0..height - 1) {
for (x in 0..width - 1) {
val ch = screenBuffer.getChar(x, y)
// background
g.color = getColor(screenBuffer.getBackgroundColour(x, y))
g.fillRect(fontW * x.toFloat(), fontH * y.toFloat(), fontW.toFloat(), fontH.toFloat())
// foreground
if (ch.toInt() != 0 && ch.toInt() != 32) {
g.color = getColor(screenBuffer.getForegroundColour(x, y))
g.drawString(
Character.toString(ch),
fontW * x.toFloat(), fontH * y.toFloat())
}
}
}
// cursor
g.color = getColor(foreDefault)
if (cursorBlinkOn && cursorBlink)
g.fillRect(
fontW * cursorX.toFloat(),
fontH * cursorY.toFloat(),
fontW.toFloat(),
fontH.toFloat()
)
// not-pure-black screen
g.color = colourScreen
blendScreen()
g.fillRect(0f, 0f, displayW.toFloat(), displayH.toFloat())
// colour overlay
g.color = phosphor
blendMul()
g.fillRect(0f, 0f, displayW.toFloat(), displayH.toFloat())
blendNormal()
}
override fun setCursor(x: Int, y: Int) {
cursorX = x
cursorY = y
}
/** Emits a bufferChar. Does not move cursor
* It is also not affected by the control sequences; just print them out as symbol */
override fun emitChar(bufferChar: Int) {
screenBuffer.drawBuffer(cursorX, cursorY, bufferChar.toChar())
}
/** Emits a char. Does not move cursor
* It is also not affected by the control sequences; just print them out as symbol */
override fun emitChar(c: Char) {
screenBuffer.drawBuffer(cursorX, cursorY, c.toInt().and(0xFF).toChar(), colourKey)
}
val asciiControlInUse = charArrayOf(
ASCII_NUL,
ASCII_BEL,
ASCII_BS,
ASCII_TAB,
ASCII_LF,
ASCII_FF,
ASCII_CR,
ASCII_DEL,
ASCII_DC1,
ASCII_DC2,
ASCII_DC3,
ASCII_DC4
)
/** Prints a char and move cursor accordingly. */
override fun printChar(c: Char) {
wrap()
if (c >= ' ' && c.toInt() != 127) {
emitChar(c)
cursorX += 1
}
else {
when (c) {
ASCII_BEL -> beep()
ASCII_BS -> { cursorX -= 1; wrap() }
ASCII_TAB -> { cursorX = (cursorX).div(TABSIZE).times(TABSIZE) + TABSIZE }
ASCII_LF -> { cursorX = 0; cursorY += 1; wrap() }
ASCII_FF -> clear()
ASCII_CR -> { cursorX = 0 }
ASCII_DEL -> { cursorX -= 1; wrap(); emitChar(colourKey.shl(8)) }
ASCII_DC1, ASCII_DC2, ASCII_DC3, ASCII_DC4 -> { foreColour = c - ASCII_DC1 }
}
}
}
/** Emits a string and move cursor accordingly. */
override fun printString(s: String, x: Int, y: Int) {
setCursor(x, y)
emitString(s)
val absCursorPos = cursorX + cursorY * width + s.length
setCursor(absCursorPos % width, absCursorPos / width)
printChar(ASCII_LF)
}
/** Emits a string. Does not move cursor */
override fun emitString(s: String) {
val x = cursorX
val y = cursorY
for (i in 0..s.length - 1)
printChar(s[i])
setCursor(x, y)
}
override fun clear() {
screenBuffer.clear(backColour)
cursorX = 0
cursorY = 0
}
override fun clearLine() {
for (i in 0..width - 1)
screenBuffer.drawBuffer(i, cursorY, 0.toChar(), colourKey)
}
override fun scroll(amount: Int) {
val offset = amount * width
for (i in offset..screenBuffer.sizeof.ushr(1) - 1) {
screenBuffer.frameBuffer[i - offset] = screenBuffer.frameBuffer[i]
}
for (c in 1..amount) {
cursorY -= 1
clearLine()
}
}
override fun setColour(back: Int, fore: Int) {
backColour = back
foreColour = fore
}
override fun resetColour() {
backColour = backDefault
foreColour = foreDefault
}
private val sampleRate = 22050
private val maxDuration = 10000
private val beepSamples = maxDuration.div(1000).times(sampleRate)
private var beepSource: Int? = null
private var beepBuffer: Int? = null
override fun beep(freq: Float, duration: Int) {
throw NotImplementedError("errenous OpenAL behaviour; *grunts*")
val audioData = BufferUtils.createByteBuffer(duration.times(sampleRate).div(1000))
var chop = false
val realDuration = Math.min(maxDuration, duration)
for (i in 0..realDuration - 1) {
if (i.mod(freq) < 1.0) chop = !chop
audioData.put(if (chop) 0xFF.toByte() else 0x00.toByte())
}
audioData.rewind()
// Clear error stack.
AL10.alGetError()
beepBuffer = AL10.alGenBuffers()
checkALError()
try {
AL10.alBufferData(beepBuffer!!, AL10.AL_FORMAT_MONO8, audioData, sampleRate)
checkALError()
beepSource = AL10.alGenSources()
checkALError()
try {
AL10.alSourceQueueBuffers(beepSource!!, beepBuffer!!)
checkALError()
AL10.alSource3f(beepSource!!, AL10.AL_POSITION, 0f, 0f, 1f)
AL10.alSourcef(beepSource!!, AL10.AL_REFERENCE_DISTANCE, 1f)
AL10.alSourcef(beepSource!!, AL10.AL_MAX_DISTANCE, 1f)
AL10.alSourcef(beepSource!!, AL10.AL_GAIN, 0.3f)
checkALError()
AL10.alSourcePlay(beepSource!!)
checkALError()
}
catch (e: ALException) {
AL10.alDeleteSources(beepSource!!)
}
}
catch (e: ALException) {
if (beepSource != null) AL10.alDeleteSources(beepSource!!)
}
/*def checkFinished = AL10.alGetSourcei(source, AL10.AL_SOURCE_STATE) != AL10.AL_PLAYING && {
AL10.alDeleteSources(source)
AL10.alDeleteBuffers(buffer)
true
}*/
}
// Custom implementation of Util.checkALError() that uses our custom exception.
private fun checkALError() {
val errorCode = AL10.alGetError()
if (errorCode != AL10.AL_NO_ERROR) {
throw ALException(errorCode)
}
}
/** for "beep code" on modern BIOS. Pattern: - . */
override fun beep(pattern: String) {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override var lastInputByte: Int = -1
var sb: StringBuilder = StringBuilder()
private var inputOpen = false
/**
* Technically, this is different from Java's InputStream
*/
fun openInput() {
inputOpen = true
if (DEBUG) println("[SimpleTextTerminal] openInput()")
}
fun closeInput(): String {
inputOpen = false
val ret = sb.toString()
sb = StringBuilder()
if (DEBUG) println("[SimpleTextTerminal] closeInput(), $ret")
return ret
}
override fun keyPressed(key: Int, c: Char) {
lastInputByte = c.toInt()
if (inputOpen) {
if (c == ASCII_CR)
printChar(ASCII_LF)
else
printChar(c)
if (!asciiControlInUse.contains(c)) sb.append(c)
else if (c == ASCII_DEL && sb.length > 0) sb.deleteCharAt(sb.length - 1)
}
}
override fun getKeyPress(): Int? = lastInputByte
private fun isOOB(x: Int, y: Int) =
(x < 0 || y < 0 || x >= width || y >= height)
companion object {
val AMBER = Color(255, 183, 0) // P3, 602 nm
val IBM_GREEN = Color(74, 255, 0) // P39, 525 nm
val WHITE = Color(228, 234, 255) // P4, 7 500 K
val ELECTRIC_BLUE = Color(0, 239, 255) // imaginary, 486 nm
val RED = Color(250, 0, 0) // <= 645 nm
val ASCII_BEL = 7.toChar() // *BEEP!*
val ASCII_BS = 8.toChar() // x = x - 1
val ASCII_TAB = 9.toChar() // move cursor to next (TABSIZE * yy) pos (5 -> 8, 3- > 4, 4 -> 8)
val ASCII_LF = 10.toChar() // new line
val ASCII_FF = 12.toChar() // new page
val ASCII_CR = 13.toChar() // x <- 0
val ASCII_DEL = 127.toChar() // backspace and delete char
val ASCII_DC1 = 17.toChar() // foreground colour 0
val ASCII_DC2 = 18.toChar() // foreground colour 1
val ASCII_DC3 = 19.toChar() // foreground colour 2
val ASCII_DC4 = 20.toChar() // foreground colour 3
}
private val DEBUG = true
}
class ALException(errorCode: Int) : Exception("ALerror: $errorCode") {
}

View File

@@ -0,0 +1,77 @@
package net.torvald.terrarum.virtualcomputer.terminal
import org.newdawn.slick.Color
import org.newdawn.slick.GameContainer
import org.newdawn.slick.Graphics
import org.newdawn.slick.Input
/**
* A tty (terminal)
*
* Framebuffer : use net.torvald.aa.AAFrame
*
* Background color is fixed; text color is variable
*
* Created by minjaesong on 16-09-07.
*/
interface Terminal {
val width: Int
val height: Int
val coloursCount: Int
var cursorX: Int
var cursorY: Int
var cursorBlink: Boolean
var backColour: Int
var foreColour: Int
var lastInputByte: Int
// to be used in UI
val displayW: Int
val displayH: Int
fun getColor(index: Int): Color
fun update(gc: GameContainer, delta: Int)
fun render(gc: GameContainer, g: Graphics)
fun keyPressed(key: Int, c: Char)
// API calls
fun setCursor(x: Int, y: Int)
/** Emits a bufferChar. Does not move cursor
* It is also not affected by the control sequences; just print them out as symbol */
fun emitChar(bufferChar: Int)
/** Emits a char. Does not move cursor
* It is also not affected by the control sequences; just print them out as symbol */
fun emitChar(c: Char)
/** Prints a char and move cursor accordingly. */
fun printChar(c: Char)
/** Emits a string. Does not move cursor */
fun emitString(s: String)
/** Emits a string and move cursor accordingly. */
fun printString(s: String, x: Int = cursorX, y: Int = cursorY)
fun clear()
fun clearLine()
fun scroll(amount: Int = 1)
fun setColour(back: Int, fore: Int)
fun resetColour()
/**
* @param freg: Frequency (float)
* @param duration: milliseconds
*/
fun beep(freq: Float = 1000f, duration: Int = 200)
/** for "beep code" on modern BIOS. Pattern: - . */
fun beep(pattern: String)
/** Requires keyPressed() event to be processed.
*
* null indicates the input stream is waiting for an input
*
* implementation:
*
* private var lastInputByte: Int? = null
* override fun keyPressed(key: Int, c: Char) {
lastInputByte = c.toInt()
lastInputByte = null
}
*/
fun getKeyPress(): Int?
}

View File

@@ -0,0 +1,15 @@
package net.torvald.terrarum.virtualcomputer.terminal
import org.lwjgl.input.Keyboard
import java.io.InputStream
/**
* Created by minjaesong on 16-09-10.
*/
class TerminalInputStream(val term: Terminal) : InputStream() {
override fun read(): Int {
val ret = term.lastInputByte
term.lastInputByte = -1
return ret
}
}

View File

@@ -0,0 +1,170 @@
package net.torvald.terrarum.virtualcomputer.terminal;
import li.cil.repack.com.naef.jnlua.LuaException;
import li.cil.repack.com.naef.jnlua.LuaRuntimeException;
import li.cil.repack.com.naef.jnlua.LuaState;
import java.io.*;
/**
* Created by minjaesong on 16-09-10.
*/
public class TerminalLuaConsole {
// -- 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);
}
private PrintStream out;
// -- State
private LuaState luaState;
// -- Construction
/**
* Creates a new instance.
*/
public TerminalLuaConsole(Terminal term) {
this(EMPTY_ARGS, term);
}
/**
* 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 TerminalLuaConsole(String[] args, Terminal term) {
out = new TerminalPrintStream(term);
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
out.println(String.format("JNLua %s Console using Lua %s.",
LuaState.VERSION, LuaState.LUA_VERSION));
out.print("Type 'go' on an empty line to evaluate a chunk. ");
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) {
out.print("IO error: ");
out.print(e.getMessage());
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) {
out.print(", ");
}
switch (luaState.type(i)) {
case BOOLEAN:
out.print(Boolean.valueOf(luaState.toBoolean(i)));
break;
case NUMBER:
case STRING:
out.print(luaState.toString(i));
break;
default:
out.print(luaState.typeName(i));
}
}
out.print("\t#msec=");
out.print(String.format("%.3f", (stop - start) / 1000000.0));
out.println();
} catch (LuaRuntimeException e) {
e.printLuaStackTrace();
} catch (LuaException e) {
System.err.println(e.getMessage());
}
}
}

View File

@@ -0,0 +1,15 @@
package net.torvald.terrarum.virtualcomputer.terminal
import java.io.OutputStream
import java.io.PrintStream
/**
* Created by minjaesong on 16-09-10.
*/
class TerminalPrintStream(val term: Terminal) : PrintStream(TerminalOutputStream(term)) {
}
class TerminalOutputStream(val term: Terminal) : OutputStream() {
override fun write(b: Int) = term.printChar(b.and(0xFF).toChar())
}