gdx 1.10/lwjgl3 migration; removing old Lua stuffs

This commit is contained in:
minjaesong
2021-07-27 12:43:01 +09:00
parent f75b5da0e1
commit a91156ac21
323 changed files with 937 additions and 12100 deletions

View File

@@ -1,4 +1,4 @@
module terrarum {
module terrarum.terrarum {
// java
requires java.desktop;
requires java.logging;
@@ -6,11 +6,14 @@ module terrarum {
// kotlin
requires kotlin.stdlib;
requires kotlin.test;
// gdx
requires gdx;
requires gdx.backend.lwjgl;
requires gdx.controllers;
requires gdx.platform;
requires gdx.backend.lwjgl3;
requires gdx.controllers.core;
requires gdx.controllers.desktop;
// terrarum
requires TerrarumSansBitmap;
@@ -19,8 +22,8 @@ module terrarum {
// etc
requires GetCpuName;
requires jxinput;
requires gson;
requires commons.codec;
requires com.google.gson;
requires org.apache.commons.codec;
requires commons.csv;
requires jxinput;
}

View File

@@ -238,7 +238,7 @@ data class CIEXYZ(var X: Float = 0f, var Y: Float = 0f, var Z: Float = 0f, var a
data class CIEYXY(val yy: Float = 0f, var x: Float = 0f, var y: Float = 0f, var alpha: Float = 1f) {
init {
if (yy < 0f || x < 0f || y < 0f)
throw IllegalArgumentException("Value range error - parametres of YXY cannot be negative: ($yy, $x, $y)")
throw IllegalArgumentException("Value range error - parameters of YXY cannot be negative: ($yy, $x, $y)")
}
}

View File

@@ -3,8 +3,8 @@ package net.torvald.parametricsky
import com.badlogic.gdx.Game
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Screen
import com.badlogic.gdx.backends.lwjgl.LwjglApplication
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
@@ -284,10 +284,8 @@ class Application : Game() {
fun main(args: Array<String>) {
val config = LwjglApplicationConfiguration()
config.width = WIDTH
config.height = HEIGHT
config.foregroundFPS = 0
val config = Lwjgl3ApplicationConfiguration()
config.setWindowedMode(WIDTH, HEIGHT)
LwjglApplication(Application(), config)
Lwjgl3Application(Application(), config)
}

View File

@@ -2,8 +2,8 @@ package net.torvald.spriteassembler
import com.badlogic.gdx.Game
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.backends.lwjgl.LwjglApplication
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
@@ -309,15 +309,14 @@ class SpriteAssemblerPreview: Game() {
}
fun main(args: Array<String>) {
val appConfig = LwjglApplicationConfiguration()
appConfig.resizable = false
appConfig.width = 512
appConfig.height = 1024
appConfig.foregroundFPS = 5
appConfig.backgroundFPS = 5
val appConfig = Lwjgl3ApplicationConfiguration()
appConfig.setWindowedMode(512, 1024)
appConfig.setIdleFPS(5)
appConfig.setForegroundFPS(5)
appConfig.setResizable(false)
val gdxWindow = SpriteAssemblerPreview()
LwjglApplication(gdxWindow, appConfig)
Lwjgl3Application(gdxWindow, appConfig)
SpriteAssemblerApp(gdxWindow)
}

View File

@@ -2,8 +2,8 @@ package net.torvald.terrarum;
import com.badlogic.gdx.*;
import com.badlogic.gdx.audio.AudioDevice;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
import com.badlogic.gdx.controllers.Controllers;
import com.badlogic.gdx.graphics.*;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
@@ -40,6 +40,7 @@ import net.torvald.util.ArrayListMap;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
@@ -94,7 +95,7 @@ public class AppLoader implements ApplicationListener {
* @param appConfig LWJGL(2) Application Configuration
* @param injectScreen GDX Screen you want to run
*/
public AppLoader(LwjglApplicationConfiguration appConfig, Screen injectScreen) {
public AppLoader(Lwjgl3ApplicationConfiguration appConfig, Screen injectScreen) {
AppLoader.injectScreen = injectScreen;
AppLoader.appConfig = appConfig;
}
@@ -102,9 +103,9 @@ public class AppLoader implements ApplicationListener {
/**
* Initialise the application with default game screen
*
* @param appConfig LWJGL(2) Application Configuration
* @param appConfig LWJGL3 Application Configuration
*/
public AppLoader(LwjglApplicationConfiguration appConfig) {
public AppLoader(Lwjgl3ApplicationConfiguration appConfig) {
AppLoader.appConfig = appConfig;
}
@@ -148,14 +149,6 @@ public class AppLoader implements ApplicationListener {
public static final int GLOBAL_FRAMERATE_LIMIT = 300;
public static final float TV_SAFE_GRAPHICS = 0.05f; // as per EBU recommendation (https://tech.ebu.ch/docs/r/r095.pdf)
public static final float TV_SAFE_ACTION = 0.035f; // as per EBU recommendation (https://tech.ebu.ch/docs/r/r095.pdf)
public static int getTvSafeGraphicsWidth() { return Math.round(screenW * TV_SAFE_GRAPHICS); }
public static int getTvSafeGraphicsHeight() { return Math.round(screenH * TV_SAFE_GRAPHICS); }
public static int getTvSafeActionWidth() { return Math.round(screenW * TV_SAFE_ACTION); }
public static int getTvSafeActionHeight() { return Math.round(screenH * TV_SAFE_ACTION); }
/**
* These languages won't distinguish regional differences (e.g. enUS and enUK, frFR and frCA)
*/
@@ -192,7 +185,8 @@ public class AppLoader implements ApplicationListener {
private static boolean resizeRequested = false;
private static Point2i resizeReqSize;
public static LwjglApplicationConfiguration appConfig;
public static Lwjgl3ApplicationConfiguration appConfig;
public static TerrarumScreenSize screenSize;
public static GameFontBase fontGame;
public static TinyAlphNum fontSmallNumbers;
@@ -209,10 +203,6 @@ public class AppLoader implements ApplicationListener {
public static ArrayListMap debugTimers = new ArrayListMap<String, Long>();
public static final int defaultW = 1280;
public static final int defaultH = 720;
public static final int minimumW = 1080;
public static final int minimumH = 720;
public static final String FONT_DIR = "assets/graphics/fonts/terrarum-sans-bitmap";
@@ -238,15 +228,6 @@ public class AppLoader implements ApplicationListener {
private static Screen currenScreen;
private static LoadScreenBase currentSetLoadScreen;
public static int screenW = 0;
public static int screenH = 0;
public static float screenWf = 0f;
public static float screenHf = 0f;
public static int halfScreenW = 0;
public static int halfScreenH = 0;
public static float halfScreenWf = 0f;
public static float halfScreenHf = 0f;
public static float aspectRatio = 0f;
public static Texture textureWhiteSquare;
public static Texture textureWhiteCircle;
@@ -315,35 +296,37 @@ public class AppLoader implements ApplicationListener {
ShaderProgram.pedantic = false;
LwjglApplicationConfiguration appConfig = new LwjglApplicationConfiguration();
appConfig.useGL30 = false; // https://stackoverflow.com/questions/46753218/libgdx-should-i-use-gl30
appConfig.vSyncEnabled = getConfigBoolean("usevsync");
appConfig.resizable = false;//true;
appConfig.width = getConfigInt("screenwidth");
if (appConfig.width % 2 == 1) appConfig.width -= 1;
if (appConfig.width < minimumW) appConfig.width = minimumW;
appConfig.height = getConfigInt("screenheight");
if (appConfig.height % 2 == 1) appConfig.height -= 1;
if (appConfig.height < minimumH) appConfig.height = minimumH;
appConfig.backgroundFPS = Math.min(GLOBAL_FRAMERATE_LIMIT, getConfigInt("displayfps"));
appConfig.foregroundFPS = Math.min(GLOBAL_FRAMERATE_LIMIT, getConfigInt("displayfps"));
appConfig.title = GAME_NAME;
appConfig.forceExit = true; // it seems KDE 5 likes this one better...
// (Plasma freezes upon app exit. with forceExit = true, it's only frozen for a minute; with forceExit = false, it's indefinite)
appConfig.samples = 4; // force the AA on, if the graphics driver didn't do already
screenSize = new TerrarumScreenSize(getConfigInt("screenwidth"), getConfigInt("screenheight"));
int width = screenSize.getScreenW();
int height = screenSize.getScreenH();
if (appConfig.backgroundFPS <= 0) appConfig.backgroundFPS = GLOBAL_FRAMERATE_LIMIT;
if (appConfig.foregroundFPS <= 0) appConfig.foregroundFPS = GLOBAL_FRAMERATE_LIMIT;
Lwjgl3ApplicationConfiguration appConfig = new Lwjgl3ApplicationConfiguration();
//appConfig.useGL30 = false; // https://stackoverflow.com/questions/46753218/libgdx-should-i-use-gl30
appConfig.useVsync(getConfigBoolean("usevsync"));
appConfig.setResizable(false);
appConfig.setWindowedMode(width, height);
int fps = Math.min(GLOBAL_FRAMERATE_LIMIT, getConfigInt("displayfps"));
if (fps <= 0) fps = GLOBAL_FRAMERATE_LIMIT;
appConfig.setIdleFPS(fps);
appConfig.setForegroundFPS(fps);
appConfig.setTitle(GAME_NAME);
//appConfig.forceExit = true; // it seems KDE 5 likes this one better...
// (Plasma freezes upon app exit. with forceExit = true, it's only frozen for a minute; with forceExit = false, it's indefinite)
//appConfig.samples = 4; // force the AA on, if the graphics driver didn't do already
// load app icon
int[] appIconSizes = new int[]{256,128,64,32,16};
ArrayList<String> appIconPaths = new ArrayList<>();
for (int size : appIconSizes) {
String name = "assets/appicon" + size + ".png";
if (new File("./" + name).exists()) {
appConfig.addIcon(name, Files.FileType.Internal);
appIconPaths.add("./" + name);
}
}
Object[] iconPathsTemp = appIconPaths.toArray();
appConfig.setWindowIcon(Arrays.copyOf(iconPathsTemp, iconPathsTemp.length, String[].class));
//if (args.length == 1 && args[0].equals("isdev=true")) {
IS_DEVELOPMENT_BUILD = true;
// safe area box
@@ -356,7 +339,7 @@ public class AppLoader implements ApplicationListener {
// set some more configuration vars
MULTITHREAD = THREAD_COUNT >= 3 && getConfigBoolean("multithread");
new LwjglApplication(new AppLoader(appConfig), appConfig);
new Lwjgl3Application(new AppLoader(appConfig), appConfig);
}
@Override
@@ -390,12 +373,12 @@ public class AppLoader implements ApplicationListener {
// set basis of draw
logoBatch = new SpriteBatch();
camera = new OrthographicCamera(((float) appConfig.width), ((float) appConfig.height));
camera = new OrthographicCamera((screenSize.getScreenWf()), (screenSize.getScreenHf()));
batch = new SpriteBatch();
shapeRender = new ShapeRenderer();
initViewPort(appConfig.width, appConfig.height);
initViewPort(screenSize.getScreenW(), screenSize.getScreenH());
// logo here :p
logo = new TextureRegion(new Texture(Gdx.files.internal("assets/graphics/logo_placeholder.tga")));
@@ -417,7 +400,7 @@ public class AppLoader implements ApplicationListener {
VertexAttribute.ColorUnpacked(),
VertexAttribute.TexCoords(0)
);
updateFullscreenQuad(appConfig.width, appConfig.height);
updateFullscreenQuad(screenSize.getScreenW(), screenSize.getScreenH());
// set up renderer info variables
@@ -562,7 +545,7 @@ public class AppLoader implements ApplicationListener {
screenshotRequested = false;
try {
Pixmap p = ScreenUtils.getFrameBufferPixmap(0, 0, appConfig.width, appConfig.height);
Pixmap p = ScreenUtils.getFrameBufferPixmap(0, 0, screenSize.getScreenW(), screenSize.getScreenH());
PixmapIO2.writeTGA(Gdx.files.absolute(defaultDir+"/Screenshot-"+String.valueOf(System.currentTimeMillis())+".tga"), p, true);
p.dispose();
@@ -592,8 +575,8 @@ public class AppLoader implements ApplicationListener {
setCameraPosition(0f, 0f);
int safetyTextLen = fontGame.getWidth(Lang.INSTANCE.get("APP_WARNING_HEALTH_AND_SAFETY"));
int logoPosX = (appConfig.width - logo.getRegionWidth() - safetyTextLen) >>> 1;
int logoPosY = Math.round(appConfig.height / 15f);
int logoPosX = (screenSize.getScreenW() - logo.getRegionWidth() - safetyTextLen) >>> 1;
int logoPosY = Math.round(screenSize.getScreenH() / 15f);
int textY = logoPosY + logo.getRegionHeight() - 16;
// draw logo reflection
@@ -605,8 +588,8 @@ public class AppLoader implements ApplicationListener {
logoBatch.draw(logo, logoPosX, logoPosY + logo.getRegionHeight());
}
else {
logoBatch.draw(logo, (appConfig.width - logo.getRegionWidth()) / 2f,
(appConfig.height - logo.getRegionHeight() * 2) / 2f + logo.getRegionHeight()
logoBatch.draw(logo, (screenSize.getScreenW() - logo.getRegionWidth()) / 2f,
(screenSize.getScreenH() - logo.getRegionHeight() * 2) / 2f + logo.getRegionHeight()
);
}
@@ -631,8 +614,8 @@ public class AppLoader implements ApplicationListener {
String s = Lang.INSTANCE.get("APP_CHINESE_HEALTHY_GAME_MSG_" + i);
fontGame.draw(logoBatch, s,
(appConfig.width - fontGame.getWidth(s)) >>> 1,
Math.round(appConfig.height * 12f / 15f + fontGame.getLineHeight() * (i - 1))
(screenSize.getScreenW() - fontGame.getWidth(s)) >>> 1,
Math.round(screenSize.getScreenH() * 12f / 15f + fontGame.getLineHeight() * (i - 1))
);
}
}
@@ -640,15 +623,15 @@ public class AppLoader implements ApplicationListener {
logoBatch.setColor(new Color(0x282828ff));
Texture tex1 = CommonResourcePool.INSTANCE.getAsTexture("title_health1");
Texture tex2 = CommonResourcePool.INSTANCE.getAsTexture("title_health2");
int virtualHeight = appConfig.height - logoPosY - logo.getRegionHeight() / 4;
int virtualHeightOffset = appConfig.height - virtualHeight;
logoBatch.draw(tex1, (appConfig.width - tex1.getWidth()) >>> 1, virtualHeightOffset + (virtualHeight >>> 1) - 16, tex1.getWidth(), -tex1.getHeight());
logoBatch.draw(tex2, (appConfig.width - tex2.getWidth()) >>> 1, virtualHeightOffset + (virtualHeight >>> 1) + 16 + tex2.getHeight(), tex2.getWidth(), -tex2.getHeight());
int virtualHeight = screenSize.getScreenH() - logoPosY - logo.getRegionHeight() / 4;
int virtualHeightOffset = screenSize.getScreenH() - virtualHeight;
logoBatch.draw(tex1, (screenSize.getScreenW() - tex1.getWidth()) >>> 1, virtualHeightOffset + (virtualHeight >>> 1) - 16, tex1.getWidth(), -tex1.getHeight());
logoBatch.draw(tex2, (screenSize.getScreenW() - tex2.getWidth()) >>> 1, virtualHeightOffset + (virtualHeight >>> 1) + 16 + tex2.getHeight(), tex2.getWidth(), -tex2.getHeight());
}
else {
logoBatch.draw(logo, (appConfig.width - logo.getRegionWidth()) / 2f,
(appConfig.height - logo.getRegionHeight() * 2) / 2f
logoBatch.draw(logo, (screenSize.getScreenW() - logo.getRegionWidth()) / 2f,
(screenSize.getScreenH() - logo.getRegionHeight() * 2) / 2f
);
}
@@ -662,45 +645,30 @@ public class AppLoader implements ApplicationListener {
//initViewPort(width, height);
screenW = width;
screenH = height;
screenSize.setDimension(width, height);
if (currenScreen != null) currenScreen.resize(screenW, screenH);
if (currenScreen != null) currenScreen.resize(screenSize.getScreenW(), screenSize.getScreenH());
updateFullscreenQuad(screenSize.getScreenW(), screenSize.getScreenH());
if (renderFBO == null ||
(renderFBO.getWidth() != screenW ||
renderFBO.getHeight() != screenH)
(renderFBO.getWidth() != screenSize.getScreenW() ||
renderFBO.getHeight() != screenSize.getScreenH())
) {
renderFBO = new FrameBuffer(
Pixmap.Format.RGBA8888,
screenW,
screenH,
screenSize.getScreenW(),
screenSize.getScreenH(),
false
);
}
appConfig.width = screenW;
appConfig.height = screenH;
halfScreenW = screenW / 2;
halfScreenH = screenH / 2;
screenWf = (float) screenW;
screenHf = (float) screenH;
halfScreenWf = (float) halfScreenW;
halfScreenHf = (float) halfScreenH;
aspectRatio = screenWf / screenHf;
updateFullscreenQuad(screenW, screenH);
printdbg(this, "Resize end");
}
public static void resizeScreen(int width, int height) {
resizeRequested = true;
resizeReqSize = new Point2i(Math.max(width, minimumW), Math.max(height, minimumH));
resizeReqSize = new Point2i(width, height);
}
@Override
@@ -798,7 +766,7 @@ public class AppLoader implements ApplicationListener {
currenScreen = screen;
currenScreen.show();
currenScreen.resize(appConfig.width, appConfig.height);
currenScreen.resize(screenSize.getScreenW(), screenSize.getScreenH());
System.gc();
@@ -847,7 +815,7 @@ public class AppLoader implements ApplicationListener {
private void setCameraPosition(float newX, float newY) {
camera.position.set((-newX + appConfig.width / 2), (-newY + appConfig.height / 2), 0f); // deliberate integer division
camera.position.set((-newX + screenSize.getScreenW() / 2), (-newY + screenSize.getScreenH() / 2), 0f); // deliberate integer division
camera.update();
logoBatch.setProjectionMatrix(camera.combined);
}

View File

@@ -2,8 +2,8 @@ package net.torvald.terrarum
import com.badlogic.gdx.ApplicationAdapter
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.backends.lwjgl.LwjglApplication
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.Texture
@@ -18,14 +18,11 @@ import net.torvald.terrarumsansbitmap.gdx.GameFontBase
*/
fun main(args: Array<String>) { // LWJGL 3 won't work? java.lang.VerifyError
val config = LwjglApplicationConfiguration()
//config.useGL30 = true
config.vSyncEnabled = false
config.resizable = false
config.width = 1072
config.height = 742
config.foregroundFPS = 9999
LwjglApplication(ColorLimiterTest, config)
val config = Lwjgl3ApplicationConfiguration()
config.useVsync(false)
config.setResizable(false)
config.setWindowedMode(1072, 742)
Lwjgl3Application(ColorLimiterTest, config)
}
object ColorLimiterTest : ApplicationAdapter() {

View File

@@ -4,7 +4,6 @@ import com.badlogic.gdx.Input
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.BlockCodex
/**
* Keys must be all lowercase
@@ -17,8 +16,8 @@ object DefaultConfig {
jsonObject.addProperty("displayfps", 0) // 0: no limit, non-zero: limit
jsonObject.addProperty("usevsync", false)
jsonObject.addProperty("screenwidth", AppLoader.defaultW)
jsonObject.addProperty("screenheight", AppLoader.defaultH)
jsonObject.addProperty("screenwidth", TerrarumScreenSize.defaultW)
jsonObject.addProperty("screenheight", TerrarumScreenSize.defaultH)
//jsonObject.addProperty("imtooyoungtodie", false) // no perma-death

View File

@@ -2,8 +2,8 @@ package net.torvald.terrarum
import com.badlogic.gdx.ApplicationAdapter
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.backends.lwjgl.LwjglApplication
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
import com.badlogic.gdx.graphics.*
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.glutils.ShaderProgram
@@ -15,14 +15,11 @@ import net.torvald.terrarumsansbitmap.gdx.GameFontBase
* Created by minjaesong on 2017-08-25.
*/
fun main(args: Array<String>) { // LWJGL 3 won't work? java.lang.VerifyError
val config = LwjglApplicationConfiguration()
//config.useGL30 = true
config.vSyncEnabled = false
config.resizable = false
config.width = 1072
config.height = 742
config.foregroundFPS = 9999
LwjglApplication(GlslTilingTest, config)
val config = Lwjgl3ApplicationConfiguration()
config.useVsync(false)
config.setResizable(false)
config.setWindowedMode(1072, 742)
Lwjgl3Application(GlslTilingTest, config)
}
object GlslTilingTest : ApplicationAdapter() {

View File

@@ -21,7 +21,7 @@ open class LoadScreenBase : ScreenAdapter(), Disposable {
internal var errorTrapped = false
internal var doContextChange = false
var camera = OrthographicCamera(AppLoader.screenWf, AppLoader.screenHf)
var camera = OrthographicCamera(AppLoader.screenSize.screenWf, AppLoader.screenSize.screenHf)
override fun show() {
messages.clear()
@@ -49,7 +49,7 @@ open class LoadScreenBase : ScreenAdapter(), Disposable {
}
initViewPort(AppLoader.screenW, AppLoader.screenH)
initViewPort(AppLoader.screenSize.screenW, AppLoader.screenSize.screenH)
}
fun initViewPort(width: Int, height: Int) {
@@ -77,6 +77,6 @@ open class LoadScreenBase : ScreenAdapter(), Disposable {
}
override fun resize(width: Int, height: Int) {
initViewPort(AppLoader.screenW, AppLoader.screenH)
initViewPort(AppLoader.screenSize.screenW, AppLoader.screenSize.screenH)
}
}

View File

@@ -12,8 +12,8 @@ class ModOptionsHost : UICanvas() {
private val moduleAreaHMargin = 48
private val moduleAreaBorder = 8
override var width = AppLoader.screenW - UIRemoCon.remoConWidth - moduleAreaHMargin
override var height = AppLoader.screenH - moduleAreaHMargin * 2
override var width = AppLoader.screenSize.screenW - UIRemoCon.remoConWidth - moduleAreaHMargin
override var height = AppLoader.screenSize.screenH - moduleAreaHMargin * 2
override fun updateUI(delta: Float) {
}

View File

@@ -2,8 +2,8 @@ package net.torvald.terrarum;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Files;
import com.badlogic.gdx.backends.lwjgl.LwjglApplication;
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application;
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration;
import com.badlogic.gdx.graphics.Texture;
import net.torvald.terrarumsansbitmap.gdx.GameFontBase;
@@ -14,37 +14,22 @@ import java.io.File;
*/
public class MusicComposerApp extends ApplicationAdapter {
public static LwjglApplicationConfiguration appConfig;
public static Lwjgl3ApplicationConfiguration appConfig;
public static GameFontBase fontGame;
public MusicComposerApp(LwjglApplicationConfiguration appConfig) {
public MusicComposerApp(Lwjgl3ApplicationConfiguration appConfig) {
this.appConfig = appConfig;
}
public void main(String[] args) {
LwjglApplicationConfiguration appConfig = new LwjglApplicationConfiguration();
appConfig.useGL30 = true; // utilising some GL trickeries, need this to be TRUE
appConfig.resizable = false;//true;
//appConfig.width = 1110; // photographic ratio (1.5:1)
//appConfig.height = 740; // photographic ratio (1.5:1)
appConfig.width = 1000;;;
appConfig.height = 666;
appConfig.backgroundFPS = 9999;
appConfig.foregroundFPS = 9999;
appConfig.title = "Speelklok";
appConfig.forceExit = false;
Lwjgl3ApplicationConfiguration appConfig = new Lwjgl3ApplicationConfiguration();
// load app icon
int[] appIconSizes = new int[]{256,128,64,32,16};
for (int size : appIconSizes) {
String name = "assets/appicon" + size + ".png";
if (new File("./" + name).exists()) {
appConfig.addIcon(name, Files.FileType.Internal);
}
}
appConfig.setResizable(false);
appConfig.setWindowedMode(1280, 720);
appConfig.setTitle("Speelklok");
new LwjglApplication(new MusicComposerApp(appConfig), appConfig);
new Lwjgl3Application(new MusicComposerApp(appConfig), appConfig);
}
@Override

View File

@@ -1,18 +1,18 @@
package net.torvald.terrarum
import com.badlogic.gdx.ApplicationAdapter
import com.badlogic.gdx.backends.lwjgl.LwjglApplication
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
import com.badlogic.gdx.graphics.Color
import com.glester.jopus.JOpusBufferFile
fun main(args: Array<String>) {
val config = LwjglApplicationConfiguration()
LwjglApplication(OpusDecodeTest, config)
val config = Lwjgl3ApplicationConfiguration()
config.useVsync(false)
config.setResizable(false)
config.setWindowedMode(1072, 742)
Lwjgl3Application(OpusDecodeTest, config)
}
/**
@@ -21,8 +21,6 @@ fun main(args: Array<String>) {
object OpusDecodeTest : ApplicationAdapter() {
private lateinit var opusFile: JOpusBufferFile
override fun create() {
}

View File

@@ -65,13 +65,13 @@ object PostProcessor : Disposable {
debugUI.setPosition(0, 0)
batch = SpriteBatch()
camera = OrthographicCamera(AppLoader.screenWf, AppLoader.screenHf)
camera = OrthographicCamera(AppLoader.screenSize.screenWf, AppLoader.screenSize.screenHf)
camera.setToOrtho(true)
batch.projectionMatrix = camera.combined
shapeRenderer = ShapeRenderer()
Gdx.gl20.glViewport(0, 0, AppLoader.appConfig.width, AppLoader.appConfig.height)
Gdx.gl20.glViewport(0, 0, AppLoader.screenSize.screenW, AppLoader.screenSize.screenH)
}
@@ -93,7 +93,7 @@ object PostProcessor : Disposable {
batch.color = Color.WHITE
batch.inUse {
it.draw(functionRowHelper,
(AppLoader.screenW - functionRowHelper.width) / 2f,
(AppLoader.screenSize.screenW - functionRowHelper.width) / 2f,
functionRowHelper.height.toFloat(),
functionRowHelper.width.toFloat(),
functionRowHelper.height * -1f
@@ -120,7 +120,7 @@ object PostProcessor : Disposable {
if (AppLoader.IS_DEVELOPMENT_BUILD && Terrarum.ingame != null) {
batch.inUse {
batch.color = safeAreaCol
AppLoader.fontGame.draw(it, thisIsDebugStr, 5f, AppLoader.screenH - 24f)
AppLoader.fontGame.draw(it, thisIsDebugStr, 5f, AppLoader.screenSize.screenH - 24f)
}
}
}
@@ -147,37 +147,37 @@ object PostProcessor : Disposable {
}
private fun drawSafeArea() {
val tvSafeAreaW = AppLoader.getTvSafeGraphicsWidth().toFloat()
val tvSafeAreaH = AppLoader.getTvSafeGraphicsHeight().toFloat()
val tvSafeArea2W = AppLoader.getTvSafeActionWidth().toFloat()
val tvSafeArea2H = AppLoader.getTvSafeActionHeight().toFloat()
val tvSafeAreaW = AppLoader.screenSize.tvSafeGraphicsWidth.toFloat()
val tvSafeAreaH = AppLoader.screenSize.tvSafeGraphicsHeight.toFloat()
val tvSafeArea2W = AppLoader.screenSize.tvSafeActionWidth.toFloat()
val tvSafeArea2H = AppLoader.screenSize.tvSafeActionHeight.toFloat()
shapeRenderer.inUse(ShapeRenderer.ShapeType.Line) {
// centre ind
shapeRenderer.color = safeAreaCol2
shapeRenderer.line(0f, 0f, AppLoader.screenWf, AppLoader.screenHf)
shapeRenderer.line(0f, AppLoader.screenHf, AppLoader.screenWf, 0f)
shapeRenderer.line(0f, 0f, AppLoader.screenSize.screenWf, AppLoader.screenSize.screenHf)
shapeRenderer.line(0f, AppLoader.screenSize.screenHf, AppLoader.screenSize.screenWf, 0f)
// safe action area
shapeRenderer.color = safeAreaCol2
shapeRenderer.rect(
tvSafeArea2W, tvSafeArea2H, AppLoader.screenW - 2 * tvSafeArea2W, AppLoader.screenH - 2 * tvSafeArea2H
tvSafeArea2W, tvSafeArea2H, AppLoader.screenSize.screenW - 2 * tvSafeArea2W, AppLoader.screenSize.screenH - 2 * tvSafeArea2H
)
// safe graphics area
shapeRenderer.color = safeAreaCol
shapeRenderer.rect(
tvSafeAreaW, tvSafeAreaH, AppLoader.screenW - 2 * tvSafeAreaW, AppLoader.screenH - 2 * tvSafeAreaH
tvSafeAreaW, tvSafeAreaH, AppLoader.screenSize.screenW - 2 * tvSafeAreaW, AppLoader.screenSize.screenH - 2 * tvSafeAreaH
)
// default res ind
shapeRenderer.color = defaultResCol
shapeRenderer.rect(
(AppLoader.screenW - AppLoader.minimumW).div(2).toFloat(),
(AppLoader.screenH - AppLoader.minimumH).div(2).toFloat(),
AppLoader.minimumW.toFloat(),
AppLoader.minimumH.toFloat()
(AppLoader.screenSize.screenW - TerrarumScreenSize.minimumW).div(2).toFloat(),
(AppLoader.screenSize.screenH - TerrarumScreenSize.minimumH).div(2).toFloat(),
TerrarumScreenSize.minimumW.toFloat(),
TerrarumScreenSize.minimumH.toFloat()
)
}
@@ -192,14 +192,14 @@ object PostProcessor : Disposable {
batch.color = defaultResCol
AppLoader.fontSmallNumbers.draw(
batch, defaultResStr,
(AppLoader.screenW - AppLoader.minimumW).div(2).toFloat(),
(AppLoader.screenH - AppLoader.minimumH).div(2).toFloat()
(AppLoader.screenSize.screenW - TerrarumScreenSize.minimumW).div(2).toFloat(),
(AppLoader.screenSize.screenH - TerrarumScreenSize.minimumH).div(2).toFloat()
)
batch.color = currentResCol
AppLoader.fontSmallNumbers.draw(
batch, currentResStr,
AppLoader.screenW - 80f,
AppLoader.screenSize.screenW - 80f,
0f
)
}
@@ -213,8 +213,8 @@ object PostProcessor : Disposable {
}
}
private val defaultResStr = "${AppLoader.minimumW}x${AppLoader.minimumH}"
private val currentResStr = "${AppLoader.screenW}x${AppLoader.screenH}"
private val defaultResStr = "${TerrarumScreenSize.minimumW}x${TerrarumScreenSize.minimumH}"
private val currentResStr = "${AppLoader.screenSize.screenW}x${AppLoader.screenSize.screenH}"
private val safeAreaStr = "TV Safe Area"
private val versionStr = "Version ${AppLoader.getVERSION_STRING()}"
private val thisIsDebugStr = "${AppLoader.GAME_NAME} Develoment Build $versionStr"

View File

@@ -1,16 +1,13 @@
package net.torvald.terrarum
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.ScreenAdapter
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.jme3.math.FastMath
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.util.CircularArray
/**
* Created by minjaesong on 2017-07-13.
@@ -24,7 +21,7 @@ object SanicLoadScreen : LoadScreenBase() {
private var arrowObjPos = 0f // 0 means at starting position, regardless of screen position
private var arrowObjGlideOffsetX = 0f
private var arrowObjGlideSize = 0f
private val arrowGlideSpeed: Float; get() = AppLoader.screenW * 2f // pixels per sec
private val arrowGlideSpeed: Float; get() = AppLoader.screenSize.screenW * 2f // pixels per sec
private lateinit var arrowObjTex: Texture
private var glideTimer = 0f
private var glideDispY = 0f
@@ -63,7 +60,7 @@ object SanicLoadScreen : LoadScreenBase() {
}
val textX: Float; get() = (AppLoader.screenW * 0.72f).floor()
val textX: Float; get() = (AppLoader.screenSize.screenW * 0.72f).floor()
private var genuineSonic = false // the "NOW LOADING..." won't appear unless the arrow first run passes it (it's totally not a GenuineIntel tho)
@@ -75,8 +72,8 @@ object SanicLoadScreen : LoadScreenBase() {
val delta = Gdx.graphics.rawDeltaTime
glideDispY = AppLoader.screenH - 100f - AppLoader.fontGame.lineHeight
arrowObjGlideSize = arrowObjTex.width + 2f * AppLoader.screenW
glideDispY = AppLoader.screenSize.screenH - 100f - AppLoader.fontGame.lineHeight
arrowObjGlideSize = arrowObjTex.width + 2f * AppLoader.screenSize.screenW
@@ -137,14 +134,14 @@ object SanicLoadScreen : LoadScreenBase() {
AppLoader.batch.inUse {
initViewPort(AppLoader.screenW, AppLoader.screenH) // dunno, no render without this
initViewPort(AppLoader.screenSize.screenW, AppLoader.screenSize.screenH) // dunno, no render without this
it.projectionMatrix = camera.combined
blendNormal(AppLoader.batch)
// almost black background
it.color = Color(0x181818ff)
it.fillRect(0f, 0f, AppLoader.screenWf, AppLoader.screenHf)
it.fillRect(0f, 0f, AppLoader.screenSize.screenWf, AppLoader.screenSize.screenHf)
it.color = Color.WHITE
@@ -187,14 +184,14 @@ object SanicLoadScreen : LoadScreenBase() {
// message backgrounds
it.color = messageBackgroundColour
it.fillRect(0f, 60f, AppLoader.screenWf, 40f + (messages.size) * AppLoader.fontGame.lineHeight)
it.fillRect(0f, 60f, AppLoader.screenSize.screenWf, 40f + (messages.size) * AppLoader.fontGame.lineHeight)
// log messages
it.color = messageForegroundColour
messages.forEachIndexed { i, s ->
AppLoader.fontGame.draw(it,
s,
AppLoader.getTvSafeGraphicsWidth() + 16f,
AppLoader.screenSize.tvSafeGraphicsWidth + 16f,
80f + (messages.size - i - 1) * AppLoader.fontGame.lineHeight
)
}
@@ -204,7 +201,7 @@ object SanicLoadScreen : LoadScreenBase() {
AppLoader.batch.inUse {
// recycling part of the draw code //
initViewPort(AppLoader.screenW, AppLoader.screenH) // dunno, no render without this
initViewPort(AppLoader.screenSize.screenW, AppLoader.screenSize.screenH) // dunno, no render without this
it.projectionMatrix = camera.combined
blendNormal(AppLoader.batch)
@@ -212,14 +209,14 @@ object SanicLoadScreen : LoadScreenBase() {
// message backgrounds
it.color = messageBackgroundColour
it.fillRect(0f, 60f, AppLoader.screenWf, 40f + (messages.size) * AppLoader.fontGame.lineHeight)
it.fillRect(0f, 60f, AppLoader.screenSize.screenWf, 40f + (messages.size) * AppLoader.fontGame.lineHeight)
// log messages
it.color = messageForegroundColour
messages.forEachIndexed { i, s ->
AppLoader.fontGame.draw(it,
s,
AppLoader.getTvSafeGraphicsWidth() + 16f,
AppLoader.screenSize.tvSafeGraphicsWidth + 16f,
80f + (messages.size - i - 1) * AppLoader.fontGame.lineHeight
)
}

View File

@@ -2,8 +2,8 @@ package net.torvald.terrarum
import com.badlogic.gdx.ApplicationAdapter
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.backends.lwjgl.LwjglApplication
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
import com.badlogic.gdx.graphics.*
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.glutils.ShaderProgram
@@ -14,14 +14,11 @@ import net.torvald.terrarumsansbitmap.gdx.GameFontBase
* Created by minjaesong on 2017-08-11.
*/
fun main(args: Array<String>) { // LWJGL 3 won't work? java.lang.VerifyError
val config = LwjglApplicationConfiguration()
//config.useGL30 = true
config.vSyncEnabled = false
config.resizable = false
config.width = 1072
config.height = 742
config.foregroundFPS = 9999
LwjglApplication(ShitOnGlsl, config)
val config = Lwjgl3ApplicationConfiguration()
config.useVsync(false)
config.setResizable(false)
config.setWindowedMode(1072, 742)
Lwjgl3Application(ShitOnGlsl, config)
}
object ShitOnGlsl : ApplicationAdapter() {

View File

@@ -335,7 +335,7 @@ inline fun FrameBuffer.inAction(camera: OrthographicCamera?, batch: SpriteBatch?
//this.end()
FrameBufferManager.end()
camera?.setToOrtho(true, AppLoader.screenWf, AppLoader.screenHf)
camera?.setToOrtho(true, AppLoader.screenSize.screenWf, AppLoader.screenSize.screenHf)
camera?.update()
batch?.projectionMatrix = camera?.combined
}

View File

@@ -0,0 +1,48 @@
package net.torvald.terrarum
class TerrarumScreenSize(scrw: Int = defaultW, scrh: Int = defaultH) {
companion object {
const val minimumW = 1080
const val minimumH = 720
const val defaultW = 1280
const val defaultH = 720
const val TV_SAFE_GRAPHICS = 0.05f // as per EBU recommendation (https://tech.ebu.ch/docs/r/r095.pdf)
const val TV_SAFE_ACTION = 0.035f // as per EBU recommendation (https://tech.ebu.ch/docs/r/r095.pdf)
}
var screenW: Int = 0; private set
var screenH: Int = 0; private set
var screenWf: Float = 0f; private set
var screenHf: Float = 0f; private set
var halfScreenW: Int = 0; private set
var halfScreenH: Int = 0; private set
var halfScreenWf: Float = 0f; private set
var halfScreenHf: Float = 0f; private set
var aspectRatio: Float = 0f; private set
val tvSafeGraphicsWidth: Int; get() = Math.round(screenW * TV_SAFE_GRAPHICS)
val tvSafeGraphicsHeight: Int; get() = Math.round(screenH * TV_SAFE_GRAPHICS)
val tvSafeActionWidth: Int; get() = Math.round(screenW * TV_SAFE_ACTION)
val tvSafeActionHeight: Int; get() = Math.round(screenH * TV_SAFE_ACTION)
init {
setDimension(maxOf(minimumW, scrw), maxOf(minimumH, scrh))
}
fun setDimension(scrw: Int, scrh: Int) {
screenW = scrw and 0x7FFFFFFE
screenH = scrh and 0x7FFFFFFE
screenWf = scrw.toFloat()
screenHf = scrh.toFloat()
halfScreenW = screenW / 2
halfScreenH = screenH / 2
halfScreenWf = screenWf / 2f
halfScreenHf = screenHf / 2f
aspectRatio = screenWf / screenHf
}
}

View File

@@ -3,8 +3,8 @@ package net.torvald.terrarum
import com.badlogic.gdx.ApplicationAdapter
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Screen
import com.badlogic.gdx.backends.lwjgl.LwjglApplication
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
import com.badlogic.gdx.graphics.*
import com.badlogic.gdx.graphics.g2d.BitmapFont
import com.badlogic.gdx.graphics.g2d.SpriteBatch
@@ -45,7 +45,7 @@ class TestTestTest(val batch: SpriteBatch) : Screen {
fun enter() {
// init view port
camera = OrthographicCamera(AppLoader.screenWf, AppLoader.screenHf)
camera = OrthographicCamera(AppLoader.screenSize.screenWf, AppLoader.screenSize.screenHf)
img = Texture("assets/test_texture.tga")
@@ -57,14 +57,14 @@ class TestTestTest(val batch: SpriteBatch) : Screen {
blurFboA = FrameBuffer(Pixmap.Format.RGBA8888, img.width, img.height, false)
blurFboB = FrameBuffer(Pixmap.Format.RGBA8888, img.width, img.height, false)
worldFbo = FrameBuffer(Pixmap.Format.RGBA8888, AppLoader.screenW, AppLoader.screenH, false)
worldFbo = FrameBuffer(Pixmap.Format.RGBA8888, AppLoader.screenSize.screenW, AppLoader.screenSize.screenH, false)
//blurShader.begin()
//blurShader.setUniformf("iResolution", img.width.toFloat(), img.height.toFloat(), 0f)
//blurShader.end()
initViewPort(AppLoader.screenW, AppLoader.screenH)
initViewPort(AppLoader.screenSize.screenW, AppLoader.screenSize.screenH)
}
override fun render(delta: Float) {
@@ -135,7 +135,7 @@ class TestTestTest(val batch: SpriteBatch) : Screen {
batch.inUse {
batch.shader = null
camera.position.set(AppLoader.screenW / 2f - 50f, AppLoader.screenH / 2f - 50f, 0f)
camera.position.set(AppLoader.screenSize.screenW / 2f - 50f, AppLoader.screenSize.screenH / 2f - 50f, 0f)
camera.update()
batch.projectionMatrix = camera.combined
@@ -147,11 +147,11 @@ class TestTestTest(val batch: SpriteBatch) : Screen {
}
camera.setToOrtho(true, AppLoader.screenWf, AppLoader.screenHf)
camera.setToOrtho(true, AppLoader.screenSize.screenWf, AppLoader.screenSize.screenHf)
batch.projectionMatrix = camera.combined
batch.inUse {
camera.position.set(AppLoader.screenW / 2f, AppLoader.screenH / 2f, 0f)
camera.position.set(AppLoader.screenSize.screenW / 2f, AppLoader.screenSize.screenH / 2f, 0f)
camera.update()
batch.projectionMatrix = camera.combined
@@ -168,7 +168,7 @@ class TestTestTest(val batch: SpriteBatch) : Screen {
}
override fun show() {
initViewPort(AppLoader.screenW, AppLoader.screenH)
initViewPort(AppLoader.screenSize.screenW, AppLoader.screenSize.screenH)
}
override fun pause() {
@@ -216,12 +216,9 @@ object TestTestMain : ApplicationAdapter() {
}
fun main(args: Array<String>) { // LWJGL 3 won't work? java.lang.VerifyError
val config = LwjglApplicationConfiguration()
//config.useGL30 = true
config.vSyncEnabled = false
config.resizable = false
config.width = 1072
config.height = 742
config.foregroundFPS = 9999
LwjglApplication(TestTestMain, config)
val config = Lwjgl3ApplicationConfiguration()
config.useVsync(false)
config.setResizable(false)
config.setWindowedMode(1072, 742)
Lwjgl3Application(TestTestMain, config)
}

View File

@@ -2,8 +2,8 @@ package net.torvald.terrarum
import com.badlogic.gdx.ApplicationAdapter
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.backends.lwjgl.LwjglApplication
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
@@ -19,14 +19,11 @@ import java.util.zip.GZIPInputStream
*/
fun main(args: Array<String>) { // LWJGL 3 won't work? java.lang.VerifyError
val config = LwjglApplicationConfiguration()
//config.useGL30 = true
config.vSyncEnabled = false
config.resizable = false
config.width = 1072
config.height = 742
config.foregroundFPS = 9999
LwjglApplication(TexRegionTilingTest, config)
val config = Lwjgl3ApplicationConfiguration()
config.useVsync(false)
config.setResizable(false)
config.setWindowedMode(1072, 742)
Lwjgl3Application(TexRegionTilingTest, config)
}
object TexRegionTilingTest : ApplicationAdapter() {

View File

@@ -5,9 +5,7 @@ import com.badlogic.gdx.InputAdapter
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g2d.TextureRegion
import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.jme3.math.FastMath
import net.torvald.random.HQRNG
@@ -38,7 +36,7 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
// todo register titlescreen as the ingame, similar in a way that the buildingmaker did
var camera = OrthographicCamera(AppLoader.screenWf, AppLoader.screenHf)
var camera = OrthographicCamera(AppLoader.screenSize.screenWf, AppLoader.screenSize.screenHf)
// invert Y
@@ -170,13 +168,13 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
override fun show() {
printdbg(this, "show() called")
initViewPort(AppLoader.screenW, AppLoader.screenH)
initViewPort(AppLoader.screenSize.screenW, AppLoader.screenSize.screenH)
Gdx.input.inputProcessor = TitleScreenController(this)
worldFBO = FrameBuffer(Pixmap.Format.RGBA8888, AppLoader.screenW, AppLoader.screenH, false)
worldFBO = FrameBuffer(Pixmap.Format.RGBA8888, AppLoader.screenSize.screenW, AppLoader.screenSize.screenH, false)
loadThingsWhileIntroIsVisible()
@@ -235,7 +233,7 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
Gdx.graphics.setTitle(TerrarumIngame.getCanonicalTitle())
//camera.setToOrtho(true, AppLoader.screenWf, AppLoader.screenHf)
//camera.setToOrtho(true, AppLoader.terrarumAppConfig.screenWf, AppLoader.terrarumAppConfig.screenHf)
// render world
gdxClearAndSetBlend(.64f, .754f, .84f, 1f)
@@ -272,14 +270,14 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
COPYTING.forEachIndexed { index, s ->
val textWidth = AppLoader.fontGame.getWidth(s)
AppLoader.fontGame.draw(batch, s,
(AppLoader.screenW - textWidth - 1f).toInt().toFloat(),
(AppLoader.screenH - AppLoader.fontGame.lineHeight * (COPYTING.size - index) - 1f).toInt().toFloat()
(AppLoader.screenSize.screenW - textWidth - 1f).toInt().toFloat(),
(AppLoader.screenSize.screenH - AppLoader.fontGame.lineHeight * (COPYTING.size - index) - 1f).toInt().toFloat()
)
}
AppLoader.fontGame.draw(batch, "${AppLoader.GAME_NAME} ${AppLoader.getVERSION_STRING()}",
1f.toInt().toFloat(),
(AppLoader.screenH - AppLoader.fontGame.lineHeight - 1f).toInt().toFloat()
(AppLoader.screenSize.screenH - AppLoader.fontGame.lineHeight - 1f).toInt().toFloat()
)
}
@@ -296,11 +294,11 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
printStackTrace(this)
// Set up viewport when window is resized
initViewPort(AppLoader.screenW, AppLoader.screenH)
initViewPort(AppLoader.screenSize.screenW, AppLoader.screenSize.screenH)
// resize UI by re-creating it (!!)
uiMenu.resize(AppLoader.screenW, AppLoader.screenH)
uiMenu.resize(AppLoader.screenSize.screenW, AppLoader.screenSize.screenH)
// TODO I forgot what the fuck kind of hack I was talking about
//uiMenu.setPosition(0, UITitleRemoConRoot.menubarOffY)
uiMenu.setPosition(0, 0) // shitty hack. Could be:
@@ -308,7 +306,7 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
// 2: The UI is coded shit
IngameRenderer.resize(AppLoader.screenW, AppLoader.screenH)
IngameRenderer.resize(AppLoader.screenSize.screenW, AppLoader.screenSize.screenH)
printdbg(this, "resize() exit")
}
@@ -342,8 +340,8 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
return true
}
override fun scrolled(amount: Int): Boolean {
screen.uiContainer.forEach { it?.scrolled(amount) }
override fun scrolled(amountX: Float, amountY: Float): Boolean {
screen.uiContainer.forEach { it?.scrolled(amountX, amountY) }
return true
}

View File

@@ -4,7 +4,6 @@ import com.jme3.math.FastMath
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameitem.ItemID
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.worlddrawer.BlocksDrawer
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
@@ -31,8 +30,8 @@ object BlockStats {
val player = (Terrarum.ingame!! as TerrarumIngame).actorNowPlaying
if (player == null) return
val renderWidth = FastMath.ceil(AppLoader.screenWf)
val renderHeight = FastMath.ceil(AppLoader.screenHf)
val renderWidth = FastMath.ceil(AppLoader.screenSize.screenWf)
val renderHeight = FastMath.ceil(AppLoader.screenSize.screenHf)
val noZoomCameraX = Math.round(FastMath.clamp(
player.hitbox.centeredX.toFloat() - renderWidth / 2, TSIZE.toFloat(), map.width * TSIZE - renderWidth - TSIZE.toFloat()))

View File

@@ -1,6 +1,7 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.TerrarumScreenSize
object ResizeScreen: ConsoleCommand {
override fun execute(args: Array<String>) {
@@ -11,7 +12,7 @@ object ResizeScreen: ConsoleCommand {
when (args[1]) {
"720p" -> AppLoader.resizeScreen(1280,720)
"1080p" -> AppLoader.resizeScreen(1920,1080)
"default" -> AppLoader.resizeScreen(AppLoader.defaultW, AppLoader.defaultH)
"default" -> AppLoader.resizeScreen(TerrarumScreenSize.defaultW, TerrarumScreenSize.defaultH)
else -> { printUsage(); return }
}
}
@@ -19,11 +20,11 @@ object ResizeScreen: ConsoleCommand {
printUsage(); return
}
Echo("Screen resized to ${AppLoader.screenW}x${AppLoader.screenH}")
Echo("Screen resized to ${AppLoader.screenSize.screenW}x${AppLoader.screenSize.screenH}")
}
override fun printUsage() {
Echo("Usage: resize [width] [height]. Minimum size is ${AppLoader.minimumW}x${AppLoader.minimumH}")
Echo("Usage: resize [width] [height]. Minimum size is ${TerrarumScreenSize.minimumW}x${TerrarumScreenSize.minimumH}")
Echo("Reserved keywords: 720p, 1080p, default")
}
}

View File

@@ -1,7 +1,7 @@
package net.torvald.terrarum.controller
import com.badlogic.gdx.controllers.Controller
import com.badlogic.gdx.controllers.PovDirection
import net.torvald.terrarum.toInt
/**
* Created by minjaesong on 2019-02-09.
@@ -16,18 +16,11 @@ class GdxControllerAdapter(val c: Controller): TerrarumController {
return c.getAxis(index)
}
override fun getPov(): Int {
return when(c.getPov(0)) {
PovDirection.north -> TerrarumController.POV_N
PovDirection.northEast -> TerrarumController.POV_NE
PovDirection.northWest -> TerrarumController.POV_NW
PovDirection.east -> TerrarumController.POV_E
PovDirection.west -> TerrarumController.POV_W
PovDirection.south -> TerrarumController.POV_S
PovDirection.southEast -> TerrarumController.POV_SE
PovDirection.southWest -> TerrarumController.POV_SW
else -> 0
}
override fun getDpad(): Int {
return (c.getButton(c.mapping.buttonDpadLeft).toInt()) or
(c.getButton(c.mapping.buttonDpadDown).toInt() shl 1) or
(c.getButton(c.mapping.buttonDpadRight).toInt() shl 2) or
(c.getButton(c.mapping.buttonDpadUp).toInt() shl 3)
}
override fun getName(): String {

View File

@@ -70,7 +70,7 @@ interface TerrarumController {
* 6 2 3
* ```
*/
fun getPov(): Int
fun getDpad(): Int
fun getName(): String
/**

View File

@@ -53,7 +53,7 @@ class XinputControllerAdapter(val c: XInputDevice): TerrarumController {
return -1f
}
override fun getPov(): Int {
override fun getDpad(): Int {
if (c.poll()) {
val axes = c.components.axes

View File

@@ -1,398 +0,0 @@
package net.torvald.terrarum.gameactors.ai
import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
/**
* Created by minjaesong on 2016-10-24.
*/
/*internal class AILuaAPI(g: Globals, actor: ActorWBMovable) {
// FIXME when actor jumps, the actor releases left/right stick
init {
if (actor !is AIControlled)
throw IllegalArgumentException("The actor is not AIControlled! $actor")
// load functions and set up constants
g["ai"] = LuaValue.tableOf()
g["ai"]["getSelfActorInfo"] = GetSelfActorInfo(actor)
g["ai"]["getNearestActor"] = GetNearestActor()
g["ai"]["getNearestPlayer"] = GetNearestPlayer()
g["ai"]["getX"] = GetX(actor)
g["ai"]["getY"] = GetY(actor)
g["ai"]["moveUp"] = MoveUp(actor)
g["ai"]["moveDown"] = MoveDown(actor)
g["ai"]["moveLeft"] = MoveLeft(actor)
g["ai"]["moveRight"] = MoveRight(actor)
g["ai"]["moveTo"] = MoveTo(actor)
g["ai"]["jump"] = Jump(actor)
g["ai"]["getNearbyTiles"] = GetNearbyTiles(actor)
g["ai"]["getFloorsHeight"] = GetFloorsHeight(actor)
g["ai"]["getCeilingsHeight"] = GetCeilingsHeight(actor)
g["ai"]["getLedgesHeight"] = GetLedgesHeight(actor)
g["game"] = LuaValue.tableOf()
g["game"]["version"] = GameVersion()
g["game"]["versionRaw"] = GameVersionRaw()
}
companion object {
/**
* Reads arbitrary ActorWBMovable and returns its information as Lua table
*/
fun composeActorObject(actor: ActorWBMovable): LuaTable {
val t: LuaTable = LuaTable()
val moveDelta = actor.externalV + actor.controllerV
t["name"] = actor.actorValue.getAsString(AVKey.NAME).toLua()
t["startX"] = actor.hitbox.centeredX.toLua()
t["startY"] = actor.hitbox.centeredY.toLua()
t["veloX"] = moveDelta.x.toLua()
t["veloY"] = moveDelta.y.toLua()
t["width"] = actor.hitbox.width.toLua()
t["height"] = actor.hitbox.height.toLua()
t["mass"] = actor.mass.toLua()
t["collisionType"] = actor.collisionType.toLua()
t["strength"] = actor.avStrength.toLua()
return t
}
operator fun LuaTable.set(index: Int, value: Int) { this[index] = value.toLua() }
}
class GetSelfActorInfo(val actor: ActorWBMovable) : ZeroArgFunction() {
override fun call(): LuaValue {
return composeActorObject(actor)
}
}
/** ai.getNearestActor(nullable any criterion, nullable number range) */
class GetNearestActor() : LuaFunction() {
override fun call(): LuaValue {
return LuaValue.NONE
}
override fun call(crit: LuaValue): LuaValue {
return LuaValue.NONE
}
override fun call(crit: LuaValue, range: LuaValue): LuaValue {
return LuaValue.NONE
}
}
/** ai.getNearestPlayer(nullable any criterion, nullable number range) */
class GetNearestPlayer() : LuaFunction() {
override fun call(): LuaValue {
return LuaValue.NONE
}
override fun call(crit: LuaValue): LuaValue {
return LuaValue.NONE
}
override fun call(crit: LuaValue, range: LuaValue): LuaValue {
return LuaValue.NONE
}
}
class GetX(val actor: ActorWBMovable) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(actor.hitbox.centeredX)
}
}
class GetY(val actor: ActorWBMovable) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(actor.hitbox.centeredY)
}
}
class MoveLeft(val actor: AIControlled) : LuaFunction() {
override fun call(): LuaValue { // hard key press
actor.moveLeft()
return LuaValue.NONE
}
/** @param amount [0.0 - 1.0] */
override fun call(amount: LuaValue): LuaValue { // stick tilt
actor.moveLeft(amount.checkdouble().toFloat())
return LuaValue.NONE
}
}
class MoveRight(val actor: AIControlled) : LuaFunction() {
override fun call(): LuaValue { // hard key press
actor.moveRight()
return LuaValue.NONE
}
/** @param amount [0.0 - 1.0] */
override fun call(amount: LuaValue): LuaValue { // stick tilt
actor.moveRight(amount.checkdouble().toFloat())
return LuaValue.NONE
}
}
class MoveUp(val actor: AIControlled) : LuaFunction() {
override fun call(): LuaValue { // hard key press
actor.moveUp()
return LuaValue.NONE
}
/** @param amount [0.0 - 1.0] */
override fun call(amount: LuaValue): LuaValue { // stick tilt
actor.moveUp(amount.checkdouble().toFloat())
return LuaValue.NONE
}
}
class MoveDown(val actor: AIControlled) : LuaFunction() {
override fun call(): LuaValue { // hard key press
actor.moveDown()
return LuaValue.NONE
}
/** @param amount [0.0 - 1.0] */
override fun call(amount: LuaValue): LuaValue { // stick tilt
actor.moveDown(amount.checkdouble().toFloat())
return LuaValue.NONE
}
}
class MoveTo(val actor: AIControlled) : LuaFunction() {
override fun call(bearing: LuaValue): LuaValue {
actor.moveTo(bearing.checkdouble())
return LuaValue.NONE
}
override fun call(toX: LuaValue, toY: LuaValue): LuaValue {
actor.moveTo(toX.checkdouble(), toY.checkdouble())
return LuaValue.NONE
}
}
class Jump(val actor: AIControlled) : LuaFunction() {
override fun call(): LuaValue {
actor.moveJump()
return LuaValue.NONE
}
/** @param amount [0.0 - 1.0] */
override fun call(amount: LuaValue): LuaValue { // stick tilt
actor.moveJump(amount.checkdouble().toFloat())
return LuaValue.NONE
}
}
class GetNearbyTiles(val actor: ActorWBMovable) : OneArgFunction() {
/** @param radius
*
* 3 will return 7x7 array, 0 will return 1x1, 1 will return 3x3
*
* Index: [-3: y][-3: x] ... [0: y][0: x] ... [3: y][3: x] for radius 3
* Return value: bitset (int 0-7)
* 1 -- solidity
* 2 -- liquidity
* 3 -- gravity
*/
override fun call(arg: LuaValue): LuaValue {
val radius = arg.checkint()
if (radius < 0) {
return LuaValue.NONE
}
else if (radius > 8) {
throw IllegalArgumentException("Radius too large -- must be 8 or less")
}
else {
val luatable = LuaTable()
val feetTilePos = actor.feetPosTile
for (y in feetTilePos[1] - radius..feetTilePos[1] + radius) {
luatable[y - feetTilePos[1]] = LuaTable()
for (x in feetTilePos[0] - radius..feetTilePos[0] + radius) {
val tile = BlockCodex[(Terrarum.ingame!!.world).getTileFromTerrain(x, y) ?: Block.NULL]
val solidity = tile.isSolid.toInt()
val liquidity = tile.isFluid.toInt()
val gravity = tile.maxSupport.toInt()
val tileFlag: Int = gravity.shl(2) + liquidity.shl(1) + solidity
luatable[y - feetTilePos[1]][x - feetTilePos[0]] = tileFlag.toLua()
}
}
return luatable
}
}
}
class GetFloorsHeight(val actor: ActorWBMovable) : OneArgFunction() {
/** @param radius
*
* 3 will return len:7 array, 0 will return len:1, 1 will return len:3
*
* Index: [-3] .. [0] .. [3] for radius
* Return value: floor height
* 0: body tile (legs area)
* 1: tile you can stand on
* 2+: tiles down there
*/
override fun call(arg: LuaValue): LuaValue {
val radius = arg.checkint()
val searchDownLimit = 12
if (radius < 0) {
return LuaValue.NONE
}
else if (radius > 8) {
throw IllegalArgumentException("Radius too large -- must be 8 or less")
}
else {
val luatable = LuaTable()
val feetTilePos = actor.feetPosTile
for (x in feetTilePos[0] - radius..feetTilePos[0] + radius) {
// search down
var searchDownCounter = 0
while (true) {
val tile = (Terrarum.ingame!!.world).getTileFromTerrain(x, feetTilePos[1] + searchDownCounter) ?: Block.STONE
if (BlockCodex[tile].isSolid || searchDownCounter >= searchDownLimit) {
luatable[x - feetTilePos[0]] = searchDownCounter
break
}
searchDownCounter++
}
}
return luatable
}
}
}
class GetCeilingsHeight(val actor: ActorWBMovable) : OneArgFunction() {
/** @param arg radius
*
* 3 will return 7x7 array, 0 will return 1x1, 1 will return 3x3
*
* Index: [-3] .. [0] .. [3] for radius
* Return value: floor height
* 0: body tile (legs area)
* 1: body tile (may be vary depend on the size of the actor)
* 2+: tiles up there
*/
override fun call(arg: LuaValue): LuaValue {
val radius = arg.checkint()
val searchUpLimit = 12
if (radius < 0) {
return LuaValue.NONE
}
else if (radius > 8) {
throw IllegalArgumentException("Radius too large -- must be 8 or less")
}
else {
val luatable = LuaTable()
val feetTilePos = actor.feetPosTile
for (x in feetTilePos[0] - radius..feetTilePos[0] + radius) {
// search up
var searchUpCounter = 0
while (true) {
val tile = (Terrarum.ingame!!.world).getTileFromTerrain(x, feetTilePos[1] - searchUpCounter) ?: Block.STONE
if (BlockCodex[tile].isSolid || searchUpCounter >= searchUpLimit) {
luatable[x - feetTilePos[0]] = searchUpCounter
break
}
searchUpCounter++
}
}
return luatable
}
}
}
class GetLedgesHeight(val actor: ActorWBMovable) : OneArgFunction() {
/** @param arg radius
* ==
* <- (non-solid found)
* ==
* ==
* ==
* == @ -> ledge height: 4
* =================
*/
override fun call(arg: LuaValue): LuaValue {
val radius = arg.checkint()
val searchUpLimit = 12
if (radius < 0) {
return LuaValue.NONE
}
else if (radius > 8) {
throw IllegalArgumentException("Radius too large -- must be 8 or less")
}
else {
val luatable = LuaTable()
val feetTilePos = actor.feetPosTile
for (x in feetTilePos[0] - radius..feetTilePos[0] + radius) {
// search up
var searchUpCounter = 0
while (true) {
val tile = (Terrarum.ingame!!.world).getTileFromTerrain(x, feetTilePos[1] - searchUpCounter) ?: Block.STONE
if (!BlockCodex[tile].isSolid || searchUpCounter >= searchUpLimit) {
luatable[x - feetTilePos[0]] = searchUpCounter
break
}
searchUpCounter++
}
}
return luatable
}
}
}
class GameVersion : ZeroArgFunction() {
override fun call(): LuaValue {
return AppLoader.getVERSION_STRING().toLua()
}
}
class GameVersionRaw : ZeroArgFunction() {
override fun call(): LuaValue {
return AppLoader.VERSION_RAW.toLua()
}
}
}*/
fun Double.toLua() = LuaValue.valueOf(this)
fun Int.toLua() = LuaValue.valueOf(this)
fun String.toLua() = LuaValue.valueOf(this)
fun Boolean.toLua() = LuaValue.valueOf(this)
fun Double?.toLua() = if (this == null) LuaValue.NIL else this.toLua()
fun Int?.toLua() = if (this == null) LuaValue.NIL else this.toLua()
fun String?.toLua() = if (this == null) LuaValue.NIL else this.toLua()
fun Boolean?.toLua() = if (this == null) LuaValue.NIL else this.toLua()
fun luaTableOf(vararg luaValues: LuaValue): LuaTable {
val t = LuaTable.tableOf()
luaValues.forEachIndexed { index, luaValue -> t[index + 1] = luaValue }
return t
}

View File

@@ -1,112 +0,0 @@
package net.torvald.terrarum.gameactors.ai
import net.torvald.terrarum.gameactors.Actor
import org.luaj.vm2.Globals
import org.luaj.vm2.LuaError
import org.luaj.vm2.LuaInteger
import org.luaj.vm2.LuaValue
import org.luaj.vm2.lib.jse.JsePlatform
import java.io.InputStreamReader
import java.io.Reader
/**
* Created by minjaesong on 2017-02-04.
*/
/*class LuaAIWrapper(private val scriptPath: String) : ActorAI {
protected val luag: Globals = JsePlatform.standardGlobals()
/**
* Initialised in init block.
* Use lua function "update(delta)" to step the AI.
*/
protected lateinit var luaInstance: LuaValue
private lateinit var aiLuaAPI: AILuaAPI
private lateinit var targetActor: Actor
/**
* The initialiser
*
* Use ```(p.ai as LuaAIWrapper).attachActor(p)```
*/
fun attachActor(actor: Actor) {
targetActor = actor
luag["io"] = LuaValue.NIL
luag["os"] = LuaValue.NIL
luag["luajava"] = LuaValue.NIL
aiLuaAPI = AILuaAPI(luag, targetActor)
// load the script and execute it (initialises target script)
val inputStream = javaClass.getResourceAsStream(scriptPath)
luaInstance = luag.load(InputStreamReader(inputStream), scriptPath.split(Regex("[\\/]")).last())
luaInstance.call()
}
override fun update(actor: Actor, delta: Float) {
// run "update()" function in the script
luag.get("update").call(delta.toLua())
}
lateinit var currentExecutionThread: Thread
var threadRun = false
fun runCommand(reader: Reader, filename: String) {
if (!threadRun && !targetActor.flagDespawn) {
currentExecutionThread = Thread(ThreadRunCommand(luag, reader, filename))
currentExecutionThread.start()
threadRun = true
}
}
fun runCommand(script: String) {
if (!threadRun && !targetActor.flagDespawn) {
currentExecutionThread = Thread(ThreadRunCommand(luag, script, ""))
currentExecutionThread.start()
threadRun = true
}
}
class ThreadRunCommand : Runnable {
val mode: Int
val arg1: Any
val arg2: String
val lua: Globals
constructor(luaInstance: Globals, line: String, env: String) {
mode = 0
arg1 = line
arg2 = env
lua = luaInstance
}
constructor(luaInstance: Globals, reader: Reader, filename: String) {
mode = 1
arg1 = reader
arg2 = filename
lua = luaInstance
}
override fun run() {
try {
val chunk: LuaValue
if (mode == 0)
chunk = lua.load(arg1 as String, arg2)
else if (mode == 1)
chunk = lua.load(arg1 as Reader, arg2)
else
throw IllegalArgumentException("Unsupported mode: $mode")
chunk.call()
}
catch (e: LuaError) {
e.printStackTrace(System.err)
}
}
}
fun Float.toLua(): LuaValue = LuaInteger.valueOf(this.toDouble())
}*/

View File

@@ -1,83 +0,0 @@
--
-- Created by minjaesong on 2017-01-06.
--
timeCounter = 0
countMax = 0
moveMode = math.random() >= 0.5 and "left" or "right"
currentMode = "move"
jumpheight = 6 -- lol
function generateCountMax()
local function generateTurn()
return 4600 + 1250 * math.random()
end
local function generateWalk()
return 1645 + 402 * math.random()
end
return (currentMode == "move") and generateWalk() or generateTurn()
end
function moveToDirection(delta)
local pits = ai.getFloorsHeight(2)
local ledges = ai.getLedgesHeight(1)
if moveMode == "left" then
if pits[-1] == 1 then
ai.moveLeft(0.8)
if ledges[-1] <= jumpheight then -- no futile jumps
ai.jump()
end
else
ai.moveLeft(0.5)
end
elseif moveMode == "right" then
if pits[1] == 1 then
ai.moveRight(0.8)
if ledges[1] <= jumpheight then -- no futile jumps
ai.jump()
end
else
ai.moveRight(0.5)
end
end
timeCounter = timeCounter + delta
end
function toggleCurrentMode()
currentMode = (currentMode == "move") and "turn" or "move"
end
function toggleMoveMode()
moveMode = (moveMode == "left") and "right" or "left"
end
-------------------------------------------------------------------------------
countMax = generateCountMax()
function toggleCondition()
local floorsheight = ai.getFloorsHeight(1)
return timeCounter >= countMax or
-- avoid great falls
(timeCounter > 150 and (floorsheight[-1] > jumpheight or floorsheight[1] > jumpheight))
end
function update(delta)
if currentMode == "move" then
moveToDirection(delta)
else
timeCounter = timeCounter + delta -- no countup when jumping
end
if toggleCondition() then
timeCounter = 0
toggleCurrentMode()
countMax = generateCountMax()
if currentMode == "turn" then
toggleMoveMode()
end
end
end

View File

@@ -4,8 +4,10 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import com.badlogic.gdx.InputAdapter
import com.badlogic.gdx.controllers.Controllers
import com.badlogic.gdx.utils.GdxRuntimeException
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.AppLoader.printdbgerr
import net.torvald.terrarum.controller.TerrarumController
import net.torvald.terrarum.floorInt
import net.torvald.terrarum.gameactors.AVKey
@@ -44,8 +46,14 @@ class IngameController(val terrarumIngame: TerrarumIngame) : InputAdapter() {
get() = (mouseY / CreateTileAtlas.TILE_SIZE).floorInt()
init {
if (Controllers.getControllers().size == 0) {
printdbg(this, "Controller not found")
try {
if (Controllers.getControllers().size == 0) {
printdbg(this, "Controller not found")
}
}
catch (e: GdxRuntimeException) {
printdbg(this, e.message)
e.stackTrace.forEach { printdbgerr(this, "\t$it") }
}
}
@@ -191,18 +199,18 @@ class IngameController(val terrarumIngame: TerrarumIngame) : InputAdapter() {
return true
}
override fun scrolled(amount: Int): Boolean {
override fun scrolled(amountX: Float, amountY: Float): Boolean {
if (!terrarumIngame.paused) {
// quickslot by wheel
if (terrarumIngame.actorNowPlaying != null) {
terrarumIngame.actorNowPlaying!!.actorValue.set(
AVKey.__PLAYER_QUICKSLOTSEL,
(terrarumIngame.actorNowPlaying!!.actorValue.getAsInt(AVKey.__PLAYER_QUICKSLOTSEL)!! - amount) fmod terrarumIngame.actorNowPlaying!!.inventory.quickSlot.size
(terrarumIngame.actorNowPlaying!!.actorValue.getAsInt(AVKey.__PLAYER_QUICKSLOTSEL)!! - amountY.toInt()) fmod terrarumIngame.actorNowPlaying!!.inventory.quickSlot.size
)
}
}
terrarumIngame.uiContainer.forEach { it?.scrolled(amount) }
terrarumIngame.uiContainer.forEach { it?.scrolled(amountX, amountY) }
return true
}

View File

@@ -1,57 +0,0 @@
package net.torvald.terrarum.itemproperties
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ai.toLua
import org.luaj.vm2.Globals
import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
import org.luaj.vm2.lib.ThreeArgFunction
import org.luaj.vm2.lib.ZeroArgFunction
/**
* Created by minjaesong on 2017-04-16.
*/
class ItemEffectsLuaAPI(g: Globals) {
init {
g["getMouseTile"] = GetMouseTile()
g["getMousePos"] = GetMousePos()
g["world"] = LuaTable()
g["world"]["strikeEarth"] = StrikeEarth()
g["world"]["strikeWall"] = StrikeWall()
g["actor"] = LuaTable()
}
class GetMouseTile : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.tableOf(arrayOf(Terrarum.mouseTileX.toLua(), Terrarum.mouseTileY.toLua()))
}
}
class GetMousePos : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.tableOf(arrayOf(Terrarum.mouseX.toLua(), Terrarum.mouseY.toLua()))
}
}
class StrikeEarth : ThreeArgFunction() {
override fun call(x: LuaValue, y: LuaValue, power: LuaValue): LuaValue {
(Terrarum.ingame!!.world).inflictTerrainDamage(x.checkint(), y.checkint(), power.checkdouble())
return LuaValue.NONE
}
}
class StrikeWall : ThreeArgFunction() {
override fun call(x: LuaValue, y: LuaValue, power: LuaValue): LuaValue {
(Terrarum.ingame!!.world).inflictWallDamage(x.checkint(), y.checkint(), power.checkdouble())
return LuaValue.NONE
}
}
}

View File

@@ -8,7 +8,6 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.gdx.graphics.Cvec
import net.torvald.terrarum.*
import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.BlockPropUtil
import net.torvald.terrarum.gameactors.*
import net.torvald.terrarum.gameitem.ItemID
@@ -20,18 +19,8 @@ import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerBlockChooser
import net.torvald.terrarum.modulebasegame.ui.UIBuildingMakerPenMenu
import net.torvald.terrarum.modulebasegame.ui.UIPaletteSelector
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.serialise.WriteLayerDataZip.FILE_FOOTER
import net.torvald.terrarum.serialise.WriteLayerDataZip.PAYLOAD_FOOTER
import net.torvald.terrarum.serialise.WriteLayerDataZip.PAYLOAD_HEADER
import net.torvald.terrarum.serialise.toLittle
import net.torvald.terrarum.serialise.toLittleShort
import net.torvald.terrarum.serialise.toULittle48
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UINSMenu
import net.torvald.terrarum.worlddrawer.WorldCamera
import java.io.File
import java.io.FileOutputStream
/**
* Created by minjaesong on 2018-07-06.
@@ -295,11 +284,11 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
uiToolbox.isVisible = true
uiToolbox.invocationArgument = arrayOf(this)
uiPaletteSelector.setPosition(AppLoader.screenW - uiPaletteSelector.width, 0)
uiPaletteSelector.setPosition(AppLoader.screenSize.screenW - uiPaletteSelector.width, 0)
uiPaletteSelector.isVisible = true
notifier.setPosition(
(AppLoader.screenW - notifier.width) / 2, AppLoader.screenH - notifier.height)
(AppLoader.screenSize.screenW - notifier.width) / 2, AppLoader.screenSize.screenH - notifier.height)
actorNowPlaying?.setPosition(512 * 16.0, 149 * 16.0)
@@ -379,8 +368,8 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
// position the menu to where the cursor is
uiPenMenu.posX = Terrarum.mouseScreenX - uiPenMenu.width / 2
uiPenMenu.posY = Terrarum.mouseScreenY - uiPenMenu.height / 2
uiPenMenu.posX = uiPenMenu.posX.coerceIn(0, AppLoader.screenW - uiPenMenu.width)
uiPenMenu.posY = uiPenMenu.posY.coerceIn(0, AppLoader.screenH - uiPenMenu.height)
uiPenMenu.posX = uiPenMenu.posX.coerceIn(0, AppLoader.screenSize.screenW - uiPenMenu.width)
uiPenMenu.posY = uiPenMenu.posY.coerceIn(0, AppLoader.screenSize.screenH - uiPenMenu.height)
// actually open
uiPenMenu.setAsOpen()
@@ -398,10 +387,10 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
}
override fun resize(width: Int, height: Int) {
IngameRenderer.resize(AppLoader.screenW, AppLoader.screenH)
IngameRenderer.resize(AppLoader.screenSize.screenW, AppLoader.screenSize.screenH)
uiToolbox.setPosition(0, 0)
notifier.setPosition(
(AppLoader.screenW - notifier.width) / 2, AppLoader.screenH - notifier.height)
(AppLoader.screenSize.screenW - notifier.width) / 2, AppLoader.screenSize.screenH - notifier.height)
println("[BuildingMaker] Resize event")
}
@@ -518,8 +507,8 @@ class BuildingMakerController(val screen: BuildingMaker) : InputAdapter() {
return true
}
override fun scrolled(amount: Int): Boolean {
screen.uiContainer.forEach { it?.scrolled(amount) }
override fun scrolled(amountX: Float, amountY: Float): Boolean {
screen.uiContainer.forEach { it?.scrolled(amountX, amountY) }
return true
}
@@ -563,12 +552,12 @@ class MovableWorldCamera(val parent: BuildingMaker) : ActorHumanoid(0, physProp
// TODO resize-aware
private var coerceInStart = Point2d(
(AppLoader.screenW - hitbox.width) / 2.0,
(AppLoader.screenH - hitbox.height) / 2.0
(AppLoader.screenSize.screenW - hitbox.width) / 2.0,
(AppLoader.screenSize.screenH - hitbox.height) / 2.0
)
private var coerceInEnd = Point2d(
parent.world.width * TILE_SIZE - (AppLoader.screenW - hitbox.width) / 2.0,
parent.world.height * TILE_SIZE - (AppLoader.screenH - hitbox.height) / 2.0
parent.world.width * TILE_SIZE - (AppLoader.screenSize.screenW - hitbox.width) / 2.0,
parent.world.height * TILE_SIZE - (AppLoader.screenSize.screenH - hitbox.height) / 2.0
)
override fun update(delta: Float) {

View File

@@ -56,8 +56,8 @@ object IngameRenderer : Disposable {
val shaderAtoGrey: ShaderProgram
val shaderPassthru = SpriteBatch.createDefaultShader()
private val WIDTH = AppLoader.screenW
private val HEIGHT = AppLoader.screenH
private val WIDTH = AppLoader.screenSize.screenW
private val HEIGHT = AppLoader.screenSize.screenH
private val WIDTHF = WIDTH.toFloat()
private val HEIGHTF = HEIGHT.toFloat()
@@ -608,7 +608,7 @@ object IngameRenderer : Disposable {
* Camera will be moved so that (newX, newY) would be sit on the top-left edge.
*/
private fun setCameraPosition(newX: Float, newY: Float) {
camera.position.set((-newX + AppLoader.halfScreenW).round(), (-newY + AppLoader.halfScreenH).round(), 0f)
camera.position.set((-newX + AppLoader.screenSize.halfScreenW).round(), (-newY + AppLoader.screenSize.halfScreenH).round(), 0f)
camera.update()
batch.projectionMatrix = camera.combined
}

View File

@@ -4,7 +4,6 @@ import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.utils.GdxRuntimeException
import net.torvald.EMDASH
import net.torvald.terrarum.*
import net.torvald.terrarum.AppLoader.printdbg
@@ -83,7 +82,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
companion object {
/** Sets camera position so that (0,0) would be top-left of the screen, (width, height) be bottom-right. */
fun setCameraPosition(batch: SpriteBatch, camera: Camera, newX: Float, newY: Float) {
camera.position.set((-newX + AppLoader.halfScreenW).round(), (-newY + AppLoader.halfScreenH).round(), 0f)
camera.position.set((-newX + AppLoader.screenSize.halfScreenW).round(), (-newY + AppLoader.screenSize.halfScreenH).round(), 0f)
camera.update()
batch.projectionMatrix = camera.combined
}
@@ -184,7 +183,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
}
override fun show() {
//initViewPort(AppLoader.screenW, AppLoader.screenH)
//initViewPort(AppLoader.terrarumAppConfig.screenW, AppLoader.terrarumAppConfig.screenH)
// gameLoadMode and gameLoadInfoPayload must be set beforehand!!
@@ -289,8 +288,8 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
/** Load rest of the game with GL context */
fun postInit() {
//setTheRealGamerFirstTime(PlayerBuilderSigrid())
//setTheRealGamerFirstTime(PlayerBuilderTestSubject1())
setTheRealGamerFirstTime(PlayerBuilderWerebeastTest())
setTheRealGamerFirstTime(PlayerBuilderTestSubject1())
//setTheRealGamerFirstTime(PlayerBuilderWerebeastTest())
@@ -314,8 +313,8 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
// init notifier
notifier = Notification()
notifier.setPosition(
(AppLoader.screenW - notifier.width) / 2,
AppLoader.screenH - notifier.height - AppLoader.getTvSafeGraphicsHeight()
(AppLoader.screenSize.screenW - notifier.width) / 2,
AppLoader.screenSize.screenH - notifier.height - AppLoader.screenSize.tvSafeGraphicsHeight
)
@@ -332,11 +331,11 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
// quick bar
uiQuickBar = UIQuickslotBar()
uiQuickBar.isVisible = true
uiQuickBar.setPosition((AppLoader.screenW - uiQuickBar.width) / 2, AppLoader.getTvSafeGraphicsHeight())
uiQuickBar.setPosition((AppLoader.screenSize.screenW - uiQuickBar.width) / 2, AppLoader.screenSize.tvSafeGraphicsHeight)
// pie menu
uiPieMenu = UIQuickslotPie()
uiPieMenu.setPosition(AppLoader.halfScreenW, AppLoader.halfScreenH)
uiPieMenu.setPosition(AppLoader.screenSize.halfScreenW, AppLoader.screenSize.halfScreenH)
// vital metre
// fill in getter functions by
@@ -351,14 +350,14 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
uiWatchTierOne = UITierOneWatch(actorNowPlaying)
uiWatchTierOne.setAsAlwaysVisible()
uiWatchTierOne.setPosition(
((AppLoader.screenW - AppLoader.getTvSafeActionWidth()) - (uiQuickBar.posX + uiQuickBar.width) - uiWatchTierOne.width) / 2 + (uiQuickBar.posX + uiQuickBar.width),
AppLoader.getTvSafeGraphicsHeight() + 8
((AppLoader.screenSize.screenW - AppLoader.screenSize.tvSafeActionWidth) - (uiQuickBar.posX + uiQuickBar.width) - uiWatchTierOne.width) / 2 + (uiQuickBar.posX + uiQuickBar.width),
AppLoader.screenSize.tvSafeGraphicsHeight + 8
)
// basic watch-style notification bar (temperature, new mail)
uiBasicInfo = UIBasicInfo(actorNowPlaying)
uiBasicInfo.setAsAlwaysVisible()
uiBasicInfo.setPosition((uiQuickBar.posX - uiBasicInfo.width - AppLoader.getTvSafeActionWidth()) / 2 + AppLoader.getTvSafeActionWidth(), uiWatchTierOne.posY)
uiBasicInfo.setPosition((uiQuickBar.posX - uiBasicInfo.width - AppLoader.screenSize.tvSafeActionWidth) / 2 + AppLoader.screenSize.tvSafeActionWidth, uiWatchTierOne.posY)
uiTooltip = UITooltip()
@@ -1009,8 +1008,8 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
/**
* @param width same as AppLoader.screenW
* @param height same as AppLoader.screenH
* @param width same as AppLoader.terrarumAppConfig.screenW
* @param height same as AppLoader.terrarumAppConfig.screenH
* @see net.torvald.terrarum.Terrarum
*/
override fun resize(width: Int, height: Int) {
@@ -1019,7 +1018,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
//MegaRainGovernor.resize()
IngameRenderer.resize(AppLoader.screenW, AppLoader.screenH)
IngameRenderer.resize(AppLoader.screenSize.screenW, AppLoader.screenSize.screenH)
if (gameInitialised) {
@@ -1031,23 +1030,23 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
// resize UIs
notifier.setPosition(
(AppLoader.screenW - notifier.width) / 2, AppLoader.screenH - notifier.height)
uiQuickBar.setPosition((AppLoader.screenW - uiQuickBar.width) / 2, AppLoader.getTvSafeGraphicsHeight())
(AppLoader.screenSize.screenW - notifier.width) / 2, AppLoader.screenSize.screenH - notifier.height)
uiQuickBar.setPosition((AppLoader.screenSize.screenW - uiQuickBar.width) / 2, AppLoader.screenSize.tvSafeGraphicsHeight)
// inventory
/*uiInventoryPlayer =
UIInventory(player,
width = 840,
height = AppLoader.screenH - 160,
height = AppLoader.terrarumAppConfig.screenH - 160,
categoryWidth = 210
)*/
// basic watch-style notification bar (temperature, new mail)
uiBasicInfo.setPosition(AppLoader.screenW - uiBasicInfo.width, 0)
uiBasicInfo.setPosition(AppLoader.screenSize.screenW - uiBasicInfo.width, 0)
uiWatchTierOne.setPosition(
((AppLoader.screenW - AppLoader.getTvSafeGraphicsWidth()) - (uiQuickBar.posX + uiQuickBar.width) - uiWatchTierOne.width) / 2 + (uiQuickBar.posX + uiQuickBar.width),
AppLoader.getTvSafeGraphicsHeight() + 8
((AppLoader.screenSize.screenW - AppLoader.screenSize.tvSafeGraphicsWidth) - (uiQuickBar.posX + uiQuickBar.width) - uiWatchTierOne.width) / 2 + (uiQuickBar.posX + uiQuickBar.width),
AppLoader.screenSize.tvSafeGraphicsHeight + 8
)
}

View File

@@ -1,16 +1,11 @@
package net.torvald.terrarum.modulebasegame
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.ScreenAdapter
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
import net.torvald.terrarum.*
import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.blockproperties.BlockProp
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.util.CircularArray
import kotlin.math.roundToInt
/**
@@ -39,8 +34,8 @@ class WorldgenLoadScreen(screenToBeLoaded: IngameInstance, private val worldwidt
private val COL_AIR = Color.BLACK
}
private val previewWidth = (AppLoader.screenW * WIDTH_RATIO).roundToInt()
private val previewHeight = (AppLoader.screenW * WIDTH_RATIO * worldheight / worldwidth).roundToInt()
private val previewWidth = (AppLoader.screenSize.screenW * WIDTH_RATIO).roundToInt()
private val previewHeight = (AppLoader.screenSize.screenW * WIDTH_RATIO * worldheight / worldwidth).roundToInt()
private lateinit var previewPixmap: Pixmap
private lateinit var previewTexture: Texture
@@ -73,15 +68,15 @@ class WorldgenLoadScreen(screenToBeLoaded: IngameInstance, private val worldwidt
AppLoader.batch.inUse {
it.color = Color.WHITE
val previewY = (AppLoader.screenH - previewHeight.times(1.5f)).div(2f).round()
val previewY = (AppLoader.screenSize.screenH - previewHeight.times(1.5f)).div(2f).round()
it.draw(previewTexture,
(AppLoader.screenW - previewWidth).div(2f).round(),
(AppLoader.screenSize.screenW - previewWidth).div(2f).round(),
previewY
)
val text = messages.getHeadElem() ?: ""
AppLoader.fontGame.draw(it,
text,
(AppLoader.screenW - AppLoader.fontGame.getWidth(text)).div(2f).round(),
(AppLoader.screenSize.screenW - AppLoader.fontGame.getWidth(text)).div(2f).round(),
previewY + previewHeight + 98 - AppLoader.fontGame.lineHeight
)
}

View File

@@ -5,7 +5,6 @@ import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.glutils.ShapeRenderer
import net.torvald.terrarum.*
import net.torvald.terrarum.AppLoader.printdbg
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.gameitem.GameItem
import net.torvald.terrarum.langpack.Lang
@@ -13,7 +12,6 @@ import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory.Companion.CAPACITY_MODE_COUNT
import net.torvald.terrarum.modulebasegame.ui.*
import net.torvald.terrarum.modulebasegame.ui.UIInventoryCells.Companion.weightBarWidth
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.CELLS_HOR
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.CELLS_VRT
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.INVENTORY_CELLS_OFFSET_X
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.INVENTORY_CELLS_OFFSET_Y
@@ -61,8 +59,8 @@ internal class UIStorageChest : UICanvas(), HasInventory {
lateinit var chestInventory: FixtureInventory
lateinit var chestNameFun: () -> String
override var width = AppLoader.screenW
override var height = AppLoader.screenH
override var width = AppLoader.screenSize.screenW
override var height = AppLoader.screenSize.screenH
override var openCloseTime: Second = 0.0f
private val shapeRenderer = ShapeRenderer()
@@ -124,8 +122,8 @@ internal class UIStorageChest : UICanvas(), HasInventory {
catBar = UIItemInventoryCatBar(
this,
(AppLoader.screenW - catBarWidth) / 2,
42 + (AppLoader.screenH - internalHeight) / 2,
(AppLoader.screenSize.screenW - catBarWidth) / 2,
42 + (AppLoader.screenSize.screenH - internalHeight) / 2,
internalWidth,
catBarWidth,
false
@@ -192,17 +190,17 @@ internal class UIStorageChest : UICanvas(), HasInventory {
gdxSetBlendNormal()
val gradTopStart = (AppLoader.screenH - internalHeight).div(2).toFloat()
val gradBottomEnd = AppLoader.screenH - gradTopStart
val gradTopStart = (AppLoader.screenSize.screenH - internalHeight).div(2).toFloat()
val gradBottomEnd = AppLoader.screenSize.screenH - gradTopStart
shapeRenderer.inUse {
shapeRenderer.rect(0f, gradTopStart, AppLoader.screenWf, gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
shapeRenderer.rect(0f, gradBottomEnd, AppLoader.screenWf, -gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
shapeRenderer.rect(0f, gradTopStart, AppLoader.screenSize.screenWf, gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
shapeRenderer.rect(0f, gradBottomEnd, AppLoader.screenSize.screenWf, -gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
shapeRenderer.rect(0f, gradTopStart + gradHeight, AppLoader.screenWf, internalHeight - (2 * gradHeight), gradEndCol, gradEndCol, gradEndCol, gradEndCol)
shapeRenderer.rect(0f, gradTopStart + gradHeight, AppLoader.screenSize.screenWf, internalHeight - (2 * gradHeight), gradEndCol, gradEndCol, gradEndCol, gradEndCol)
shapeRenderer.rect(0f, 0f, AppLoader.screenWf, gradTopStart, gradStartCol, gradStartCol, gradStartCol, gradStartCol)
shapeRenderer.rect(0f, AppLoader.screenHf, AppLoader.screenWf, -(AppLoader.screenHf - gradBottomEnd), gradStartCol, gradStartCol, gradStartCol, gradStartCol)
shapeRenderer.rect(0f, 0f, AppLoader.screenSize.screenWf, gradTopStart, gradStartCol, gradStartCol, gradStartCol, gradStartCol)
shapeRenderer.rect(0f, AppLoader.screenSize.screenHf, AppLoader.screenSize.screenWf, -(AppLoader.screenSize.screenHf - gradBottomEnd), gradStartCol, gradStartCol, gradStartCol, gradStartCol)
}

View File

@@ -47,7 +47,7 @@ object MegaRainGovernor {
val h = body.height
bodies = Array(1024) {
//val pixmap = Pixmap(AppLoader.screenW * 2, AppLoader.screenH / 4, Pixmap.Format.RGBA8888)
//val pixmap = Pixmap(AppLoader.terrarumAppConfig.screenW * 2, AppLoader.terrarumAppConfig.screenH / 4, Pixmap.Format.RGBA8888)
val pixmap = Pixmap(64, 64, Pixmap.Format.RGBA8888)
val rng = HQRNG()

View File

@@ -5,7 +5,6 @@ import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.Second
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.blendNormal
import net.torvald.terrarum.ui.UICanvas
@@ -62,7 +61,7 @@ class Notification : UICanvas() {
val displayedTextWidth = maxOf(240, realTextWidth)
// force the UI to the centre of the screen
this.posX = (AppLoader.screenW - displayedTextWidth) / 2
this.posX = (AppLoader.screenSize.screenW - displayedTextWidth) / 2
val textHeight = message.size * AppLoader.fontGame.lineHeight

View File

@@ -70,8 +70,8 @@ class UIBuildingMakerPenMenu(val parent: BuildingMaker): UICanvas() {
{
parent.uiPalette.isVisible = true
parent.uiPalette.setPosition(Gdx.input.x - parent.uiPalette.width / 2, Gdx.input.y - parent.uiPalette.height / 2)
parent.uiPalette.posX = parent.uiPalette.posX.coerceIn(0, AppLoader.screenW - parent.uiPalette.width)
parent.uiPalette.posY = parent.uiPalette.posY.coerceIn(0, AppLoader.screenH - parent.uiPalette.height)
parent.uiPalette.posX = parent.uiPalette.posX.coerceIn(0, AppLoader.screenSize.screenW - parent.uiPalette.width)
parent.uiPalette.posY = parent.uiPalette.posY.coerceIn(0, AppLoader.screenSize.screenH - parent.uiPalette.height)
},
{
parent.currentPenMode = BuildingMaker.PENMODE_PENCIL_ERASE

View File

@@ -52,40 +52,4 @@ class UIBuildingMakerToolbox : UICanvas() {
override fun dispose() {
toolsTexture.dispose()
}
override fun mouseMoved(screenX: Int, screenY: Int): Boolean {
return super.mouseMoved(screenX, screenY)
}
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
return super.touchDragged(screenX, screenY, pointer)
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
return super.touchDown(screenX, screenY, pointer, button)
}
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
return super.touchUp(screenX, screenY, pointer, button)
}
override fun scrolled(amount: Int): Boolean {
return super.scrolled(amount)
}
override fun keyDown(keycode: Int): Boolean {
return super.keyDown(keycode)
}
override fun keyUp(keycode: Int): Boolean {
return super.keyUp(keycode)
}
override fun keyTyped(character: Char): Boolean {
return super.keyTyped(character)
}
override fun resize(width: Int, height: Int) {
super.resize(width, height)
}
}

View File

@@ -16,11 +16,11 @@ import net.torvald.terrarum.ui.UICanvas
class UICheatDetected : UICanvas() {
override var width: Int
get() = AppLoader.screenW
get() = AppLoader.screenSize.screenW
set(value) { throw UnsupportedOperationException() }
override var height: Int
get() = AppLoader.screenH
get() = AppLoader.screenSize.screenH
set(value) { throw UnsupportedOperationException() }
override var openCloseTime: Second = 0f

View File

@@ -6,7 +6,6 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.*
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameactors.ActorInventory
import net.torvald.terrarum.modulebasegame.gameactors.FixtureInventory
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.CELLS_HOR
import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull.Companion.CELLS_VRT
@@ -23,8 +22,8 @@ internal class UIInventoryCells(
val full: UIInventoryFull
) : UICanvas() {
override var width: Int = AppLoader.screenW
override var height: Int = AppLoader.screenH
override var width: Int = AppLoader.screenSize.screenW
override var height: Int = AppLoader.screenSize.screenH
override var openCloseTime: Second = 0.0f
companion object {
@@ -56,7 +55,7 @@ internal class UIInventoryCells(
full,
full.actor.inventory,
full.actor as ActorWithBody,
internalWidth - UIItemInventoryEquippedView.WIDTH + (AppLoader.screenW - internalWidth) / 2,
internalWidth - UIItemInventoryEquippedView.WIDTH + (AppLoader.screenSize.screenW - internalWidth) / 2,
INVENTORY_CELLS_OFFSET_Y,
{ rebuildList() }
)

View File

@@ -15,8 +15,8 @@ import net.torvald.terrarum.ui.UIItemTextButtonList.Companion.DEFAULT_LINE_HEIGH
class UIInventoryEscMenu(val full: UIInventoryFull) : UICanvas() {
override var width: Int = AppLoader.screenW
override var height: Int = AppLoader.screenH
override var width: Int = AppLoader.screenSize.screenW
override var height: Int = AppLoader.screenSize.screenH
override var openCloseTime = 0.0f
private val gameMenu = arrayOf("MENU_LABEL_MAINMENU", "MENU_LABEL_DESKTOP", "MENU_OPTIONS_CONTROLS", "MENU_OPTIONS_SOUND", "MENU_LABEL_GRAPHICS")
@@ -24,7 +24,7 @@ class UIInventoryEscMenu(val full: UIInventoryFull) : UICanvas() {
private val gameMenuListWidth = 400
private val gameMenuButtons = UIItemTextButtonList(
this, gameMenu,
(AppLoader.screenW - gameMenuListWidth) / 2,
(AppLoader.screenSize.screenW - gameMenuListWidth) / 2,
INVENTORY_CELLS_OFFSET_Y + (INVENTORY_CELLS_UI_HEIGHT - gameMenuListHeight) / 2,
gameMenuListWidth, gameMenuListHeight,
readFromLang = true,

View File

@@ -25,8 +25,8 @@ class UIInventoryFull(
doNotWarnConstant: Boolean = false
) : UICanvas(toggleKeyLiteral, toggleButtonLiteral, customPositioning, doNotWarnConstant) {
override var width: Int = AppLoader.screenW
override var height: Int = AppLoader.screenH
override var width: Int = AppLoader.screenSize.screenW
override var height: Int = AppLoader.screenSize.screenH
override var openCloseTime: Second = 0.0f
companion object {
@@ -34,7 +34,7 @@ class UIInventoryFull(
const val REQUIRED_MARGIN: Int = 138 // hard-coded value. Don't know the details. Range: [91-146]. I chose MAX-8 because cell gap is 8
const val CELLS_HOR = 10
val CELLS_VRT: Int; get() = (AppLoader.screenH - REQUIRED_MARGIN - 134 + UIItemInventoryItemGrid.listGap) / // 134 is another magic number
val CELLS_VRT: Int; get() = (AppLoader.screenSize.screenH - REQUIRED_MARGIN - 134 + UIItemInventoryItemGrid.listGap) / // 134 is another magic number
(UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap)
const val itemListToEquipViewGap = UIItemInventoryItemGrid.listGap // used to be 24; figured out that the extra gap does nothig
@@ -45,8 +45,8 @@ class UIInventoryFull(
val itemListHeight: Int = CELLS_VRT * UIItemInventoryElemSimple.height + (CELLS_VRT - 1) * net.torvald.terrarum.modulebasegame.ui.UIItemInventoryItemGrid.Companion.listGap
val INVENTORY_CELLS_UI_HEIGHT: Int = CELLS_VRT * UIItemInventoryElemSimple.height + (CELLS_VRT - 1) * UIItemInventoryItemGrid.listGap
val INVENTORY_CELLS_OFFSET_X = 0 + (AppLoader.screenW - internalWidth) / 2
val INVENTORY_CELLS_OFFSET_Y: Int = 107 + (AppLoader.screenH - internalHeight) / 2
val INVENTORY_CELLS_OFFSET_X = 0 + (AppLoader.screenSize.screenW - internalWidth) / 2
val INVENTORY_CELLS_OFFSET_Y: Int = 107 + (AppLoader.screenSize.screenH - internalHeight) / 2
val catBarWidth = 330
@@ -60,7 +60,7 @@ class UIInventoryFull(
//val REQUIRED_MARGIN: Int = 138 // hard-coded value. Don't know the details. Range: [91-146]. I chose MAX-8 because cell gap is 8
//val CELLS_HOR = 10
//val CELLS_VRT: Int; get() = (AppLoader.screenH - REQUIRED_MARGIN - 134 + UIItemInventoryItemGrid.listGap) / // 134 is another magic number
//val CELLS_VRT: Int; get() = (AppLoader.terrarumAppConfig.screenH - REQUIRED_MARGIN - 134 + UIItemInventoryItemGrid.listGap) / // 134 is another magic number
// (UIItemInventoryElemSimple.height + UIItemInventoryItemGrid.listGap)
//private val itemListToEquipViewGap = UIItemInventoryItemGrid.listGap // used to be 24; figured out that the extra gap does nothig
@@ -71,8 +71,8 @@ class UIInventoryFull(
//val itemListHeight: Int = CELLS_VRT * UIItemInventoryElemSimple.height + (CELLS_VRT - 1) * net.torvald.terrarum.modulebasegame.ui.UIItemInventoryItemGrid.Companion.listGap
//val INVENTORY_CELLS_UI_HEIGHT: Int = CELLS_VRT * UIItemInventoryElemSimple.height + (CELLS_VRT - 1) * UIItemInventoryItemGrid.listGap
//val INVENTORY_CELLS_OFFSET_X = 0 + (AppLoader.screenW - internalWidth) / 2
//val INVENTORY_CELLS_OFFSET_Y: Int = 107 + (AppLoader.screenH - internalHeight) / 2
//val INVENTORY_CELLS_OFFSET_X = 0 + (AppLoader.terrarumAppConfig.screenW - internalWidth) / 2
//val INVENTORY_CELLS_OFFSET_Y: Int = 107 + (AppLoader.terrarumAppConfig.screenH - internalHeight) / 2
init {
handler.allowESCtoClose = true
@@ -113,8 +113,8 @@ class UIInventoryFull(
val catBar = UIItemInventoryCatBar(
this,
(AppLoader.screenW - catBarWidth) / 2,
42 + (AppLoader.screenH - internalHeight) / 2,
(AppLoader.screenSize.screenW - catBarWidth) / 2,
42 + (AppLoader.screenSize.screenH - internalHeight) / 2,
internalWidth,
catBarWidth,
true,
@@ -127,10 +127,10 @@ class UIInventoryFull(
private val transitionalEscMenu = UIInventoryEscMenu(this)
private val transitionPanel = UIItemHorizontalFadeSlide(
this,
(AppLoader.screenW - internalWidth) / 2,
(AppLoader.screenSize.screenW - internalWidth) / 2,
INVENTORY_CELLS_OFFSET_Y,
AppLoader.screenW,
AppLoader.screenH,
AppLoader.screenSize.screenW,
AppLoader.screenSize.screenH,
1f,
transitionalMinimap, transitionalItemCells, transitionalEscMenu
)
@@ -151,9 +151,9 @@ class UIInventoryFull(
}
internal var offsetX = ((AppLoader.screenW - internalWidth) / 2).toFloat()
internal var offsetX = ((AppLoader.screenSize.screenW - internalWidth) / 2).toFloat()
private set
internal var offsetY = ((AppLoader.screenH - internalHeight) / 2).toFloat()
internal var offsetY = ((AppLoader.screenSize.screenH - internalHeight) / 2).toFloat()
private set
fun requestTransition(target: Int) = transitionPanel.requestTransition(target)
@@ -172,9 +172,9 @@ class UIInventoryFull(
//private val gradHeight = 48f
private val shapeRenderer = ShapeRenderer()
internal var xEnd = (AppLoader.screenW + internalWidth).div(2).toFloat()
internal var xEnd = (AppLoader.screenSize.screenW + internalWidth).div(2).toFloat()
private set
internal var yEnd = (AppLoader.screenH + internalHeight).div(2).toFloat()
internal var yEnd = (AppLoader.screenSize.screenH + internalHeight).div(2).toFloat()
private set
override fun renderUI(batch: SpriteBatch, camera: Camera) {
@@ -185,17 +185,17 @@ class UIInventoryFull(
gdxSetBlendNormal()
val gradTopStart = (AppLoader.screenH - internalHeight).div(2).toFloat()
val gradBottomEnd = AppLoader.screenH - gradTopStart
val gradTopStart = (AppLoader.screenSize.screenH - internalHeight).div(2).toFloat()
val gradBottomEnd = AppLoader.screenSize.screenH - gradTopStart
shapeRenderer.inUse {
shapeRenderer.rect(0f, gradTopStart, AppLoader.screenWf, gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
shapeRenderer.rect(0f, gradBottomEnd, AppLoader.screenWf, -gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
shapeRenderer.rect(0f, gradTopStart, AppLoader.screenSize.screenWf, gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
shapeRenderer.rect(0f, gradBottomEnd, AppLoader.screenSize.screenWf, -gradHeight, gradStartCol, gradStartCol, gradEndCol, gradEndCol)
shapeRenderer.rect(0f, gradTopStart + gradHeight, AppLoader.screenWf, internalHeight - (2 * gradHeight), gradEndCol, gradEndCol, gradEndCol, gradEndCol)
shapeRenderer.rect(0f, gradTopStart + gradHeight, AppLoader.screenSize.screenWf, internalHeight - (2 * gradHeight), gradEndCol, gradEndCol, gradEndCol, gradEndCol)
shapeRenderer.rect(0f, 0f, AppLoader.screenWf, gradTopStart, gradStartCol, gradStartCol, gradStartCol, gradStartCol)
shapeRenderer.rect(0f, AppLoader.screenHf, AppLoader.screenWf, -(AppLoader.screenHf - gradBottomEnd), gradStartCol, gradStartCol, gradStartCol, gradStartCol)
shapeRenderer.rect(0f, 0f, AppLoader.screenSize.screenWf, gradTopStart, gradStartCol, gradStartCol, gradStartCol, gradStartCol)
shapeRenderer.rect(0f, AppLoader.screenSize.screenHf, AppLoader.screenSize.screenWf, -(AppLoader.screenSize.screenHf - gradBottomEnd), gradStartCol, gradStartCol, gradStartCol, gradStartCol)
}
@@ -255,11 +255,11 @@ class UIInventoryFull(
override fun resize(width: Int, height: Int) {
super.resize(width, height)
offsetX = ((AppLoader.screenW - internalWidth) / 2).toFloat()
offsetY = ((AppLoader.screenH - internalHeight) / 2).toFloat()
offsetX = ((AppLoader.screenSize.screenW - internalWidth) / 2).toFloat()
offsetY = ((AppLoader.screenSize.screenH - internalHeight) / 2).toFloat()
xEnd = (AppLoader.screenW + internalWidth).div(2).toFloat()
yEnd = (AppLoader.screenH + internalHeight).div(2).toFloat()
xEnd = (AppLoader.screenSize.screenW + internalWidth).div(2).toFloat()
yEnd = (AppLoader.screenSize.screenH + internalHeight).div(2).toFloat()
}
}

View File

@@ -15,8 +15,8 @@ class UIInventoryMinimap(val full: UIInventoryFull) : UICanvas() {
private val debugvals = true
override var width: Int = AppLoader.screenW
override var height: Int = AppLoader.screenH
override var width: Int = AppLoader.screenSize.screenW
override var height: Int = AppLoader.screenSize.screenH
override var openCloseTime = 0.0f
private val MINIMAP_WIDTH = 800f
@@ -115,23 +115,23 @@ class UIInventoryMinimap(val full: UIInventoryFull) : UICanvas() {
batch.begin()
if (debugvals) {
AppLoader.fontSmallNumbers.draw(batch, "$minimapPanX, $minimapPanY; x$minimapZoom", (AppLoader.screenW - MINIMAP_WIDTH) / 2, -10f + INVENTORY_CELLS_OFFSET_Y)
AppLoader.fontSmallNumbers.draw(batch, "$minimapPanX, $minimapPanY; x$minimapZoom", (AppLoader.screenSize.screenW - MINIMAP_WIDTH) / 2, -10f + INVENTORY_CELLS_OFFSET_Y)
}
batch.projectionMatrix = camera.combined
// 1px stroke
batch.color = Color.WHITE
batch.fillRect((AppLoader.screenW - MINIMAP_WIDTH) / 2, -1 + INVENTORY_CELLS_OFFSET_Y.toFloat(), MINIMAP_WIDTH, 1f)
batch.fillRect((AppLoader.screenW - MINIMAP_WIDTH) / 2, INVENTORY_CELLS_OFFSET_Y + MINIMAP_HEIGHT, MINIMAP_WIDTH, 1f)
batch.fillRect(-1 + (AppLoader.screenW - MINIMAP_WIDTH) / 2, INVENTORY_CELLS_OFFSET_Y.toFloat(), 1f, MINIMAP_HEIGHT)
batch.fillRect((AppLoader.screenW - MINIMAP_WIDTH) / 2 + MINIMAP_WIDTH, INVENTORY_CELLS_OFFSET_Y.toFloat(), 1f, MINIMAP_HEIGHT)
batch.fillRect((AppLoader.screenSize.screenW - MINIMAP_WIDTH) / 2, -1 + INVENTORY_CELLS_OFFSET_Y.toFloat(), MINIMAP_WIDTH, 1f)
batch.fillRect((AppLoader.screenSize.screenW - MINIMAP_WIDTH) / 2, INVENTORY_CELLS_OFFSET_Y + MINIMAP_HEIGHT, MINIMAP_WIDTH, 1f)
batch.fillRect(-1 + (AppLoader.screenSize.screenW - MINIMAP_WIDTH) / 2, INVENTORY_CELLS_OFFSET_Y.toFloat(), 1f, MINIMAP_HEIGHT)
batch.fillRect((AppLoader.screenSize.screenW - MINIMAP_WIDTH) / 2 + MINIMAP_WIDTH, INVENTORY_CELLS_OFFSET_Y.toFloat(), 1f, MINIMAP_HEIGHT)
// control hints
batch.color = Color.WHITE
AppLoader.fontGame.draw(batch, full.minimapControlHelp, full.offsetX, full.yEnd - 20)
// the minimap
batch.draw(minimapFBO.colorBufferTexture, (AppLoader.screenW - MINIMAP_WIDTH) / 2, INVENTORY_CELLS_OFFSET_Y.toFloat())
batch.draw(minimapFBO.colorBufferTexture, (AppLoader.screenSize.screenW - MINIMAP_WIDTH) / 2, INVENTORY_CELLS_OFFSET_Y.toFloat())
}
override fun doOpening(delta: Float) {}

View File

@@ -523,12 +523,12 @@ class UIItemInventoryItemGrid(
return true
}
override fun scrolled(amount: Int): Boolean {
super.scrolled(amount)
override fun scrolled(amountX: Float, amountY: Float): Boolean {
super.scrolled(amountX, amountY)
// scroll the item list (for now)
if (mouseUp) {
scrollItemPage(amount)
scrollItemPage(amountX.toInt())
}
return true

View File

@@ -46,40 +46,4 @@ class UIProxyNewBuildingMaker : UICanvas() {
override fun dispose() {
TODO("not implemented")
}
override fun mouseMoved(screenX: Int, screenY: Int): Boolean {
return super.mouseMoved(screenX, screenY)
}
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
return super.touchDragged(screenX, screenY, pointer)
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
return super.touchDown(screenX, screenY, pointer, button)
}
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
return super.touchUp(screenX, screenY, pointer, button)
}
override fun scrolled(amount: Int): Boolean {
return super.scrolled(amount)
}
override fun keyDown(keycode: Int): Boolean {
return super.keyDown(keycode)
}
override fun keyUp(keycode: Int): Boolean {
return super.keyUp(keycode)
}
override fun keyTyped(character: Char): Boolean {
return super.keyTyped(character)
}
override fun resize(width: Int, height: Int) {
super.resize(width, height)
}
}

View File

@@ -62,40 +62,4 @@ class UIProxyNewRandomGame : UICanvas() {
override fun dispose() {
TODO("not implemented")
}
override fun mouseMoved(screenX: Int, screenY: Int): Boolean {
return super.mouseMoved(screenX, screenY)
}
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
return super.touchDragged(screenX, screenY, pointer)
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
return super.touchDown(screenX, screenY, pointer, button)
}
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
return super.touchUp(screenX, screenY, pointer, button)
}
override fun scrolled(amount: Int): Boolean {
return super.scrolled(amount)
}
override fun keyDown(keycode: Int): Boolean {
return super.keyDown(keycode)
}
override fun keyUp(keycode: Int): Boolean {
return super.keyUp(keycode)
}
override fun keyTyped(character: Char): Boolean {
return super.keyTyped(character)
}
override fun resize(width: Int, height: Int) {
super.resize(width, height)
}
}

View File

@@ -83,10 +83,10 @@ class UIQuickslotBar : UICanvas() {
handler.opacity = 0f
}
override fun scrolled(amount: Int): Boolean {
override fun scrolled(amountX: Float, amountY: Float): Boolean {
// super.scrolled(amount) // no UIItems here
selection = selection.plus(if (amount > 1) 1 else if (amount < -1) -1 else 0).fmod(SLOT_COUNT)
selection = selection.plus(if (amountX > 1) 1 else if (amountX < -1) -1 else 0).fmod(SLOT_COUNT)
return true
}

View File

@@ -49,7 +49,7 @@ class UIQuickslotPie : UICanvas() {
// update controls
if (handler.isOpened || handler.isOpening) {
val cursorPos = Vector2(Terrarum.mouseScreenX.toDouble(), Terrarum.mouseScreenY.toDouble())
val centre = Vector2(AppLoader.halfScreenW.toDouble(), AppLoader.halfScreenH.toDouble())
val centre = Vector2(AppLoader.screenSize.halfScreenW.toDouble(), AppLoader.screenSize.halfScreenH.toDouble())
val deg = -(centre - cursorPos).direction.toFloat()
selection = Math.round(deg * slotCount / FastMath.TWO_PI)

View File

@@ -8,7 +8,6 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.AppLoader.printdbgerr
import net.torvald.terrarum.QNDTreeNode
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.Yaml
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItemTextButton
@@ -221,9 +220,9 @@ open class UIRemoCon(treeRepresentation: QNDTreeNode<String>) : UICanvas() {
return true
}
override fun scrolled(amount: Int): Boolean {
override fun scrolled(amountX: Float, amountY: Float): Boolean {
screens.forEach {
it.second.scrolled(amount) // again, underlying handler will block unnecessary renders
it.second.scrolled(amountX, amountY) // again, underlying handler will block unnecessary renders
}
return true
@@ -300,6 +299,6 @@ open class UIRemoCon(treeRepresentation: QNDTreeNode<String>) : UICanvas() {
val remoConWidth = 304
fun getRemoConHeight(menu: ArrayList<String>) = DEFAULT_LINE_HEIGHT * menu.size.plus(1)
fun getRemoConHeight(menu: Array<String>) = DEFAULT_LINE_HEIGHT * menu.size.plus(1)
val menubarOffY: Int; get() = AppLoader.screenH / 2 - (AppLoader.fontGame.lineHeight * 1.5).toInt()
val menubarOffY: Int; get() = AppLoader.screenSize.screenH / 2 - (AppLoader.fontGame.lineHeight * 1.5).toInt()
}
}

View File

@@ -6,6 +6,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.EMDASH
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.TerrarumScreenSize
import net.torvald.terrarum.keyToIcon
import net.torvald.terrarum.ui.Movement
import net.torvald.terrarum.ui.UICanvas
@@ -39,8 +40,8 @@ class UIScreenZoom : UICanvas(
AppLoader.fontGame.draw(
batch, zoomText,
(AppLoader.screenW * AppLoader.TV_SAFE_GRAPHICS + 1).toInt().toFloat(),
(AppLoader.screenH - height - AppLoader.getTvSafeGraphicsHeight()).toFloat()
(AppLoader.screenSize.screenW * TerrarumScreenSize.TV_SAFE_GRAPHICS + 1).toInt().toFloat(),
(AppLoader.screenSize.screenH - height - AppLoader.screenSize.tvSafeGraphicsHeight).toFloat()
)
}

View File

@@ -19,8 +19,8 @@ class UITitleCharactersList : UICanvas() {
private val moduleAreaHMargin = 48
private val moduleAreaBorder = 8
override var width = AppLoader.screenW - UIRemoCon.remoConWidth - moduleAreaHMargin
override var height = AppLoader.screenH - moduleAreaHMargin * 2
override var width = AppLoader.screenSize.screenW - UIRemoCon.remoConWidth - moduleAreaHMargin
override var height = AppLoader.screenSize.screenH - moduleAreaHMargin * 2
private val moduleInfoCells = ArrayList<UIItemSavegameInfoCell>()
// build characters list

View File

@@ -3,7 +3,6 @@ package net.torvald.terrarum.modulebasegame.ui
import com.badlogic.gdx.graphics.Camera
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.Second
import net.torvald.terrarum.langpack.Lang
@@ -21,13 +20,13 @@ class UITitleLanguage : UICanvas() {
private val textAreaHMargin = 48
override var width = (AppLoader.screenW * 0.75).toInt()
override var height = AppLoader.screenH - textAreaHMargin * 2
override var width = (AppLoader.screenSize.screenW * 0.75).toInt()
override var height = AppLoader.screenSize.screenH - textAreaHMargin * 2
private val localeList = Lang.languageList.toList().sorted()
private val textArea = UIItemTextButtonList(this,
localeList.map { Lang.langpack["MENU_LANGUAGE_THIS_$it"] ?: "!ERR: $it" }.toTypedArray(),
AppLoader.screenW - width, textAreaHMargin,
AppLoader.screenSize.screenW - width, textAreaHMargin,
width, height,
textAreaWidth = width,
readFromLang = false,

View File

@@ -21,8 +21,8 @@ class UITitleModules : UICanvas() {
private val moduleAreaHMargin = 48
private val moduleAreaBorder = 8
override var width = AppLoader.screenW - UIRemoCon.remoConWidth - moduleAreaHMargin
override var height = AppLoader.screenH - moduleAreaHMargin * 2
override var width = AppLoader.screenSize.screenW - UIRemoCon.remoConWidth - moduleAreaHMargin
override var height = AppLoader.screenSize.screenH - moduleAreaHMargin * 2
private val moduleInfoCells = ArrayList<UIItemModuleInfoCell>()

View File

@@ -6,7 +6,7 @@ package net.torvald.terrarum.modulebasegame.ui
val remoConWidth = 240
fun getRemoConHeight(menu: ArrayList<String>) = 36 * menu.size.plus(1)
fun getRemoConHeight(menu: Array<String>) = 36 * menu.size.plus(1)
val menubarOffY: Int; get() = AppLoader.screenH / 2 - (AppLoader.fontGame.lineHeight * 1.5).toInt()
val menubarOffY: Int; get() = AppLoader.terrarumAppConfig.screenH / 2 - (AppLoader.fontGame.lineHeight * 1.5).toInt()
}

View File

@@ -15,8 +15,8 @@ open class UITitleWallOfText(private val text: List<String>) : UICanvas() {
private val textAreaHMargin = 48
override var width = AppLoader.screenW - UIRemoCon.remoConWidth - textAreaHMargin
override var height = AppLoader.screenH - textAreaHMargin * 2
override var width = AppLoader.screenSize.screenW - UIRemoCon.remoConWidth - textAreaHMargin
override var height = AppLoader.screenSize.screenH - textAreaHMargin * 2
private val textArea = UIItemTextArea(this,
UIRemoCon.remoConWidth, textAreaHMargin,
width, height

View File

@@ -50,8 +50,8 @@ class UIVitalMetre(
override fun updateUI(delta: Float) {
handler.setPosition(
AppLoader.halfScreenW,
AppLoader.halfScreenH
AppLoader.screenSize.halfScreenW,
AppLoader.screenSize.halfScreenH
)
}

View File

@@ -99,8 +99,8 @@ internal object WeatherMixer : RNGConsumer {
val playerPosY = player.hitbox.centeredY
kotlin.repeat(7) {
val rainParticle = ParticleMegaRain(
playerPosX + HQRNG().nextInt(AppLoader.screenW) - AppLoader.halfScreenW,
playerPosY - AppLoader.screenH
playerPosX + HQRNG().nextInt(AppLoader.screenSize.screenW) - AppLoader.screenSize.halfScreenW,
playerPosY - AppLoader.screenSize.screenH
)
(Terrarum.ingame!! as TerrarumIngame).addParticle(rainParticle)
}
@@ -187,7 +187,7 @@ internal object WeatherMixer : RNGConsumer {
batch.shader = null
}
batch.inUse {
it.draw(skyboxTexture, 0f, -AppLoader.halfScreenHf, AppLoader.screenWf, AppLoader.screenHf * 2f) // because of how the linear filter works, we extend the image by two
it.draw(skyboxTexture, 0f, -AppLoader.screenSize.halfScreenHf, AppLoader.screenSize.screenWf, AppLoader.screenSize.screenHf * 2f) // because of how the linear filter works, we extend the image by two
}
// don't use shader to just fill the whole screen... frag shader will be called a million times and it's best to not burden it

View File

@@ -53,7 +53,7 @@ abstract class Gen(val world: GameWorld, val seed: Long, val params: Any) {
data class WorldgenParams(
val seed: Long,
// optional parametres
// optional parameters
val terragenParams: TerragenParams = TerragenParams(),
val biomegenParams: BiomegenParams = BiomegenParams()
)

View File

@@ -1,27 +0,0 @@
_G.parsecmd = function(str)
local parsetable = {}
local quotemode = false
local wordbuffer = ""
for c = 1, #str do
local char = str:byte(c)
if not quotemode and char == 32 then -- quotestack is empty and char is a space
table.insert(parsetable, wordbuffer)
wordbuffer = ""
elseif char == 34 then -- "
quotemode = not quotemode
else
wordbuffer = wordbuffer..string.char(char)
end
end
if #wordbuffer ~= 0 then
table.insert(parsetable, wordbuffer)
end
return parsetable
end
_G.TODO = function(str)
error("Not implemented: "..str or "TODO", 2)
end

View File

@@ -1,6 +0,0 @@
local args = {...}
if (#args ~= 2) then
print([[usage: cp source_file target_file
cp source_file target_directory]])
return end
fs.cp(os.expandPath(args[1]), os.expandPath(args[2]))

View File

@@ -1,257 +0,0 @@
local args = {...}
os.dshenv = {}
--[[
DUMBSHELL: semi sh-compatible language interpreter
SYNOPSIS
dsh [option] [file]
sh [option] [file]
OPTIONS
-c string If the -c option is present, then commands are read from
string. If there are arguments after the string, they are
assigned to the positional parameters, starting with $0.
]]
-- returns full path. if p starts with "/", only the p is returned
local function expandPath(p)
return (p:byte(1) == 47) and p or os.expandPath(p)
end
local function startsFromRoot(p)
return p:byte(1) == 47
end
local function endsWithSlash(p)
return p:byte(#p) == 47
end
--__DSHDEBUG__ = 0x51621D
local function debug(msg)
if __DSHDEBUG__ then print("DEBUG", msg) end
end
local function printErr(msg)
print(DLE..msg)
end
local function shallowCopy(t)
return {table.unpack(t)}
end
-- BUILTINS -------------------------------------------------------------------
local function cd(tArgs)
local dir = tArgs[1]
if (dir == nil or #dir < 1) then return end
local oldWorkingDir = shallowCopy(os.workingDir)
-- parse dir by delimeter '/'
if (dir:byte(1) == 47) then -- if dir begins with '/'
os.setWorkingDir(dir)
else
for word in string.gmatch(dir, "[^/]+") do
machine.println("CD word: "..word)
-- 'execute' directory
-- Rules: '..' pops os.workingDir
-- if dir begins with '/', re-build os.workingDir
-- otherwise, push the 'word' to os.workingDir
if (word == "..") then
os.popWorkingDir()
elseif (word == ".") then
-- pass
else
os.pushWorkingDir(word)
end
end
end
-- check if the directory exists
if not fs.isDir(os.fullWorkPath()) then
os.errorNoSuchFileOrDir("cd: "..dir)
os.workingDir = shallowCopy(oldWorkingDir)
return
end
end
local function exit(tArgs)
exitshell = true
end
local function exec(tArgs)
debug("EXECARGS\t"..table.concat(tArgs, ", "))
if (tArgs[1] == nil or #tArgs[1] < 1) then return end
local filePath = tArgs[1]
local fullFilePath = expandPath(tArgs[1])
local execArgs = {}
for i, v in ipairs(tArgs) do
if (i >= 2) then table.insert(execArgs, v) end
end
local execByPathFileExists = false
local execByPathArg = ""
-- do some sophisticated file-matching
-- step 1: exact file
if fs.isFile(fullFilePath) then
shell.run(fullFilePath, execArgs)
-- step 2: try appending ".lua"
elseif fs.isFile(fullFilePath..".lua") then
shell.run(fullFilePath..".lua", execArgs)
-- step 3: parse os.path (just like $PATH)
-- step 3.1: exact file; step 3.2: append ".lua"
elseif not startsFromRoot(filePath) then
for path in string.gmatch(os.path, "[^;]+") do
-- check if 'path' ends with '/'
if not endsWithSlash(path) then path = path.."/" end
debug(path..filePath)
if fs.isFile(path..filePath) then
execByPathArg = path..filePath
execByPathFileExists = true
break
elseif fs.isFile(path..filePath..".lua") then
execByPathArg = path..filePath..".lua"
execByPathFileExists = true
break
end
end
end
-- step else: file not found
if execByPathFileExists then
shell.run(execByPathArg, execArgs)
return EXIT_SUCCESS
else
if filePath:byte(1) == 46 or filePath:byte(1) == 47 then
os.errorNoSuchFile(filePath)
else
os.errorCmdNotFound(filePath)
end
end
return false
end
-- SYNTAX PARSER --------------------------------------------------------------
-- tables with functions
local builtins = {
cd = cd,
exit = exit,
exec = exec,
clear = term.clear
}
local function runcommand(str, recurse)
if #str < 1 then return end
local cmdFound = false
-- simple cmd parse: WORD ARG1 ARG2 ARG3 ...
local args = {}
local command = ""
for word in string.gmatch(str, "[^ ]+") do
if #command < 1 then command = word -- first word will be a name of command
else table.insert(args, word) end
end
if builtins[command] then -- try for builtins table
builtins[command](args)
cmdFound = true
return true
else
-- FIXME: 'exec programname args' works, but not 'programname args'
-- try for os.dshenv.aliases
if os.dshenv.aliases[command] then
--builtins[os.dshenv.aliases[command]](args)
if not recurse then
cmdFound = runcommand(os.dshenv.aliases[command], true)
end
else
-- try to launch as program
if not recurse then
cmdFound = runcommand("exec "..str, true)
end
end
end
-- command not found (really)
if not cmdFound then
os.errorCmdNotFound(command)
end
end
-- END OF SYNTAX PARSER -------------------------------------------------------
-- INIT SHELL -----------------------------------------------------------------
exitshell = false
-- load up aliases
if fs.isFile("/etc/.dshrc") then
fs.dofile("/etc/.dshrc")
machine.println("[dummix/dsh.lua] Dsh aliases successfully loaded.")
end
-- END OF INIT SHELL ----------------------------------------------------------
-- run interpreter and quit
if (args[1]) then
local f = fs.open(args[1], "r")
local line = ""
local s = ""
-- treat interpreter key (#!) properly
-- I'm assuming I was called because I'm the right one
-- I have a full trust on "shell.run()" that it rightfully redirected to me
--
-- NOTE: shell redirection should only apply in interactive mode AND the input
-- was like "./filename", or else I'm the right one. Period.
-- (and that's how BASH works)
repeat
line = f.readLine()
if line == nil then break end
if line:sub(1,2) ~= "#!" then -- ignore line that contains hashbang
s = s.." "..line
end
until line == nil
f.close()
runcommand(s)
exitshell = true
end
function getPromptText()
--return DC4..os.workingDir[#os.workingDir]..DC3.."# "..DC4 -- we're root! omgwtf
return DC4..os.fullWorkPath()..DC3.."# "..DC4 -- we're root! omgwtf
end
-- interactive mode
local time = os.date()
print(time)
repeat
term.setCursorBlink(true)
io.write(getPromptText())
local s = input.readLine()
runcommand(s)
until exitshell
collectgarbage()
return EXIT_SUCCESS

View File

@@ -1,170 +0,0 @@
--[[
LESS IS MORE
SYNOPSIS:
lessismore [filename]
less [filename]
more [filename]
]]
local args = {...}
displayLineNo = true
local prompt = function()
term.setForeCol(3)
term.emitString(" scroll ", 3, term.height())
term.emitString(" quit", 14, term.height())
term.setForeCol(1)
term.emit(18, 1, term.height())
term.emit(29, 2, term.height())
term.emit(81, 13, term.height())
term.setForeCol(3)
term.setBackCol(0)
end
local function printUsage()
print("More: no file specified.")
print("Usage: more [filename]")
end
if args[1] == nil or #args[1] <= 0 then printUsage() return end
filepath = os.expandPath(args[1])
if not fs.isFile(filepath) then os.errorNoSuchFile(filepath) return end
function log10(n)
if n < 1 then return 0
elseif n < 10 then return 1
elseif n < 100 then return 2
elseif n < 1000 then return 3
elseif n < 10000 then return 4
elseif n < 100000 then return 5
elseif n < 1000000 then return 6
elseif n < 10000000 then return 7
elseif n < 100000000 then return 8
elseif n < 1000000000 then return 9
else return 10
end
end
----------------
-- fetch text --
----------------
lines = {}
displayHeight = term.height() - 1 -- bottom one line for prompt
local file = fs.open(filepath, "r")
local line = ""
repeat
line = file.readLine()
table.insert(lines, line)
until line == nil
lineNoLen = log10(#lines)
-----------
-- input --
-----------
local function scrollDownAction(n)
term.clearLine() -- prevent prompt to be scrolled
curY = curY + n
-- prevent overscroll
if (curY > #lines - displayHeight) then
curY = #lines - displayHeight
end
term.scroll(n)
for i = 0, n - 1 do
drawString(curY + displayHeight - i, displayHeight - i) -- redraw newline
end
end
local function scrollUpAction(n)
curY = curY - n
-- prevent overscroll
if (curY < 1) then
curY = 1
end
term.scroll(-n)
for i = 0, n - 1 do
drawString(curY + i, i + 1) -- redraw prev line
end
term.setCursor(n, term.height())
end
local function processInput()
if input.isKeyDown(keys.q) then quit = true end
if input.isKeyDown(keys.down) and curY < #lines - displayHeight then
scrollDownAction(1)
prompt()
elseif input.isKeyDown(keys.pageDown) and curY < #lines - displayHeight then
scrollDownAction(8)
prompt()
elseif input.isKeyDown(keys.up) and curY > 1 then
scrollUpAction(1)
term.clearLine() -- make space for prompt
prompt()
elseif input.isKeyDown(keys.pageUp) and curY > 1 then
scrollUpAction(8)
term.clearLine() -- make space for prompt
prompt()
end
machine.sleep(50)
end
-------------
-- display --
-------------
displayWidth = term.width() - 1 - (displayLineNo and lineNoLen or 0)
function drawString(lineNo, y)
local string = (lineNo > #lines) and ""
or lines[lineNo]:sub(curX, curX + displayWidth)
if (displayLineNo) then
local lineNoStr = DC3..string.format("%"..lineNoLen.."d", curY + y - 1)..DC4
string = lineNoStr..string
end
local strDrawX = curX
term.emitString(string, strDrawX, y)
end
function redrawText()
for i = curY, #lines do
if (i >= displayHeight + curY) then break end
drawString(i, i - curY + 1)
end
end
curY = 1
curX = 1
quit = false
if term.isTeletype() then
for _, l in ipairs(line) do
term.print(l)
end
quit = true
end
term.clear()
term.setCursorBlink(false)
redrawText()
repeat
prompt()
term.setCursor(1, term.height())
processInput()
until quit
term.clearLine()
return

View File

@@ -1,10 +0,0 @@
local args = {...}
local dir = os.fullWorkPath()--(#args < 1) and os.fullWorkPath() or args[1]
local list = fs.list("/"..dir)
table.sort(list)
for _, v in ipairs(list) do
print(v)
end

View File

@@ -1,76 +0,0 @@
local args = {...}
local _APPVERSION = 0.3
--[[
MOONSHELL: basically just lua.lua
SYNOPSIS
msh [file]
msh: Runs shell in interactive mode
msh [file]: Try to execute file as Lua script
]]
-- run interpreter and quit
if (args[1]) then
local f = fs.open(args[1], "r")
local line = ""
local s = ""
-- treat interpreter key (#!) properly
-- I'm assuming I was called because I'm the right one
-- I have a full trust on "shell.run()" that it rightfully redirected to me
repeat
line = f.readLine()
if line == nil then break end
if line:sub(1,2) ~= "#!" then -- ignore line that contains hashbang
s = s.." "..line
end
until line == nil
f.close()
xpcall(
function() _G.runscript(s, "="..args[1]) end,
function(err) print(DLE..err) end
)
goto terminate
end
-- interactive mode. This is a copy of BOOT.lua
run = shell.run
print("Moonshell "..DC2.._APPVERSION..DC4..", running "..DC2.._VERSION..DC4)
print("Lua is copyrighted (C) 1994-2013 Lua.org, PUC-Rio")
print("Run run(path) to execute program on 'path'.")
print("Run exit() to quit.")
while not machine.isHalted() do
term.setCursorBlink(true)
io.write(DC3.."lua"..computer.prompt)
local s = input.readLine()
if s == "exit()" then break end
xpcall(
function()
if s:byte(1) == 61 then -- print out value
s1 = string.sub(s, 2)
_G.runscript("print(tostring("..s1.."))\n", "=stdin")
else
_G.runscript(s, "=stdin")
end
end,
function(err) print(DLE..err) end -- it catches logical errors
)
end
::terminate::
collectgarbage()
return EXIT_SUCCESS

View File

@@ -1,6 +0,0 @@
local args = {...}
if (#args ~= 2) then
print([[usage: mv source target
mv source ... directory]])
return end
fs.mv(os.expandPath(args[1]), os.expandPath(args[2]))

View File

@@ -1 +0,0 @@
fs.dofile("/etc/_boot.lua")

View File

@@ -1,8 +0,0 @@
-- dsh aliases
os.dshenv.aliases = {
lua = "msh",
sh = "dsh",
shutdown = "exit", -- should be a separate program that actually halts the system
less = "lessismore",
more = "lessismore"
}

View File

@@ -1,117 +0,0 @@
--[[
Bootloader for Operation System
Created by minjaesong on 2016-09-21
]]
-- check directories
dirlist = {
"/boot",
"/bin", -- crucial binaries (e.g. cat, ls, sh(ell), cp, rm, mkdir), it's loosely an UNIX system
"/usr",
"/usr/bin", -- more utilities and binaries (e.g. less/more, nano)
"/home", -- home directory for user
"/home/bin", -- user-installed apps
"/media" -- auto mounts (e.g. "/media/fd1", "/media/hdb", "/media/sda")
}
-- just make them if they don't exist
for _, dir in ipairs(dirlist) do
fs.mkdir(dir)
end
if not _G.os then _G.os = {} end
os.version = "0.0"
os.EXIT_SUCCESS = 0
os.workingDir = {"home"}
os.path = "home/bin/;/usr/bin/;/bin/" -- infamous $path
os.fullWorkPath = function()
local ret = table.concat(os.workingDir, "/") -- there's nothing wrong with this.
if computer.verbose then
machine.println("workingDir size: "..#os.workingDir)
machine.println("fullWorkPath: "..ret)
end
return ret
end
os.setWorkingDir = function(s)
if s:byte(#s) == 47 then
s = string.sub(s, 1, #s - 1)
end
if s:byte(1) == 47 then
s = string.sub(s, 2, #s)
end
if computer.verbose then
machine.println("renew working dir; '"..s.."'")
end
local oldWorkingDir = {table.unpack(os.workingDir)}
-- renew working directory, EVEN IF s STARTS WITH '/'
local t = {}
for word in string.gmatch(s, "[^/]+") do
table.insert(t, word)
end
os.workingDir = t
-- check if the directory exists
if not fs.isDir(s) then
os.errorNoSuchFileOrDir("cd: "..s)
os.workingDir = oldWorkingDir
return
end
end
os.pushWorkingDir = function(s)
if (s == "..") then
error("cannot push '..' to working directory.")
else
table.insert(os.workingDir, s)
if computer.verbose then
machine.println("pushing '"..s.."' to working directory.")
end
end
end
os.popWorkingDir = function()
if (#os.workingDir > 1) then
table.remove(os.workingDir)
end
end
-- @param "path/of/arbitrary"
-- @return /working/dir/path/of/arbitrary
-- input path's trailing '/' is PRESERVED.
os.expandPath = function(p)
-- not applicable if the path starts with /
if p:byte(1) == 47 or p:byte(1) == 92 then
return p
end
return os.fullWorkPath().."/"..p
end
os.defaultshell = "/bin/dsh.lua"
os.clock = function() return machine.milliTime() / 1000 end -- uptime of the computer, in seconds
function os.errorCmdNotFound(cmd)
print(cmd..": command not found")
end
function os.errorNoSuchFile(cmd)
print(cmd..": No such file")
end
function os.errorNoSuchFileOrDir(cmd)
print(cmd..": No such file or directory")
end
function os.errorIsDir(cmd)
print(cmd.." is a directory")
end
-- run default shell
fs.dofile(os.defaultshell)
-- quit properly
shell.status = shell.halt

View File

@@ -1,12 +0,0 @@
NAME
msh - the Moonshell
SYNOPSIS
msh [file]
COPYRIGHT
See copyright information for the game you are actually playing.
DESCRIPTION
Msh is a Lua prompt that reads lua script from the user, or execute
a file user had put as an argument.

View File

@@ -1,58 +0,0 @@
print("")
print("Starting Lunados...")
------------------
--- INITIALISE ---
------------------
require "common"
local prompt = "> "
_G.dos = {}
_G.dos.version = "0.1"
_G.dos.copyright = "Copyright (C) 2019 CuriousTorvald. Distributed under GNU GPL 3."
_G.dos.currentpath = {}
--- appends the directory into the current path
_G.dos.currentpath.push = function(name)
table.insert(dos.path, name)
end
--- removes the current directory from the current path and returns what has been removed
_G.dos.currentpath.pop = function()
return table.remove(dos.path)
end
_G.dos.envpath = "C:\\lunados\\bin;" -- must be a sting and not a table
--------------------------
--- LET THE SHOW BEGIN ---
--------------------------
print("Lunados Version "..dos.version)
print(dos.copyright)
--- PARSE AND RUN COMMANDS ---
local exit = false
while not exit do
io.write(table.concat(dos.path, '\\'))
io.write(prompt)
local cmd = io.read()
local commands = parsecmd(cmd)
TODO()
end

View File

@@ -1,47 +0,0 @@
--[[
From https://github.com/prapin/LuaBrainFuck/blob/master/brainfuck.lua
LuaBrainFuck License
--------------------
LuaBrainFuck is placed under the same license as Lua itself,
so licensed under terms of the MIT license reproduced below.
This means that the library is free software and can be used for both academic
and commercial purposes at absolutely no cost.
===============================================================================
Copyright (C) 2012 Patrick Rapin, CH-1543 Grandcour
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================================================
(end of COPYRIGHT)
Example usage: require "brainfuck" "+++>>> your BF code here <<<---"
]]
return function(s)
local subst = {["+"]="v=v+1 ", ["-"]="v=v-1 ", [">"]="i=i+1 ", ["<"]="i=i-1 ",
["."] = "w(v)", [","]="v=r()", ["["]="while v~=0 do ", ["]"]="end "}
local env = setmetatable({ i=0, t=setmetatable({},{__index=function() return 0 end}),
r=function() return io.read(1):byte() end, w=function(c) io.write(string.char(c)) end },
{__index=function(t,k) return t.t[t.i] end, __newindex=function(t,k,v) t.t[t.i]=v end })
load(s:gsub("[^%+%-<>%.,%[%]]+",""):gsub(".", subst), "brainfuck", "t", env)()
end

View File

@@ -1,159 +0,0 @@
--[[
-- ComputerCraft API compatibility layer
Usage: require("CCAPI")
Created by minjaesong on 2016-09-16.
--]]
--------------
-- PREAMBLE --
--------------
if term.isTeletype() then error("This is a teletype; cannot use CCAPI layer") end
table.insert(computer.loadedCLayer, "CCAPI")
local function intLog2(i)
if i == 0 then return 0 end
local log = 0
if bit32.band(i, 0xffff0000) ~= 0 then i = bit32.rshift(i, 16) log = 16 end
if i >= 256 then i = bit32.rshift(i, 8) log = log + 8 end
if i >= 16 then i = bit32.rshift(i, 8) log = log + 4 end
if i >= 4 then i = bit32.rshift(i, 8) log = log + 2 end
return log + bit32.rshift(i, 1)
end
-----------------------
-- BIT API Extension --
-----------------------
bit.blshift = bit32.lshift(n, bits)
bit.brshift = bit32.arshift(n, bits)
bit.blogic_rshift = bit32.rshift(n, bits)
----------------
-- COLORS API --
----------------
_G.colors = {}
colors.white = 0x1
colors.orange = 0x2
colors.magenta = 0x4
colors.lightBlue = 0x8
colors.yellow = 0x10
colors.lime = 0x20
colors.pink = 0x40
colors.gray = 0x80
colors.grey = 0x80
colors.lightGray = 0x100
colors.lightGrey = 0x100
colors.cyan = 0x200
colors.purple = 0x400
colors.blue = 0x800
colors.brown = 0x1000
colors.green = 0x2000
colors.red = 0x4000
colors.black = 0x8000
local function normaliseCCcol(cccol)
if cccol >= 0x1 and cccol <= 0xFFFF then
return intLog2(cccol)
else
error("invalid CC Colors: "..cccol)
end
end
_G.colours = _G.colors
--------------
-- TERM API --
--------------
-- paint_index -> Terminal colour index
local ccToGameCol = {--pink
1, 5, 7, 10, 4, 11, 15, 2, 3, 10, 8, 9, 14, 12, 6, 0
}
-- "a" -> 10, "3" -> 3
local function cHexToInt(c)
if type(c) == "number" then -- char
if c >= 48 and c <= 57 then
return c - 48
elseif c >= 65 and c <= 70 then
return c - 65 + 10
elseif c >= 97 and c <= 102 then
return c - 97 + 10
else
return 0
end
elseif type(c) == "string" then -- single-letter string
if c:byte(1) >= 48 and c:byte(1) <= 57 then
return c:byte(1) - 48
elseif c:byte(1) >= 65 and c:byte(1) <= 70 then
return c:byte(1) - 65 + 10
elseif c:byte(1) >= 97 and c:byte(1) <= 102 then
return c:byte(1) - 97 + 10
else
--error("unrepresentable: " .. c)
-- return black, as defined in http://www.computercraft.info/wiki/Term.blit
return 0
end
else
error("bad argument (string or number expected, got "..type(c)..")")
end
end
-- str, str, str
term.blit = function(text, foreCol, backCol)
assert(
type(text) == "string" and type(backCol) == "string" and type(foreCol) == "string",
"bad argument: (string, string, string expected, got "..type(text)..", "..type(foreCol)..", "..type(backCol)..")"
)
if #text ~= #foreCol or #text ~= #backCol or #foreCol ~= #backCol then
error("arguments must be the same length")
end
for i = 1, #text do
term.setForeCol(ccToGameCol[1 + cHexToInt(foreCol:byte(i))])
term.setBackCol(ccToGameCol[1 + cHexToInt(backCol:byte(i))])
term.emit(text:byte(i))
term.moveCursor(term.getX() + 1, term.getY())
end
end
term.getCursorPos = term.getCursor
term.setCursorPos = term.moveCursor
term.setCursorBlink = term.blink
term.isColor = term.isCol
term.getSize = term.size
term.setTextColor = function(cccol) term.setForeCol(ccToGameCol[normaliseCCcol(cccol)]) end
term.getTextColor = term.getForeCol
term.setBackgroundColor = function(cccol) term.setBackCol(ccToGameCol[normaliseCCcol(cccol)]) end
term.getBackgroundColor = term.getBackCol
--------------------
-- FILESYSTEM API --
--------------------
fs.makeDir = fs.mkdir
fs.move = fs.mv
fs.copy = fs.cp
fs.delete = fs.rm
fs.combine = fs.concat
fs.getDir = fs.parent
fs.run = fs.dofile
------------------
-- DOWN AND OUT --
------------------
if computer.verbose then print("ComputerCraft compatibility layer successfully loaded.") end

View File

@@ -1,434 +0,0 @@
--[[
Created by minjaesong on 2016-09-15.
--]]
-------------
-- ALIASES --
-------------
--_G.io = {} -- we make our own sandbox'd system
--[[fs.dofile = function(p, ...)
local f = fs.open(p, "r")
local s = f.readAll()
_G.runscript(s, "="..p, ...)
end]] -- implementation moved to BOOT.lua
_G.loadstring = _G.load
--_G.dofile = function(f) fs.dofile(f) end
fs.fetchText = function(p)
local file = fs.open(p, "r")
local text = file.readAll()
file.close()
return text
end
-----------------------------------------
-- INPUTSTREAM AND SCANNER (java-like) --
-----------------------------------------
--[[
In whatever code that actually runs everything (computer),
there must be:
override fun keyPressed(key: Int, c: Char) {
super.keyPressed(key, c)
vt.keyPressed(key, c)
if (key == Key.RETURN) {
val input = vt.closeInputString()
}
}
...it basically says to close the input if RETURN is hit,
and THIS exact part will close the input for this function.
]]
_G.__scanforline__ = function(echo) -- pass '1' to not echo; pass nothing to echo
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 = machine.__readFromStdin()
until s
-- input is closed when RETURN is hit. See above comments.
return s
end
-- use Keys API to identify the keycode
--[[_G.__scanforkey__ = function(echo) -- pass '1' to not echo; pass nothing to echo
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 = machine.getLastKeyPress()
until key
-- input is closed when any key is hit. See above comments.
return key
end]] -- DELETED: use _G.input.isKeyDown(keycode)
--- ---
-- IO IMPLEMENTATION --
--- ---
io.__openfile__ = "stdin"
io.stdin = "stdin"
io.stdout = "stdout"
io.stderr = "stderr"
io.open = fs.open
io.input = function(luafile)
io.__openfile__ = luafile
end
io.read = function(option)
if io.__openfile__ == "stdin" then
local input = {}
-- RETURN not hit
while true do
local inkey = machine.__readFromStdin()
if inkey == 13 or inkey == 10 then
break
elseif inkey == 8 or inkey == 127 then
io.write(string.char(inkey))
table.remove(input)
elseif inkey > 0 then
io.write(string.char(inkey))
table.insert(input, string.char(inkey))
end
end
-- RETURN finally hit
io.write("\n")
return table.concat(input)
end
function _readAll()
return io.open(io.__openfile__).readAll()
end
function _readLine()
return io.open(io.__openfile__).readLine()
end
options = {}
options["*n"] = function() error("Read number is not supported, yet!") end--_readNumber
options["*a"] = _readAll
options["*l"] = _readLine
end
-----------------
-- PRINTSTREAM --
-----------------
-- only useful when IO is "opening" stdin
--[[io.write = function(...)
local args = {...}
for _, v in ipairs(args) do
local s
if v == nil then
s = "nil"
else
s = tostring(v)
end
term.write(s)
end
end]]
-- for some reason, inputstream above kills 'print' function.
-- So we rewrite it.
--[[_G.print = function(...) -- dependent on above io.write reimpl
local args = {...}
io.write(args[1])
if (#args > 1) then
for i = 2, #args do
io.write("\t")
io.write(args[i])
end
end
io.write("\n")
end]]
---------------
-- SHELL API --
---------------
_G.shell = {}
shell.status = shell.ok
-- run a script with path (string) and argstable (table)
shell.run = function(path, argstable)
-- check for interpreter key "#!"
local f = fs.open(path, "r")
local s = f.readAll()
f.close()
if s:sub(1,2) == "#!" then
local interpreter = s:sub(3)
if not argstable then
xpcall(function() fs.dofile(interpreter..".lua", path) end, function(err) print(DLE..err) end)
else
xpcall(function() fs.dofile(interpreter..".lua", path, table.unpack(argstable)) end, function(err) print(DLE..err) end)
end
else
if not argstable then
xpcall(function() fs.dofile(path) end, function(err) print(DLE..err) end)
else
xpcall(function() fs.dofile(path, table.unpack(argstable)) end, function(err) print(DLE..err) end)
end
end
end
shell.ok = 0
shell.halt = 127
--------------
-- HEXUTILS --
--------------
_G.hexutils = {}
_G.hexutils.toHexString = function(byteString)
assert(type(byteString) == "string", error("Expected string."))
-- speedup
local function iToHex(i)
if i == 0 then return "0"
elseif i == 1 then return "1"
elseif i == 2 then return "2"
elseif i == 3 then return "3"
elseif i == 4 then return "4"
elseif i == 5 then return "5"
elseif i == 6 then return "6"
elseif i == 7 then return "7"
elseif i == 8 then return "8"
elseif i == 9 then return "9"
elseif i == 10 then return "a"
elseif i == 11 then return "b"
elseif i == 12 then return "c"
elseif i == 13 then return "d"
elseif i == 14 then return "e"
elseif i == 15 then return "f"
else error("unrepresentable: " .. i)
end
end
local ret = ""
for i = 1, #byteString do
local c = byteString:byte(i)
local msb = iToHex(bit32.rshift(c, 4) % 16)
local lsb = iToHex(c % 16)
ret = ret .. (msb .. lsb)
end
return ret
end
--------------
-- KEYS API --
--------------
-- ComputerCraft compliant
local keycodeNumToName = {
["30"] = "a",
["48"] = "b",
["46"] = "c",
["32"] = "d",
["18"] = "e",
["33"] = "f",
["34"] = "g",
["35"] = "h",
["23"] = "i",
["36"] = "j",
["37"] = "k",
["38"] = "l",
["50"] = "m",
["49"] = "n",
["24"] = "o",
["25"] = "p",
["16"] = "q",
["19"] = "r",
["31"] = "s",
["20"] = "t",
["22"] = "u",
["47"] = "v",
["17"] = "w",
["45"] = "x",
["21"] = "y",
["44"] = "z",
["2"] = "one",
["3"] = "two",
["4"] = "three",
["5"] = "four",
["6"] = "five",
["7"] = "six",
["8"] = "seven",
["9"] = "eight",
["10"] = "nine",
["11"] = "zero",
["12"] = "minus",
["13"] = "equals",
["14"] = "backspace",
["15"] = "tab",
["26"] = "leftBracket",
["27"] = "rightBracket",
["28"] = "enter",
["29"] = "leftCtrl",
["39"] = "semiColon",
["40"] = "apostrophe",
["41"] = "grave",
["42"] = "leftShift",
["43"] = "backslash",
["51"] = "comma",
["52"] = "period",
["53"] = "slash",
["54"] = "rightShift",
["55"] = "multiply",
["56"] = "leftAlt",
["57"] = "space",
["58"] = "capsLock",
["59"] = "f1",
["60"] = "f2",
["61"] = "f3",
["62"] = "f4",
["63"] = "f5",
["64"] = "f6",
["65"] = "f7",
["66"] = "f8",
["67"] = "f9",
["68"] = "f10",
["69"] = "numLock",
["70"] = "scollLock",
["87"] = "f11",
["88"] = "f12",
["89"] = "f13",
["90"] = "f14",
["91"] = "f15",
["144"] = "cimcumflex",
["145"] = "at",
["146"] = "colon",
["147"] = "underscore",
["157"] = "rightCtrl",
["184"] = "rightAlt",
["197"] = "pause",
["199"] = "home",
["200"] = "up",
["201"] = "pageUp",
["203"] = "left",
["205"] = "right",
["207"] = "end",
["208"] = "down",
["209"] = "pageDown",
["210"] = "insert",
["211"] = "delete",
["219"] = "leftCommand"
}
_G.keys = {
["a"] = 30,
["b"] = 48,
["c"] = 46,
["d"] = 32,
["e"] = 18,
["f"] = 33,
["g"] = 34,
["h"] = 35,
["i"] = 23,
["j"] = 36,
["k"] = 37,
["l"] = 38,
["m"] = 50,
["n"] = 49,
["o"] = 24,
["p"] = 25,
["q"] = 16,
["r"] = 19,
["s"] = 31,
["t"] = 20,
["u"] = 22,
["v"] = 47,
["w"] = 17,
["x"] = 45,
["y"] = 21,
["z"] = 44,
["one"] = 2,
["two"] = 3,
["three"] = 4,
["four"] = 5,
["five"] = 6,
["six"] = 7,
["seven"] = 8,
["eight"] = 9,
["nine"] = 10,
["zero"] = 11,
["minus"] = 12,
["equals"] = 13,
["backspace"] = 14,
["tab"] = 15,
["leftBracket"] = 26,
["rightBracket"] = 27,
["enter"] = 28,
["leftCtrl"] = 29,
["semiColon"] = 39,
["apostrophe"] = 40,
["grave"] = 41,
["leftShift"] = 42,
["backslash"] = 43,
["comma"] = 51,
["period"] = 52,
["slash"] = 53,
["rightShift"] = 54,
["multiply"] = 55,
["leftAlt"] = 56,
["space"] = 57,
["capsLock"] = 58,
["f1"] = 59,
["f2"] = 60,
["f3"] = 61,
["f4"] = 62,
["f5"] = 63,
["f6"] = 64,
["f7"] = 65,
["f8"] = 66,
["f9"] = 67,
["f10"] = 68,
["numLock"] = 69,
["scollLock"] = 70,
["f11"] = 87,
["f12"] = 88,
["f13"] = 89,
["f14"] = 90,
["f15"] = 91,
["cimcumflex"] = 144,
["at"] = 145,
["colon"] = 146,
["underscore"] = 147,
["rightCtrl"] = 157,
["rightAlt"] = 184,
["pause"] = 197,
["home"] = 199,
["up"] = 200,
["pageUp"] = 201,
["left"] = 203,
["right"] = 205,
["end"] = 207,
["down"] = 208,
["pageDown"] = 209,
["insert"] = 210,
["delete"] = 211,
["leftCommand"] = 219
}
_G.keys.getName = function(code) return keycodeNumToName[tostring(code)] end

View File

@@ -1,497 +0,0 @@
--[[
TBASIC: Simple BASIC language based on the Commodore BASIC Version 2.
(C64 rulz? Nope.)
How to use in your program:
1. load the script by:
if you're using ComputerCraft, use:
os.loadAPI "TBASEXEC.lua"
else, use:
require "TBASEXEC"
2. run:
_TBASIC.EXEC(string of whole command)
]]
if os and os.loadAPI then -- ComputerCraft
os.loadAPI "TBASINCL.lua"
else
require "TBASINCL"
end
table.concat = function(t, delimeter)
if #t == 0 then return "" end
local outstr = t[1]
for i = 2, #t do
outstr = outstr..delimeter..tostring(t[i])
end
return outstr
end
-- Copy from TBASINCL; looks like OpenComputers has a bug...
function string_hash(str)
local hash = 2166136261
for i = 1, #str do
hash = hash * 16777619
hash = bit.bxor(hash, str:byte(i))
end
return hash
end
-- INTERPRETER STATUS ---------------------------------------------------------
local programlist = {}
-- LEXER ----------------------------------------------------------------------
local function appendcommand(lineno, statement)
if lineno > _TBASIC._INTPRTR.MAXLINES then
_TBASIC._ERROR.LINETOOBIG()
elseif lineno < 0 then
_TBASIC._ERROR.NOLINENUM()
else
programlist[lineno] = statement
end
end
do -- Avoid heap allocs for performance
local tokens = {" ", "\t", ",", "(", ")"} -- initial obvious tokens
local longest_token_len = 0
-- build 'tokens' table from list of operators from the language
for _, v in ipairs(_TBASIC._OPERATR) do
if not v:match("[A-Za-z]") then -- we want non-alphabetic operators as a token
table.insert(tokens, v)
-- get longest_token_len, will be used for 'lookahead'
local tokenlen = #v
if longest_token_len < #v then
longest_token_len = #v
end
end
end
-- sort them out using ther hash for binary search
table.sort(tokens, function(a, b) return string_hash(a) < string_hash(b) end)
function parsewords(line)
if line == nil then return end
-----------------------
-- check line sanity --
-----------------------
-- filter for IF statement
if line:sub(1, 2):upper() == "IF" then
-- no matching THEN
if not line:match("[Tt][Hh][Ee][Nn]") then
_TBASIC._ERROR.NOMATCHING("IF", "THEN")
-- assignment on IF clause
elseif line:match("[Ii][Ff][^\n]+[Tt][Hh][Ee][Nn]"):match("[^=+%-*/%%<>!]=[^=<>]") or
line:match("[Ii][Ff][^\n]+[Tt][Hh][Ee][Nn]"):match(":=") then
_TBASIC._ERROR.ASGONIF()
end
end
--------------------------------------------------
-- automatically infer and insert some commands --
--------------------------------------------------
-- (This is starting to get dirty...)
-- unary minus
for matchobj in line:gmatch("%-[0-9]+") do
local newline = line:gsub(matchobj, "MINUS "..matchobj:sub(2, #matchobj))
line = newline
end
-- conditional for IF
-- if IF statement has no appended paren
if line:sub(1, 2):upper() == "IF" and not line:match("[Ii][Ff][ ]*%(") then
local newline = line:gsub("[Ii][Ff]", "IF ( ", 1):gsub("[Tt][Hh][Ee][Nn]", " ) THEN", 1)
line = newline
end
-- special treatment for FOR
if line:sub(1, 3):upper() == "FOR" then
if line:match("[0-9]?%.[0-9]") then -- real number used (e.g. "3.14", ".5")
_TBASIC._ERROR.ILLEGALARG()
else
local varnameintm = line:match(" [^\n]+[ =]")
if varnameintm then
local varname = varnameintm:match("[^= ]+")
if varname then
local newline = line:gsub(" "..varname.."[ =]", " $"..varname.." "..varname.." = ")
line = newline:gsub("= =", "=")
else
_TBASIC._ERROR.SYNTAX()
end
end
-- basically, "FOR x x = 1 TO 10", which converts to "x x 1 10 TO = FOR",
-- which is executed (in RPN) in steps of:
-- "x x 1 10 TO = FOR"
-- "x x (arr) = FOR"
-- "x FOR" -- see this part? we need extra 'x' to feed for the FOR statement to function
end
end
printdbg("parsing line", line)
lextable = {}
isquote = false
quotemode = false
wordbuffer = ""
local function flush()
if (#wordbuffer > 0) then
table.insert(lextable, wordbuffer)
wordbuffer = ""
end
end
local function append(char)
wordbuffer = wordbuffer..char
end
local function append_no_whitespace(char)
if char ~= " " and char ~= "\t" then
wordbuffer = wordbuffer..char
end
end
-- return: lookless_count on success, nil on failure
local function isdelimeter(string)
local cmpval = function(table_elem) return string_hash(table_elem) end
local lookless_count = #string
local ret = nil
repeat
ret = table.binsearch(tokens, string:sub(1, lookless_count), cmpval)
lookless_count = lookless_count - 1
until ret or lookless_count < 1
return ret and lookless_count + 1 or false
end
local i = 1 -- Lua Protip: variable in 'for' is immutable, and is different from general variable table, even if they have same name
while i <= #line do
local c = string.char(line:byte(i))
local lookahead = line:sub(i, i+longest_token_len)
if isquote then
if c == [["]] then
flush()
isquote = false
else
append(c)
end
else
if c == [["]] then
isquote = true
append_no_whitespace("~")
else
local delimsize = isdelimeter(lookahead) -- returns nil if no matching delimeter found
if delimsize then
flush() -- flush buffer
append_no_whitespace(lookahead:sub(1, delimsize))
flush() -- flush this delimeter
i = i + delimsize - 1
else
append_no_whitespace(c)
end
end
end
i = i + 1
end
flush() -- don't forget this!
return lextable
end
end
local function readprogram(program)
for line in program:gmatch("[^\n]+") do
lineno = line:match("[0-9]+ ", 1)
if not lineno then
_TBASIC._ERROR.NOLINENUM()
end
statement = line:sub(#lineno + 1)
appendcommand(tonumber(lineno), statement)
end
end
do -- Avoid heap allocs for performance
local function stackpush(t, v)
t[#t + 1] = v
end
local function stackpop(t)
local v = t[#t]
t[#t] = nil
return v
end
local function stackpeek(t)
local v = t[#t]
return v
end
local function unmark(word)
if type(word) == "table" then return word end
return word:sub(2, #word)
end
local function isoperator(word)
if word == nil then return false end
return word:byte(1) == 35
end
local isvariable = _TBASIC.isvariable
local isnumber = _TBASIC.isnumber
local isstring = _TBASIC.isstring
local function isuserfunc(word)
if type(word) == "table" then return false end
if word == nil then return false end
return word:byte(1) == 64
end
local function isbuiltin(word)
if type(word) == "table" then return false end
if word == nil then return false end
return word:byte(1) == 38
end
local function iskeyword(word)
if word == nil then return false end
return isoperator(word) or isuserfunc(word) or isbuiltin(word)
end
local function isassign(word)
if word == nil then return false end
return word ~= "==" and word ~= ">=" and word ~= "<=" and word:byte(#word) == 61
end
-- returns truthy value "terminate_loop" upon termination of loop; nil otherwise.
local function execword(word, args)
if not _TBASIC.__appexit then
printdbg("--> execword", word)
printdbg("--> execword_args", table.unpack(args))
if word == "IF" then
printdbg("--> branch statement 'IF'")
if not _TBASIC.__readvar(args[1]) then -- if condition 'false'
printdbg("--> if condition 'false'", table.unpack(args))
return "terminate_loop" -- evaluated as 'true' to Lua
else
printdbg("--> if condition 'true'", table.unpack(args))
end
end
printdbg("--> execword_outarg", table.unpack(args))
result = _TBASIC.LUAFN[word][1](table.unpack(args))
printdbg("--> result", result)
stackpush(execstack, result)
end
end
function printdbg(...)
local debug = false
if debug then print("DBG", ...) end
end
function interpretline(line)
if not _TBASIC.__appexit then
--[[
impl
1. (normalise expr using parsewords)
2. use _TBASIC.RPNPARSR to convert to RPN
3. execute RPN op set like FORTH
* "&" - internal functions
* "@" - user-defined functions
* "$" - variables (builtin constants and user-defined) -- familiar, eh?
* "#" - operators
* "~" - strings
* none prepended - data (number or string)
]]
lextable = parsewords(line)
local vararg = -13 -- magic
if lextable and lextable[1] ~= nil then
if lextable[1]:upper() == "REM" then return nil end
printdbg("lextable", table.concat(lextable, "|"))
-- execute expression
exprlist = _TBASIC.TORPN(lextable) -- 2 2 #+ &PRINT for "PRINT 2+2"
printdbg("trying to exec", table.concat(exprlist, " "), "\n--------")
execstack = {}
for _, word in ipairs(exprlist) do
printdbg("stack before", table.concat(execstack, " "))
printdbg("word", word)
if iskeyword(word) then
printdbg("is keyword")
funcname = unmark(word)
args = {}
argsize = _TBASIC._GETARGS(funcname)
printdbg("argsize", argsize)
if not argsize then
_TBASIC._ERROR.DEV_UNIMPL(funcname)
else
if argsize ~= vararg then
-- consume 'argsize' elements from the stack
for argcnt = argsize, 1, -1 do
if #execstack == 0 then
_TBASIC._ERROR.ARGMISSING(funcname)
end
args[argcnt] = stackpop(execstack)
end
else
-- consume entire stack
local reversedargs = {}
while #execstack > 0 and
(isvariable(stackpeek(execstack)) or isnumber(stackpeek(execstack)) or
isstring(stackpeek(execstack)))
do
stackpush(reversedargs, stackpop(execstack))
end
-- reverse 'args'
while #reversedargs > 0 do
stackpush(args, stackpop(reversedargs))
end
end
local terminate_loop = execword(funcname, args)
if terminate_loop then
printdbg("--> termination of loop")
printdbg("--------")
break
end
end
elseif isvariable(word) then
printdbg("is variable")
stackpush(execstack, word) -- push raw variable ($ sign retained)
else
printdbg("is data")
stackpush(execstack, word) -- push number or string
end
printdbg("stack after", table.concat(execstack, " "))
printdbg("--------")
end
-- if execstack is not empty, something is wrong
if #execstack > 0 then
_TBASIC._ERROR.SYNTAX() -- cannot reliably pinpoint which statement has error; use generic error
end
end
end
end
end
local function termination_condition()
return terminated or
_TBASIC.__appexit or
#_TBASIC._INTPRTR.CALLSTCK > _TBASIC._INTPRTR.STACKMAX
end
local function fetchnextcmd()
cmd = nil
repeat
_TBASIC._INTPRTR.PROGCNTR = _TBASIC._INTPRTR.PROGCNTR + 1
cmd = programlist[_TBASIC._INTPRTR.PROGCNTR]
if _TBASIC._INTPRTR.PROGCNTR > _TBASIC._INTPRTR.MAXLINES then
terminated = true
break
end
until cmd ~= nil
if cmd ~= nil then
if _TBASIC._INTPRTR.TRACE then
print("PC", _TBASIC._INTPRTR.PROGCNTR)
end
return cmd
end
end
local function interpretall()
terminated = false
repeat
interpretline(fetchnextcmd())
until termination_condition()
end
-- END OF LEXER ---------------------------------------------------------------
-- _TBASIC.SHOWLUAERROR = false -- commented; let the shell handle it
local testprogram = nil
_G._TBASIC.EXEC = function(cmdstring) -- you can access this interpreter with this global function
_TBASIC._INTPRTR.RESET()
programlist = {} -- wipe out previous commands from interpreter (do not delete)
readprogram(cmdstring)
interpretall()
end
if testprogram then
_TBASIC._INTPRTR.RESET()
programlist = {} -- wipe out previous commands from interpreter (do not delete)
readprogram(testprogram)
interpretall()
end
--[[
Terran BASIC (TBASIC)
Copyright (c) 2016 Torvald (minjaesong) and the contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the Software), to deal in the
Software without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]

View File

@@ -1,34 +0,0 @@
-- TBASIC extension
-- these are utilities. Do not touch these lines
local __assert = _TBASIC.__assert
local __assertlhand = _TBASIC.__assertlhand
local __assertrhand = _TBASIC.__assertrhand
local __checknumber = _TBASIC.__checknumber
local __checkstring = _TBASIC.__checkstring
local __readvar = _TBASIC.__readvar
local __resolvevararg = _TBASIC.__resolvevarar
local vararg = -13 -- magic
-- end of utilities
-- these are the sample code for defining your own words
--[[
-- actual function that does the job
local function _fnupgoer(n)
print("Up-goer "..__checknumber(n).." goes up!")
end
-- add the word UPGOER to word list
table.insert(_TBASIC._FNCTION, "UPGOER")
-- add the actual function '_fnupgoer' and its number of arguments (1) to
-- '_TBASIC.LUAFN'. 'UPGOER' part should match with the word you just
-- inserted to _TBASIC._FNCTION.
_TBASIC.LUAFN.UPGOER = {_fnupgoer, 1}
]]
-- little debugger's blessing
local function _fnenableluatrace() _TBASIC.SHOWLUAERROR = true end
table.insert(_TBASIC._FNCTION, "LUATRACEON")
_TBASIC.LUAFN.LUATRACEON = {_fnenableluatrace, 0}

View File

@@ -1,292 +0,0 @@
--[[
TBASIC shell
Synopsis: TBASIC (filename)
If no file is specified, interactive mode will be started
To debug EXEC and/or INCL, there's line ```local debug = false``` on each file; change it to ```true``` manually
and you are all set.
]]
if os and os.loadAPI then -- ComputerCraft
os.loadAPI "TBASINCL.lua"
os.loadAPI "TBASEXEC.lua"
else
require "TBASINCL"
require "TBASEXEC"
end
args = {...}
print(_G._TBASIC._HEADER)
_TBASIC.PROMPT()
_TBASIC.SHOWLUAERROR = false
local function concat_lines(lines, startindex, endindex)
local out = ""
for i = startindex or 1, endindex or _TBASIC._INTPRTR.MAXLINES do
if lines[i] ~= nil then
out = out.."\n"..tostring(i).." "..lines[i]
end
end
return out
end
if args[1] then
local prog = nil
if fs and fs.open then -- ComputerCraft
local inp = assert(fs.open(args[1], "r"))
prog = inp:readAll()
inp:close()
else
local inp = assert(io.open(args[1], "r"))
prog = inp:read("*all")
inp:close()
end
_TBASIC.EXEC(prog)
else
local terminate_app = false
local ptn_nums = "[0-9]+"
local renum_targets = {"GOTO[ ]+"..ptn_nums, "GOSUB[ ]+"..ptn_nums }
local lines = {}
local linenum_match = "[0-9]+ "
local get_linenum = function(line) return line:sub(1,6):match(linenum_match, 1) end -- line:sub(1,6) limits max linumber to be 99999
local split_num_and_statements = function(line)
local linenum = get_linenum(line)
local statements = line:sub(#linenum + 1)
return tonumber(linenum), statements
end
while not terminate_app do
local __read = false
local line = io.read()
-- tokenise line by " "
local args = {} -- shadows system args
for word in line:gmatch("[^ ]+") do
table.insert(args, word:upper())
end
-- TODO more elegant code than IF-ELSEIF-ELSE
-- massive if-else for running command, cos implementing proper command executor is too expensive here
if line:sub(1,6):match(linenum_match) then -- enter new command
local linenum, statements = split_num_and_statements(line)
lines[tonumber(linenum)] = statements
__read = true
elseif args[1] == "NEW" then
lines = {}
elseif args[1] == "RUN" then
_TBASIC.EXEC(concat_lines(lines))
elseif args[1] == "LIST" then -- LIST, LIST 42, LIST 10-80
if not args[2] then
print(concat_lines(lines))
else
if args[2]:match("-") then -- ranged
local range = {}
for n in args[2]:gmatch("[^-]+") do
table.insert(range, n)
end
local rangestart = tonumber(range[1])
local rangeend = tonumber(range[2])
if not rangestart or not rangeend then
_TBASIC._ERROR.ILLEGALARG()
else
print(concat_lines(lines, rangestart, rangeend))
end
else
local linenum = tonumber(args[2])
if not linenum then
_TBASIC._ERROR.ILLEGALARG()
else
print(concat_lines(lines, linenum, linenum))
end
end
end
_TBASIC.PROMPT()
__read = true
elseif args[1] == "DELETE" then -- DELETE 30, DELETE 454-650
if not args[2] then
_TBASIC._ERROR.ILLEGALARG()
else
if args[2]:match("-") then -- ranged
local range = {}
for n in args[2]:gmatch("[^-]+") do
table.insert(range, n)
end
local rangestart = tonumber(range[1])
local rangeend = tonumber(range[2])
if not rangestart or not rangeend then
_TBASIC._ERROR.ILLEGALARG()
else
for i = rangestart, rangeend do
lines[i] = nil
end
end
else
local linenum = tonumber(args[2])
if not linenum then
_TBASIC._ERROR.ILLEGALARG()
else
lines[linenum] = nil
end
end
end
elseif args[1] == "EXIT" then
terminate_app = true
break
elseif args[1] == "SAVE" then
local status, err = pcall(function()
if fs and fs.open then -- computercraft
local file = fs.open(args[2], "w")
file.write(concat_lines(lines))
file.close()
else
local file = assert(io.open(args[2], "w"))
file:write(concat_lines(lines))
file:close()
end
end
)
if err then
if _TBASIC.SHOWLUAERROR then
print(err)
end
_TBASIC._ERROR.IOERR()
else
print("FILE SAVED")
end
elseif args[1] == "LOAD" then
local status, err = pcall(function()
lines = {}
if fs and fs.open then -- computercraft
local file = fs.open(args[2], "r")
local data = file.readAll("*all")
for dataline in data:gmatch("[^\n]+") do
if #dataline > 0 then
local linenum, statements = split_num_and_statements(dataline)
lines[linenum] = statements
end
end
file.close()
else
local file = assert(io.open(args[2], "r"))
local data = file:read("*all")
for dataline in data:gmatch("[^\n]+") do
if #dataline > 0 then
local linenum, statements = split_num_and_statements(dataline)
lines[linenum] = statements
end
end
file:close()
end
end
)
if err then
if _TBASIC.SHOWLUAERROR then
error(err)
end
_TBASIC._ERROR.IOERR()
else
print("FILE LOADED")
end
elseif args[1] == "RENUM" then
local statement_table = {}
local renumbering_table = {}
local new_linenum_counter = 10
-- first, get the list of commands, without line number indexing
for i = 1, _TBASIC._INTPRTR.MAXLINES do
if lines[i] ~= nil then
--table.insert(statement_table, lines[i])
statement_table[new_linenum_counter] = lines[i]
renumbering_table[i] = new_linenum_counter
-- test
--print("old line", i, "new line", new_linenum_counter)
new_linenum_counter = new_linenum_counter + 10
end
end
-- copy statement_table into lines table
lines = statement_table
-- re-number GOTO and GOSUB line numbers
local line_counter = 0 -- loop counter
for line_pc = 0, _TBASIC._INTPRTR.MAXLINES do
local line = lines[line_pc]
if line then
line_counter = line_counter + 1
-- replace
-- extract a <- "GOTO 320"
-- extract n_from from a (320), make n_to from it
-- make new string b <- "GOTO "..n_to
for _, match_string in ipairs(renum_targets) do
local match = line:match(match_string)
if match then
local matching_statement = match:gsub("[ ]+"..ptn_nums, "")
local target_line_old = tonumber(match:match(ptn_nums))
local target_line_new = renumbering_table[target_line_old]
local gsub_from = match
local gsub_to = matching_statement.." "..target_line_new
-- test
--print("matching_statement", matching_statement, "target_line_old", target_line_old, "target_line_new", target_line_new)
--print("gsub_from", gsub_from, "gsub_to", gsub_to)
-- substitute
lines[line_pc] = line:gsub(gsub_from, gsub_to)
end
end
end
end
elseif #line == 0 and line:byte(1) ~= 10 and line:byte(1) ~= 13 then
__read = true
else
_TBASIC.EXEC("1 "..line) -- execute command right away
end
-- reset
if not __read then
_TBASIC.PROMPT()
end
end
end
--[[
Terran BASIC (TBASIC)
Copyright (c) 2016 Torvald (minjaesong) and the contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the Software), to deal in the
Software without restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
]]

View File

@@ -1 +0,0 @@
// TODO Fill in from work_files/romapidoc/romapidoc.tex

View File

@@ -1,87 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.computer
import net.torvald.UnsafeHelper
import net.torvald.UnsafePtr
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.CommonResourcePool
/**
* Blit is a display adapter that operates in pixel-space, with resolution of 224x320 with bit depth of one.
*
* This Blit is inspired by the real-world Blit terminal from 1982 by Bell Labs.
*
* @link https://en.wikipedia.org/wiki/Blit_(computer_terminal)
*
* Created by minjaesong on 2019-07-22.
*/
class BLIT {
private val framebuffer = UnsafeHelper.allocate(W.toLong() * H)
var scrollOffsetX = 0
var scrollOffsetY = 0
var textCursorPos = 0
// each pixel is a byte. I know, 7 bits wasted, but whatever.
// any conversion to texture/GDX pixmap/etc must be done by other system.
// at least you can memcpy() them using UnsafeHelper
// TODO test memcpy() over pixmap and native memory
private fun toAddr(x: Int, y: Int) = (W * y + x) % framebuffer.size
fun drawPict(x: Int, y: Int, bytes: ByteArray, width: Int) {
for (yy in 0L until bytes.size / width) {
val writeAddr = toAddr(x, y)
UnsafeHelper.memcpyRaw(
bytes, UnsafeHelper.getArrayOffset(bytes) + yy * width,
null, framebuffer.ptr + writeAddr,
width.toLong()
)
}
}
fun drawLetter(px: Int, py: Int, char: Int) {
for (yy in 0L until 13L) {
UnsafeHelper.memcpy(
fontRom.ptr + (FONTROMW * (char / FONTROMCOLS) * FONTH * yy) + (char % FONTROMCOLS) * FONTW,
toAddr(px, py),
FONTW.toLong()
)
}
}
/**
* Notes:
*
* - The font ROM will not be redefine-able. Just draw your shape on the pixel space.
*/
companion object {
const val W = 240
const val H = 320
const val FONTW = 6
const val FONTH = 10
const val FONTROMW = 192
const val FONTROMH = 80
const val FONTROMCOLS = FONTROMW / FONTW
const val FONTROMROWS = FONTROMH / FONTH
const val TEXT_OFFSET_X = 0 // hand-calculated value
const val TEXT_OFFSET_Y = 4 // hand-calculated value
// so, y=0..3 and y=317..320 won't be touched by the text drawing
init {
// load common font rom
CommonResourcePool.addToLoadingList("dwarventech.computers.blit.fontrom") {
// TODO
}
}
private val fontRom = CommonResourcePool.getAs<UnsafePtr>("dwarventech.computers.blit.fontrom")
}
}

View File

@@ -1,12 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.computer
import java.io.RandomAccessFile
/**
* Created by minjaesong on 2019-07-13.
*/
class TEVDFile(path: String, mode: String) : RandomAccessFile(path, mode) {
}

View File

@@ -1,76 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.computer
import net.torvald.terrarum.gameactors.ai.luaTableOf
import net.torvald.terrarum.gameactors.ai.toLua
import org.luaj.vm2.Globals
import org.luaj.vm2.LuaError
import org.luaj.vm2.LuaValue
/**
* Created by minjaesong on 2019-07-10.
*/
object LoadTerrarumTermLib {
operator fun invoke(globals: Globals, terminal: MDA) {
globals.addZeroArgFun("term.getCursor") {
luaTableOf(
(terminal.cursor % terminal.width).toLua(),
(terminal.cursor / terminal.height).toLua()
)
}
globals.addTwoArgFun("term.setCursor") { p0, p1 ->
terminal.setCursor(p0.checkint(), p1.checkint())
LuaValue.NIL
}
globals.addZeroArgFun("term.getCursorBlink") {
terminal.blink.toLua()
}
globals.addOneArgFun("term.setCursorBlink") { p0 ->
terminal.blink = p0.checkboolean()
LuaValue.NIL
}
globals.addZeroArgFun("term.getTextColor") {
terminal.foreground.toLua()
}
globals.addZeroArgFun("term.getBackgroundColor") {
terminal.background.toLua()
}
globals.addOneArgFun("term.setTextColor") { p0 ->
terminal.foreground = p0.checkint()
LuaValue.NIL
}
globals.addOneArgFun("term.setBackgroundColor") { p0 ->
terminal.background = p0.checkint()
LuaValue.NIL
}
globals.addZeroArgFun("term.getSize") {
luaTableOf(
(terminal.width).toLua(),
(terminal.height).toLua()
)
}
globals.addZeroArgFun("term.clear") {
terminal.clear()
LuaValue.NIL
}
globals.addZeroArgFun("term.clearLine") {
terminal.clearCurrentLine()
LuaValue.NIL
}
globals.addOneArgFun("term.scroll") { p0 ->
if (p0.checkint() < 0)
throw LuaError("Scroll amount must be a positive number")
terminal.scroll(p0.toint())
LuaValue.NIL
}
globals.addOneArgFun("term.write") { p0 ->
terminal.print(p0.checkjstring())
LuaValue.NIL
}
globals.addThreeArgFun("term.setText") { p0, p1, p2 ->
terminal.setOneText(p0.checkint(), p1.checkint(), p2.checkint().toByte())
LuaValue.NIL
}
}
}

View File

@@ -1,697 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.computer
import net.torvald.terrarum.KVHashMap
import net.torvald.terrarum.Second
import net.torvald.terrarum.ceilInt
import org.luaj.vm2.Globals
import org.luaj.vm2.LoadState
import org.luaj.vm2.LuaError
import org.luaj.vm2.LuaValue
import org.luaj.vm2.compiler.LuaC
import org.luaj.vm2.lib.*
import org.luaj.vm2.lib.jse.*
import org.lwjgl.BufferUtils
import org.lwjgl.openal.AL10
import java.io.InputStream
import java.io.OutputStream
import java.io.PrintStream
import java.io.Reader
import java.nio.ByteBuffer
import java.util.*
/**
* 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.
* Created by minjaesong on 2016-09-10.
*/
class LuaComputerVM(val display: MDA) {
val DEBUG = true
lateinit private var luaJ_globals: Globals
var stdout: PrintStream? = null
private set
var stderr: PrintStream? = null
private set
var stdin: InputStream? = null
private set
val UUID = java.util.UUID.randomUUID().toString()
val computerValue = KVHashMap()
var isHalted = false
var stdinInput: Int = -1
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 {
initSandbox()
}
fun initSandbox() {
val luaJ_globals = Globals()
luaJ_globals.load(JseBaseLib())
luaJ_globals.load(PackageLib())
luaJ_globals.load(Bit32Lib())
luaJ_globals.load(TableLib())
luaJ_globals.load(JseStringLib())
luaJ_globals.load(CoroutineLib())
luaJ_globals.load(JseMathLib())
luaJ_globals.load(JseIoLib())
luaJ_globals.load(JseOsLib())
luaJ_globals.load(LuajavaLib())
LoadState.install(luaJ_globals)
LuaC.install(luaJ_globals)
stdout = TerminalPrintStream(this)
stderr = TerminalPrintStream(this)
stdin = TerminalInputStream(this)
luaJ_globals.STDOUT = stdout
luaJ_globals.STDERR = stderr
luaJ_globals.STDIN = stdin
luaJ_globals["bit"] = luaJ_globals["bit32"]
// load libraries
LoadTerrarumTermLib(luaJ_globals, display)
// secure the sandbox
//luaJ_globals["io"] = LuaValue.NIL
// dubug should be sandboxed in BOOT.lua (use OpenComputers code)
//val sethook = luaJ_globals["debug"]["sethook"]
//luaJ_globals["debug"] = LuaValue.NIL
}
fun update(delta: Float) {
if (currentExecutionThread.state == Thread.State.TERMINATED) {
threadRun = false
}
if (!isHalted) {
runBeepQueueManager(delta)
}
}
fun keyPressed(c: Int) {
stdinInput = c
// wake thread
runnableRunCommand.resume()
synchronized(stdin!!) {
(stdin as java.lang.Object).notifyAll()
}
}
fun openStdin() {
stdinInput = -1
// sleep the thread
runnableRunCommand.pause()
}
lateinit var currentExecutionThread: Thread
private set
lateinit var runnableRunCommand: ThreadRunCommand
private set
private var threadRun = false
fun runCommand(line: String, env: String) {
if (!threadRun) {
runnableRunCommand = ThreadRunCommand(luaJ_globals, line, env)
currentExecutionThread = Thread(null, runnableRunCommand, "LuaJ Separated")
currentExecutionThread.start()
threadRun = true
}
}
fun runCommand(reader: Reader, filename: String) {
if (!threadRun) {
runnableRunCommand = ThreadRunCommand(luaJ_globals, reader, filename)
currentExecutionThread = Thread(null, runnableRunCommand, "LuaJ Separated")
currentExecutionThread.start()
threadRun = true
}
}
/**
* @link https://stackoverflow.com/questions/16758346/how-pause-and-then-resume-a-thread#16758373
*/
class ThreadRunCommand : Runnable {
private val mode: Int
private val arg1: Any
private val arg2: String
private val lua: Globals
@Volatile private var running = true
@Volatile private var paused = false
private val pauseLock = java.lang.Object()
constructor(luaInstance: Globals, line: String, env: String) {
mode = 0
arg1 = line
arg2 = env
lua = luaInstance
}
constructor(luaInstance: Globals, reader: Reader, filename: String) {
mode = 1
arg1 = reader
arg2 = filename
lua = luaInstance
}
override fun run() {
synchronized(pauseLock) {
if (!running) { // may have changed while waiting to
// synchronize on pauseLock
return
}
if (paused) {
try {
pauseLock.wait() // will cause this Thread to block until
// another thread calls pauseLock.notifyAll()
// Note that calling wait() will
// relinquish the synchronized lock that this
// thread holds on pauseLock so another thread
// can acquire the lock to call notifyAll()
// (link with explanation below this code)
}
catch (ex: InterruptedException) {
return
}
if (!running) { // running might have changed since we paused
return
}
}
}
try {
val chunk: LuaValue
if (mode == 0)
chunk = lua.load(arg1 as String, arg2)
else if (mode == 1)
chunk = lua.load(arg1 as Reader, arg2)
else
throw IllegalArgumentException("Unsupported mode: $mode")
chunk.call()
}
catch (e: LuaError) {
e.printStackTrace(System.err)
//lua.STDERR.println("${SimpleTextTerminal.ASCII_DLE}${e.message}${SimpleTextTerminal.ASCII_DC4}")
}
}
fun stop() {
running = false
// you might also want to do this:
//interrupt()
}
fun pause() {
// you may want to throw an IllegalStateException if !running
paused = true
}
fun resume() {
synchronized(pauseLock) {
paused = false
pauseLock.notifyAll() // Unblocks thread
}
}
}
class ComputerEmitTone(val computer: LuaComputerVM) : TwoArgFunction() {
override fun call(millisec: LuaValue, freq: LuaValue): LuaValue {
computer.playTone(millisec.checkdouble().toFloat(), freq.checkdouble())
return LuaValue.NONE
}
}
///////////////////
// BEEPER DRIVER //
///////////////////
private val beepMaxLen = 10f
// let's regard it as a tracker...
private val beepQueue = ArrayList<Pair<Second, Double>>()
private var beepCursor = -1
private var beepQueueLineExecTimer: Second = 0f
private var beepQueueFired = false
private fun runBeepQueueManager(delta: Float) {
// start emitTone queue
if (beepQueue.size > 0 && beepCursor == -1) {
beepCursor = 0
}
// advance emitTone queue
if (beepCursor >= 0 && beepQueueLineExecTimer >= beepQueueGetLenOfPtn(beepCursor)) {
beepQueueLineExecTimer -= beepQueueGetLenOfPtn(beepCursor)
beepCursor += 1
beepQueueFired = false
}
// complete emitTone queue
if (beepCursor >= beepQueue.size) {
clearBeepQueue()
}
// actually play queue
if (beepCursor >= 0 && beepQueue.size > 0 && !beepQueueFired) {
playTone(beepQueue[beepCursor].first, beepQueue[beepCursor].second)
beepQueueFired = true
// delete sources that is finished. AL is limited to 256 sources. If you exceed it,
// we won't get any more sounds played.
AL10.alSourcei(oldBeepSource, AL10.AL_BUFFER, 0)
AL10.alDeleteSources(oldBeepSource)
AL10.alDeleteBuffers(oldBeepBuffer)
}
if (beepQueueFired) beepQueueLineExecTimer += delta
}
fun clearBeepQueue() {
beepQueue.clear()
beepCursor = -1
beepQueueLineExecTimer = 0f
//AL.destroy()
if (DEBUG) println("[TerrarumComputerOld] !! Beep queue clear")
}
fun enqueueBeep(duration: Double, freq: Double) {
beepQueue.add(Pair(Math.min(duration.toFloat(), beepMaxLen), freq))
}
fun beepQueueGetLenOfPtn(ptnIndex: Int) = beepQueue[ptnIndex].first
////////////////////
// TONE GENERATOR //
////////////////////
private val sampleRate = 44100
private var beepSource: Int = -1
private var beepBuffer: Int = -1
private var oldBeepSource: Int = -1
private var oldBeepBuffer: Int = -1
var audioData: ByteBuffer? = null
/**
* @param duration : milliseconds
* @param rampUp
* @param rampDown
*
* ,---. (true, true) ,---- (true, false) ----. (false, true) ----- (false, false)
*/
private fun makeAudioData(duration: Second, freq: Double,
rampUp: Boolean = true, rampDown: Boolean = true): ByteBuffer {
TODO("with duration as Seconds")
val audioDataSize = duration.times(sampleRate).ceilInt()
val audioData = BufferUtils.createByteBuffer(audioDataSize)
/*val realDuration = duration * sampleRate / 1000
val chopSize = freq / sampleRate
val amp = Math.max(4600.0 / freq, 1.0)
val nHarmonics = if (freq >= 22050.0) 1
else if (freq >= 11025.0) 2
else if (freq >= 5512.5) 3
else if (freq >= 2756.25) 4
else if (freq >= 1378.125) 5
else if (freq >= 689.0625) 6
else 7
val transitionThre = 974.47218
// TODO volume ramping?
if (freq == 0.0) {
for (_ in 0..audioDataSize - 1) {
audioData.put(0x00.toByte())
}
}
else if (freq < transitionThre) { // chopper generator (for low freq)
for (tsart in 0..audioDataSize - 1) {
var sine: Double = amp * Math.cos(Math.PI * 2 * () * chopSize)
if (sine > 0.79) sine = 0.79
else if (sine < -0.79) sine = -0.79
audioData.put(
(0.5 + 0.5 * sine).times(0xFF).roundToInt().toByte()
)
}
}
else { // harmonics generator (for high freq)
for (x in 0..realDuration - 1) {
var sine: Double = 0.0
for (k in 1..nHarmonics) { // mix only odd harmonics in order to make a squarewave
sine += Math.sin(Math.PI * 2 * (2*k - 1) * chopSize * x) / (2*k - 1)
}
audioData.put(
(0.5 + 0.5 * sine).times(0xFF).roundToInt().toByte()
)
}
}*/
audioData.rewind()
return audioData
}
private fun playTone(length: Second, freq: Double) {
/*audioData = makeAudioData(leninmilli, freq)
if (!AL.isCreated()) AL.create()
// Clear error stack.
AL10.alGetError()
oldBeepBuffer = beepBuffer
beepBuffer = AL10.alGenBuffers()
checkALError()
try {
AL10.alBufferData(beepBuffer, AL10.AL_FORMAT_MONO8, audioData, sampleRate)
checkALError()
oldBeepSource = beepSource
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) {
AL10.alDeleteSources(beepSource)
}*/
}
// 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)
}
}
}
class TerminalPrintStream(val host: LuaComputerVM) : PrintStream(TerminalOutputStream(host))
class TerminalOutputStream(val host: LuaComputerVM) : OutputStream() {
override fun write(b: Int) = host.display.write(b.and(0xFF).toByte())
}
class TerminalInputStream(val host: LuaComputerVM) : InputStream() {
override fun read(): Int {
//System.err.println(Thread.currentThread().name)
// would display "LuaJ Separated", which means this InputStream will not block main thread
/*host.openStdin()
synchronized(this) {
(this as java.lang.Object).wait()
}*/
return 65//host.stdinInput
}
}
class ALException(errorCode: Int) : Exception("ALerror: $errorCode") {
}
/**
* Install a function into the lua.
* @param identifier How you might call this lua function. E.g. "term.println"
*/
fun Globals.addOneArgFun(identifier: String, function: (p0: LuaValue) -> LuaValue) {
val theActualFun = object : OneArgFunction() {
override fun call(p0: LuaValue): LuaValue {
return function(p0)
}
}
val tableNames = identifier.split('.')
if (tableNames.isEmpty()) throw IllegalArgumentException("Identifier is empty")
//println(tableNames)
if (this[tableNames[0]].isnil()) {
this[tableNames[0]] = LuaValue.tableOf()
}
else if (!this[tableNames[0]].istable()) {
throw IllegalStateException("Redefinition: '${tableNames[0]}' (${this[tableNames[0]]})")
}
var currentTable = this[tableNames[0]]
// turn nils into tables
if (tableNames.size > 1) {
tableNames.slice(1..tableNames.lastIndex).forEachIndexed { index, it ->
if (currentTable[it].isnil()) {
currentTable[it] = LuaValue.tableOf()
}
else if (!currentTable[it].istable()) {
throw IllegalStateException("Redefinition: '${tableNames.slice(0..(index + 1)).joinToString(".")}' (${currentTable[it]})")
}
currentTable = currentTable[it]
}
// actually put the function onto the target
// for some reason, memoisation doesn't work here so we use recursion to reach the target table as generated above
tailrec fun putIntoTheTableRec(luaTable: LuaValue, recursionCount: Int) {
if (recursionCount == tableNames.lastIndex - 1) {
luaTable[tableNames[tableNames.lastIndex]] = theActualFun
}
else {
putIntoTheTableRec(luaTable[tableNames[recursionCount + 1]], recursionCount + 1)
}
}
putIntoTheTableRec(this[tableNames[0]], 0)
}
else {
this[tableNames[0]] = theActualFun
}
}
/**
* Install a function into the lua.
* @param identifier How you might call this lua function. E.g. "term.println"
*/
fun Globals.addZeroArgFun(identifier: String, function: () -> LuaValue) {
val theActualFun = object : ZeroArgFunction() {
override fun call(): LuaValue {
return function()
}
}
val tableNames = identifier.split('.')
if (tableNames.isEmpty()) throw IllegalArgumentException("Identifier is empty")
//println(tableNames)
if (this[tableNames[0]].isnil()) {
this[tableNames[0]] = LuaValue.tableOf()
}
else if (!this[tableNames[0]].istable()) {
throw IllegalStateException("Redefinition: '${tableNames[0]}' (${this[tableNames[0]]})")
}
var currentTable = this[tableNames[0]]
// turn nils into tables
if (tableNames.size > 1) {
tableNames.slice(1..tableNames.lastIndex).forEachIndexed { index, it ->
if (currentTable[it].isnil()) {
currentTable[it] = LuaValue.tableOf()
}
else if (!currentTable[it].istable()) {
throw IllegalStateException("Redefinition: '${tableNames.slice(0..(index + 1)).joinToString(".")}' (${currentTable[it]})")
}
currentTable = currentTable[it]
}
// actually put the function onto the target
// for some reason, memoisation doesn't work here so we use recursion to reach the target table as generated above
tailrec fun putIntoTheTableRec(luaTable: LuaValue, recursionCount: Int) {
if (recursionCount == tableNames.lastIndex - 1) {
luaTable[tableNames[tableNames.lastIndex]] = theActualFun
}
else {
putIntoTheTableRec(luaTable[tableNames[recursionCount + 1]], recursionCount + 1)
}
}
putIntoTheTableRec(this[tableNames[0]], 0)
}
else {
this[tableNames[0]] = theActualFun
}
}
/**
* Install a function into the lua.
* @param identifier How you might call this lua function. E.g. "term.println"
*/
fun Globals.addTwoArgFun(identifier: String, function: (p0: LuaValue, p1: LuaValue) -> LuaValue) {
val theActualFun = object : TwoArgFunction() {
override fun call(p0: LuaValue, p1: LuaValue): LuaValue {
return function(p0, p1)
}
}
val tableNames = identifier.split('.')
if (tableNames.isEmpty()) throw IllegalArgumentException("Identifier is empty")
//println(tableNames)
if (this[tableNames[0]].isnil()) {
this[tableNames[0]] = LuaValue.tableOf()
}
else if (!this[tableNames[0]].istable()) {
throw IllegalStateException("Redefinition: '${tableNames[0]}' (${this[tableNames[0]]})")
}
var currentTable = this[tableNames[0]]
// turn nils into tables
if (tableNames.size > 1) {
tableNames.slice(1..tableNames.lastIndex).forEachIndexed { index, it ->
if (currentTable[it].isnil()) {
currentTable[it] = LuaValue.tableOf()
}
else if (!currentTable[it].istable()) {
throw IllegalStateException("Redefinition: '${tableNames.slice(0..(index + 1)).joinToString(".")}' (${currentTable[it]})")
}
currentTable = currentTable[it]
}
// actually put the function onto the target
// for some reason, memoisation doesn't work here so we use recursion to reach the target table as generated above
tailrec fun putIntoTheTableRec(luaTable: LuaValue, recursionCount: Int) {
if (recursionCount == tableNames.lastIndex - 1) {
luaTable[tableNames[tableNames.lastIndex]] = theActualFun
}
else {
putIntoTheTableRec(luaTable[tableNames[recursionCount + 1]], recursionCount + 1)
}
}
putIntoTheTableRec(this[tableNames[0]], 0)
}
else {
this[tableNames[0]] = theActualFun
}
}
/**
* Install a function into the lua.
* @param identifier How you might call this lua function. E.g. "term.println"
*/
fun Globals.addThreeArgFun(identifier: String, function: (p0: LuaValue, p1: LuaValue, p2: LuaValue) -> LuaValue) {
val theActualFun = object : ThreeArgFunction() {
override fun call(p0: LuaValue, p1: LuaValue, p2: LuaValue): LuaValue {
return function(p0, p1, p2)
}
}
val tableNames = identifier.split('.')
if (tableNames.isEmpty()) throw IllegalArgumentException("Identifier is empty")
//println(tableNames)
if (this[tableNames[0]].isnil()) {
this[tableNames[0]] = LuaValue.tableOf()
}
else if (!this[tableNames[0]].istable()) {
throw IllegalStateException("Redefinition: '${tableNames[0]}' (${this[tableNames[0]]})")
}
var currentTable = this[tableNames[0]]
// turn nils into tables
if (tableNames.size > 1) {
tableNames.slice(1..tableNames.lastIndex).forEachIndexed { index, it ->
if (currentTable[it].isnil()) {
currentTable[it] = LuaValue.tableOf()
}
else if (!currentTable[it].istable()) {
throw IllegalStateException("Redefinition: '${tableNames.slice(0..(index + 1)).joinToString(".")}' (${currentTable[it]})")
}
currentTable = currentTable[it]
}
// actually put the function onto the target
// for some reason, memoisation doesn't work here so we use recursion to reach the target table as generated above
tailrec fun putIntoTheTableRec(luaTable: LuaValue, recursionCount: Int) {
if (recursionCount == tableNames.lastIndex - 1) {
luaTable[tableNames[tableNames.lastIndex]] = theActualFun
}
else {
putIntoTheTableRec(luaTable[tableNames[recursionCount + 1]], recursionCount + 1)
}
}
putIntoTheTableRec(this[tableNames[0]], 0)
}
else {
this[tableNames[0]] = theActualFun
}
}

View File

@@ -1,246 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.computer
import net.torvald.UnsafeHelper
import net.torvald.terrarum.AppLoader
import net.torvald.terrarum.gameworld.fmod
import java.io.OutputStream
import java.io.PrintStream
import java.nio.charset.Charset
/**
* Only one kind of display adapter should exist in the game: they add nothing to the game and the game
* shouldn't put much emphasis on computers anyway.
*
* The actual draw code must not exist in this class!
*
* Created by minjaesong on 2019-07-09.
*/
class MDA(val width: Int, val height: Int) {
companion object {
val charset: Charset = Charset.forName("cp437")
}
init {
if (width % 2 == 1) throw IllegalArgumentException("Display width must be an even number (width = $width)")
}
private val arrayElemOffset = 8L * if (AppLoader.is32BitJVM) 1 else 2 // 8 for 32-bit, 16 for 64-bit
private val glyphs = UnsafeHelper.allocate(width.toLong() * height + 1) // extra one byte is absolutely needed
private val attributes = UnsafeHelper.allocate(width.toLong() * height + 1)
var cursor = 0
private set
var background = 0
var foreground = 1
var blink = true
init {
glyphs.fillWith(0)
attributes.fillWith(1)
}
/*
Attibutes memory map:
for every byte:
(msb) 00bb 00ff (lsb)
where:
bb: background colour
ff: foreground colour
Colours:
0: black
1: light grey
2: dark grey
3: white
*/
fun toAttribute(back: Int, fore: Int) = (back.shl(4) or fore).toByte()
private fun wrapAround(x: Int, y: Int) = (x fmod width) to (y fmod height)
private fun toAddress(x: Int, y: Int) = (y * width + x).toLong()
inline private fun Pair<Int, Int>.toAddress() = toAddress(this.first, this.second)
fun rawGet(offset: Int) = glyphs[offset.toLong()] to attributes[offset.toLong()]
fun get(x: Int, y: Int): Pair<Byte, Byte> {
val a = wrapAround(x, y).toAddress()
return glyphs[a] to attributes[a]
}
fun set(x: Int, y: Int, glyph: Byte, attribute: Byte) {
val a = wrapAround(x, y).toAddress()
glyphs[a] = glyph
attributes[a] = attribute
}
private fun set(offset: Int, glyph: Byte, attribute: Byte) {
glyphs[offset.toLong()] = glyph
attributes[offset.toLong()] = attribute
}
fun setCursor(x: Int, y: Int) {
cursor = wrapAround(x, y).toAddress().toInt()
}
// SETTEXT methods should not deal with the scrolling, it must be handled by the PRINT methods.
/** Bulk write method. Any control characers will be represented as a glyph, rather than an actual control sequence.
* E.g. '\n' will print a symbol. */
fun setText(x: Int, y: Int, text: ByteArray, attribute: ByteArray) {
UnsafeHelper.memcpyRaw(text, arrayElemOffset, null, glyphs.ptr + wrapAround(x, y).toAddress(), text.size.toLong())
UnsafeHelper.memcpyRaw(attribute, arrayElemOffset, null, attributes.ptr + wrapAround(x, y).toAddress(), text.size.toLong())
}
private fun setText(offset: Int, text: ByteArray, attribute: ByteArray) {
UnsafeHelper.memcpyRaw(text, arrayElemOffset, null, glyphs.ptr + offset, text.size.toLong())
UnsafeHelper.memcpyRaw(attribute, arrayElemOffset, null, attributes.ptr + offset, text.size.toLong())
}
/** Bulk write method. Any control characers will be represented as a glyph, rather than an actual control sequence.
* E.g. '\n' will print a symbol. */
fun setText(x: Int, y: Int, text: ByteArray, attribute: Byte) {
setText(x, y, text, ByteArray(text.size) { attribute })
}
private fun setText(offset: Int, text: ByteArray, attribute: Byte = toAttribute(background, foreground)) {
setText(offset, text, ByteArray(text.size) { attribute })
}
/** Bulk write method. Any control characers will be represented as a glyph, rather than an actual control sequence.
* E.g. '\n' will print a symbol. */
inline fun setText(x: Int, y: Int, text: ByteArray) {
setText(x, y, text, toAttribute(background, foreground))
}
fun setOneText(x: Int, y: Int, text: Byte, attribute: Byte = toAttribute(background, foreground)) {
val o = wrapAround(x, y).toAddress()
glyphs[o] = text
attributes[o] = attribute
}
private fun setOneText(offset: Int, text: Byte, attribute: Byte = toAttribute(background, foreground)) {
glyphs[offset.toLong()] = text
attributes[offset.toLong()] = attribute
}
fun println(text: String) {
print(text)
write(0x0A)
}
inline fun print(text: String) {
print(text.toByteArray(charset))
}
fun println(text: ByteArray) {
print(text)
write(0x0A)
}
fun print(text: ByteArray) {
text.forEach { write(it) }
}
fun write(text: Byte) {
when (text) {
// LF
0x0A.toByte() -> newline()
// all others (e.g. CR)
in 0x00.toByte()..0x0D.toByte() -> { /* do nothing */ }
else -> {
setOneText(cursor, text)
cursor += 1
if (cursor > width * height) {
scroll(1)
}
}
}
}
fun clear() {
glyphs.fillWith(0)
attributes.fillWith(toAttribute(background, foreground))
cursor = 0
}
fun clearCurrentLine() {
clearLine(cursor / width)
}
fun clearLine(line: Int) {
val lineOffset = line * width
for (i in 0L until width) {
glyphs[lineOffset + i] = 0
}
}
fun clearLineAfterCursor() {
val lineOffset = (cursor / width) * width
for (i in (cursor % width).toLong() until width) {
glyphs[lineOffset + i] = 0
}
}
/**
* moves text and the current cursor position
*/
fun scroll(amount: Int) {
val offset = (width * amount).toLong()
if (amount < 0) throw IllegalArgumentException("amount = $amount")
UnsafeHelper.memcpy(glyphs, offset, glyphs, 0L, glyphs.size - offset)
UnsafeHelper.memcpy(attributes, offset, attributes, 0L, attributes.size - offset)
cursor -= offset.toInt()
if (cursor < 0) cursor = 0
clearLineAfterCursor()
}
/**
* Advance one line, scroll the screen if necessary
*/
fun newline() {
cursor += width
if (cursor >= width * height) {
scroll(1)
}
cursor = (cursor / width) * width // set cursorX to 0
clearLineAfterCursor()
}
fun dispose() {
glyphs.destroy()
attributes.destroy()
}
}
private class MDAOutputStream(val mda: MDA) : OutputStream() {
override fun write(b: Int) {
mda.write(b.toByte())
}
}
class MDAPrintStream(val mda: MDA) : PrintStream(MDAOutputStream(mda)) {
override fun print(s: String?) {
mda.print((s ?: "").toByteArray(MDA.charset))
}
override fun println(s: String?) {
print(s)
mda.newline()
}
}

View File

@@ -1,585 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.computer
import net.torvald.terrarum.KVHashMap
import net.torvald.terrarum.Second
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.ceilInt
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.VDUtil
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.VirtualDisk
import net.torvald.terrarum.modulecomputers.virtualcomputer.worldobject.ComputerPartsCodex
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 org.lwjgl.BufferUtils
import org.lwjgl.openal.AL10
import java.io.*
import java.nio.ByteBuffer
import java.util.*
import java.util.logging.Level
import kotlin.collections.HashMap
/**
* 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.
* Created by minjaesong on 2016-09-10.
*/
class TerrarumComputerOldOld(peripheralSlots: Int) {
val DEBUG_UNLIMITED_MEM = false
val DEBUG = true
val maxPeripherals: Int = if (DEBUG) 32 else peripheralSlots
lateinit var luaJ_globals: Globals
private set
var stdout: PrintStream? = null
private set
var stderr: PrintStream? = null
private set
var stdin: InputStream? = null
private set
val processorCycle: Int // number of Lua statement to process per tick (1/100 s)
get() = ComputerPartsCodex.getProcessorCycles(computerValue.getAsInt("processor") ?: 0)
val memSize: Int // in bytes; max: 8 GB
get() {
if (DEBUG_UNLIMITED_MEM) return 16.shl(20)// 16 MB
var size = 0
for (i in 0..3)
size += ComputerPartsCodex.getRamSize(computerValue.getAsInt("memSlot$i")!!)
return size
}
val UUID = java.util.UUID.randomUUID().toString()
val computerValue = KVHashMap()
var isHalted = false
lateinit var term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Teletype
private set
val peripheralTable = Array<net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral.Peripheral?>(peripheralSlots, { null }) // index == slot number
var stdinInput: Int = -1
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()
/** String:
* if it's UUID, formatted UUID as string, always 36 chars
* if not (test purpose only!), just String
*/
val diskRack = HashMap<String, VirtualDisk>()
fun attachDisk(slot: String, filename: String) {
computerValue[slot] = filename
// put disk in diskRack
if (filename.isNotEmpty() && filename.isNotBlank()) {
diskRack[slot] = VDUtil.readDiskArchive(
File(Terrarum.currentSaveDir.path + "/computers/$filename").absoluteFile,
Level.WARNING,
{ },
net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi.Filesystem.sysCharset
)
}
}
init {
computerValue["memslot0"] = 4864 // -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)
attachDisk("hda", "uuid_testhda")
attachDisk("hdb", "")
attachDisk("hdc", "")
attachDisk("hdd", "")
// as in "dev/fd1"; refers floppy disk drive
attachDisk("fd1", "")
attachDisk("fd2", "")
attachDisk("fd3", "")
attachDisk("fd4", "")
// SCSI connected optical drive
attachDisk("sda", "")
// boot device
computerValue["boot"] = "hda"
}
fun getPeripheral(tableName: String): net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral.Peripheral? {
peripheralTable.forEach {
if (it?.tableName == tableName)
return it
}
return null
}
fun getPeripheralSlot(tableName: String): Int? {
peripheralTable.forEachIndexed { index, peri ->
if (peri?.tableName == tableName)
return index
}
return null
}
/** @return installed slot */
fun attachPeripheral(peri: net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral.Peripheral): Int {
(0..maxPeripherals - 1).forEach {
try {
attachPeripheralTo(peri, it)
return it
}
catch (tryNext: RuntimeException) { }
}
throw RuntimeException("No vacant peripheral slot")
}
fun attachPeripheralTo(peri: net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral.Peripheral, slot: Int) {
if (peripheralTable[slot] == null) {
peripheralTable[slot] = peri
peri.loadLib(luaJ_globals)
println("[TerrarumComputerOld] loading peripheral $peri")
}
else {
throw RuntimeException("Peripheral slot is already taken by: ${peripheralTable[slot]?.tableName}")
}
}
fun detachPeripheral(peri: net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral.Peripheral) {
// search for the peripheral
var found = -1
for (i in 0..maxPeripherals - 1) {
if (peripheralTable[i] == peri) {
found = i
break
}
}
if (found >= 0) {
peripheralTable[found] = null
println("[TerrarumComputerOld] unloading peripheral $peri")
}
else {
throw IllegalArgumentException("Peripheral not exists: $peri")
}
}
fun attachTerminal(term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Teletype) {
this.term = term
initSandbox(term)
}
fun initSandbox(term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Teletype) {
luaJ_globals = JsePlatform.debugGlobals()
stdout = net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.TerminalPrintStream(this)
stderr = net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.TerminalPrintStream(this)
stdin = net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.TerminalInputStream(this)
luaJ_globals.STDOUT = stdout
luaJ_globals.STDERR = stderr
luaJ_globals.STDIN = stdin
luaJ_globals["bit"] = luaJ_globals["bit32"]
// load libraries
net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi.Term(luaJ_globals, term)
net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi.Security(luaJ_globals)
net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi.Filesystem(luaJ_globals, this)
net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi.HostAccessProvider(luaJ_globals, this)
net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi.Input(luaJ_globals, this)
net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi.PcSpeakerDriver(luaJ_globals, this)
net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi.WorldInformationProvider(luaJ_globals)
// secure the sandbox
//luaJ_globals["io"] = LuaValue.NIL
// dubug should be sandboxed in BOOT.lua (use OpenComputers code)
//val sethook = luaJ_globals["debug"]["sethook"]
//luaJ_globals["debug"] = LuaValue.NIL
// ROM BASIC
val inputStream = javaClass.getResourceAsStream("/net/torvald/terrarum/modulecomputers/virtualcomputer/virtualcomputer/assets/lua/BOOT.lua")
runCommand(InputStreamReader(inputStream), "=boot")
// computer-related global functions
luaJ_globals["totalMemory"] = LuaFunGetTotalMem(this)
luaJ_globals["computer"] = LuaTable()
// rest of the "computer" APIs should be implemented in BOOT.lua
// load every peripheral if we're in DEBUG
if (DEBUG) {
attachPeripheral(net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral.PeripheralInternet(this))
attachPeripheral(net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral.PeripheralPSG(this))
// ...
}
}
fun update(delta: Float) {
if (currentExecutionThread.state == Thread.State.TERMINATED) {
threadRun = false
}
if (!isHalted) {
runBeepQueueManager(delta)
}
}
fun keyPressed(key: Int, c: Char) {
stdinInput = c.toInt()
// wake thread
runnableRunCommand.resume()
synchronized(stdin!!) {
(stdin as java.lang.Object).notifyAll()
}
}
fun openStdin() {
stdinInput = -1
// sleep the thread
runnableRunCommand.pause()
}
lateinit var currentExecutionThread: Thread
private set
lateinit var runnableRunCommand: ThreadRunCommand
private set
private var threadRun = false
fun runCommand(line: String, env: String) {
if (!threadRun) {
runnableRunCommand = ThreadRunCommand(luaJ_globals, line, env)
currentExecutionThread = Thread(null, runnableRunCommand, "LuaJ Separated")
currentExecutionThread.start()
threadRun = true
}
}
fun runCommand(reader: Reader, filename: String) {
if (!threadRun) {
runnableRunCommand = ThreadRunCommand(luaJ_globals, reader, filename)
currentExecutionThread = Thread(null, runnableRunCommand, "LuaJ Separated")
currentExecutionThread.start()
threadRun = true
}
}
class ThreadRunCommand : Runnable {
private val mode: Int
private val arg1: Any
private val arg2: String
private val lua: Globals
@Volatile private var running = true
@Volatile private var paused = false
private val pauseLock = java.lang.Object()
constructor(luaInstance: Globals, line: String, env: String) {
mode = 0
arg1 = line
arg2 = env
lua = luaInstance
}
constructor(luaInstance: Globals, reader: Reader, filename: String) {
mode = 1
arg1 = reader
arg2 = filename
lua = luaInstance
}
override fun run() {
synchronized(pauseLock) {
if (!running) { // may have changed while waiting to
// synchronize on pauseLock
return
}
if (paused) {
try {
pauseLock.wait() // will cause this Thread to block until
// another thread calls pauseLock.notifyAll()
// Note that calling wait() will
// relinquish the synchronized lock that this
// thread holds on pauseLock so another thread
// can acquire the lock to call notifyAll()
// (link with explanation below this code)
}
catch (ex: InterruptedException) {
return
}
if (!running) { // running might have changed since we paused
return
}
}
}
try {
val chunk: LuaValue
if (mode == 0)
chunk = lua.load(arg1 as String, arg2)
else if (mode == 1)
chunk = lua.load(arg1 as Reader, arg2)
else
throw IllegalArgumentException("Unsupported mode: $mode")
chunk.call()
}
catch (e: LuaError) {
e.printStackTrace(System.err)
//lua.STDERR.println("${SimpleTextTerminal.ASCII_DLE}${e.message}${SimpleTextTerminal.ASCII_DC4}")
}
}
fun stop() {
running = false
// you might also want to do this:
//interrupt()
}
fun pause() {
// you may want to throw an IllegalStateException if !running
paused = true
}
fun resume() {
synchronized(pauseLock) {
paused = false
pauseLock.notifyAll() // Unblocks thread
}
}
}
class LuaFunGetTotalMem(val computer: TerrarumComputerOldOld) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(computer.memSize)
}
}
class ComputerEmitTone(val computer: TerrarumComputerOldOld) : TwoArgFunction() {
override fun call(millisec: LuaValue, freq: LuaValue): LuaValue {
computer.playTone(millisec.checkdouble().toFloat(), freq.checkdouble())
return LuaValue.NONE
}
}
///////////////////
// BEEPER DRIVER //
///////////////////
private val beepMaxLen = 10f
// let's regard it as a tracker...
private val beepQueue = ArrayList<Pair<Second, Double>>()
private var beepCursor = -1
private var beepQueueLineExecTimer: Second = 0f
private var beepQueueFired = false
private fun runBeepQueueManager(delta: Float) {
// start emitTone queue
if (beepQueue.size > 0 && beepCursor == -1) {
beepCursor = 0
}
// advance emitTone queue
if (beepCursor >= 0 && beepQueueLineExecTimer >= beepQueueGetLenOfPtn(beepCursor)) {
beepQueueLineExecTimer -= beepQueueGetLenOfPtn(beepCursor)
beepCursor += 1
beepQueueFired = false
}
// complete emitTone queue
if (beepCursor >= beepQueue.size) {
clearBeepQueue()
}
// actually play queue
if (beepCursor >= 0 && beepQueue.size > 0 && !beepQueueFired) {
playTone(beepQueue[beepCursor].first, beepQueue[beepCursor].second)
beepQueueFired = true
// delete sources that is finished. AL is limited to 256 sources. If you exceed it,
// we won't get any more sounds played.
AL10.alSourcei(oldBeepSource, AL10.AL_BUFFER, 0)
AL10.alDeleteSources(oldBeepSource)
AL10.alDeleteBuffers(oldBeepBuffer)
}
if (beepQueueFired) beepQueueLineExecTimer += delta
}
fun clearBeepQueue() {
beepQueue.clear()
beepCursor = -1
beepQueueLineExecTimer = 0f
//AL.destroy()
if (DEBUG) println("[TerrarumComputerOld] !! Beep queue clear")
}
fun enqueueBeep(duration: Double, freq: Double) {
beepQueue.add(Pair(Math.min(duration.toFloat(), beepMaxLen), freq))
}
fun beepQueueGetLenOfPtn(ptnIndex: Int) = beepQueue[ptnIndex].first
////////////////////
// TONE GENERATOR //
////////////////////
private val sampleRate = 44100
private var beepSource: Int = -1
private var beepBuffer: Int = -1
private var oldBeepSource: Int = -1
private var oldBeepBuffer: Int = -1
var audioData: ByteBuffer? = null
/**
* @param duration : milliseconds
* @param rampUp
* @param rampDown
*
* ,---. (true, true) ,---- (true, false) ----. (false, true) ----- (false, false)
*/
private fun makeAudioData(duration: Second, freq: Double,
rampUp: Boolean = true, rampDown: Boolean = true): ByteBuffer {
TODO("with duration as Seconds")
val audioDataSize = duration.times(sampleRate).ceilInt()
val audioData = BufferUtils.createByteBuffer(audioDataSize)
/*val realDuration = duration * sampleRate / 1000
val chopSize = freq / sampleRate
val amp = Math.max(4600.0 / freq, 1.0)
val nHarmonics = if (freq >= 22050.0) 1
else if (freq >= 11025.0) 2
else if (freq >= 5512.5) 3
else if (freq >= 2756.25) 4
else if (freq >= 1378.125) 5
else if (freq >= 689.0625) 6
else 7
val transitionThre = 974.47218
// TODO volume ramping?
if (freq == 0.0) {
for (_ in 0..audioDataSize - 1) {
audioData.put(0x00.toByte())
}
}
else if (freq < transitionThre) { // chopper generator (for low freq)
for (tsart in 0..audioDataSize - 1) {
var sine: Double = amp * Math.cos(Math.PI * 2 * () * chopSize)
if (sine > 0.79) sine = 0.79
else if (sine < -0.79) sine = -0.79
audioData.put(
(0.5 + 0.5 * sine).times(0xFF).roundToInt().toByte()
)
}
}
else { // harmonics generator (for high freq)
for (x in 0..realDuration - 1) {
var sine: Double = 0.0
for (k in 1..nHarmonics) { // mix only odd harmonics in order to make a squarewave
sine += Math.sin(Math.PI * 2 * (2*k - 1) * chopSize * x) / (2*k - 1)
}
audioData.put(
(0.5 + 0.5 * sine).times(0xFF).roundToInt().toByte()
)
}
}*/
audioData.rewind()
return audioData
}
private fun playTone(length: Second, freq: Double) {
/*audioData = makeAudioData(leninmilli, freq)
if (!AL.isCreated()) AL.create()
// Clear error stack.
AL10.alGetError()
oldBeepBuffer = beepBuffer
beepBuffer = AL10.alGenBuffers()
checkALError()
try {
AL10.alBufferData(beepBuffer, AL10.AL_FORMAT_MONO8, audioData, sampleRate)
checkALError()
oldBeepSource = beepSource
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) {
AL10.alDeleteSources(beepSource)
}*/
}
// Custom implementation of Util.checkALError() that uses our custom exception.
private fun checkALError() {
val errorCode = AL10.alGetError()
if (errorCode != AL10.AL_NO_ERROR) {
throw net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.ALException(errorCode)
}
}
}

View File

@@ -1,521 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi
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.modulecomputers.virtualcomputer.computer.TerrarumComputerOld
import net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi.Term.Companion.checkIBM437
import java.io.*
import java.nio.file.Files
import java.nio.file.NoSuchFileException
import java.nio.file.Path
import java.nio.file.Paths
import java.util.*
/**
* computer directory:
* .../computers/
* media/hda/ -> .../computers/<uuid for the hda>/
*
* Created by minjaesong on 2016-09-17.
*
*
* NOTES:
* Don't convert '\' to '/'! Rev-slash is used for escape character in sh, and we're sh-compatible!
* Use .absoluteFile whenever possible; there's fuckin oddity! (http://bugs.java.com/bugdatabase/view_bug.do;:YfiG?bug_id=4483097)
*/
@Deprecated("Fuck permission and shit, we go virtual. Use FilesystemTar")
internal class FilesystemDir(globals: Globals, computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) {
init {
// load things. WARNING: THIS IS MANUAL!
globals["fs"] = LuaValue.tableOf()
globals["fs"]["list"] = ListFiles(computer) // CC compliant
globals["fs"]["exists"] = FileExists(computer) // CC/OC compliant
globals["fs"]["isDir"] = IsDirectory(computer) // CC compliant
globals["fs"]["isFile"] = IsFile(computer)
globals["fs"]["isReadOnly"] = IsReadOnly(computer) // CC compliant
globals["fs"]["getSize"] = GetSize(computer) // CC compliant
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) // OC compliant
globals["fs"]["open"] = OpenFile(computer) //CC compliant
globals["fs"]["parent"] = GetParentDir(computer)
// fs.dofile defined in BOOT
// fs.fetchText defined in ROMLIB
}
companion object {
fun ensurePathSanity(path: LuaValue) {
if (path.checkIBM437().contains(Regex("""\.\.""")))
throw LuaError("'..' on path is not supported.")
if (!isValidFilename(path.checkIBM437()))
throw IOException("path contains invalid characters")
}
var isCaseInsensitive: Boolean
init {
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.
if (lowerCase.exists()) lowerCase.delete()
if (upperCase.exists()) upperCase.delete()
lowerCase.createNewFile()
val insensitive = upperCase.exists()
lowerCase.delete()
isCaseInsensitive = insensitive
println("[Filesystem] Case insensitivity: $isCaseInsensitive")
}
catch (e: IOException) {
System.err.println("[Filesystem] Couldn't determine if the file system is case sensitive, falling back to insensitive.")
e.printStackTrace(System.out)
isCaseInsensitive = 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("""[<>:"|?*\u0000-\u001F]""") // original OC uses Set(); we use regex
fun isValidFilename(name: String) = !name.contains(invalidChars)
fun String.validatePath() : String {
if (!isValidFilename(this)) {
throw IOException("path contains invalid characters")
}
return this
}
/** actual directory: <appdata>/Saves/<savename>/computers/<drivename>/
* directs media/ directory to /<uuid> directory
*/
fun net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld.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.checkIBM437().validatePath()
if (path.startsWith('/')) path = path.substring(1)
val finalPath: String
if (path.startsWith("media/")) {
val device = path.substring(6, 9)
val subPath = path.substring(9)
finalPath = computerDir + this.computerValue.getAsString("device") + subPath
}
else {
finalPath = computerDir + this.computerValue.getAsString("boot") + "/" + path
}
// remove trailing slash
return if (finalPath.endsWith("\\") || finalPath.endsWith("/"))
finalPath.substring(0, finalPath.length - 1)
else
finalPath
}
fun combinePath(base: String, local: String) : String {
return "$base$local".replace("//", "/")
}
}
/**
* @param cname == UUID of the drive
*
* actual directory: <appdata>/Saves/<savename>/computers/<drivename>/
*/
class ListFiles(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
FilesystemDir.ensurePathSanity(path)
println("ListFiles: got path ${path.checkIBM437()}")
val table = LuaTable()
val file = File(computer.getRealPath(path)).absoluteFile
try {
file.list().forEachIndexed { i, s -> table.insert(i, LuaValue.valueOf(s)) }
}
catch (e: NullPointerException) {}
return table
}
}
/** Don't use this. Use isFile */
class FileExists(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
FilesystemDir.ensurePathSanity(path)
return LuaValue.valueOf(Files.exists(Paths.get(computer.getRealPath(path)).toAbsolutePath()))
}
}
class IsDirectory(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
FilesystemDir.ensurePathSanity(path)
val isDir = Files.isDirectory(Paths.get(computer.getRealPath(path)).toAbsolutePath())
val exists = Files.exists(Paths.get(computer.getRealPath(path)).toAbsolutePath())
return LuaValue.valueOf(isDir || exists)
}
}
class IsFile(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
FilesystemDir.ensurePathSanity(path)
// check if the path is file by checking:
// 1. isfile
// 2. canwrite
// 3. length
// Why? Our Java simply wants to fuck you.
val path = Paths.get(computer.getRealPath(path)).toAbsolutePath()
var result = false
result = Files.isRegularFile(path)
if (!result) result = Files.isWritable(path)
if (!result)
try { result = Files.size(path) > 0 }
catch (e: NoSuchFileException) { result = false }
return LuaValue.valueOf(result)
}
}
class IsReadOnly(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
FilesystemDir.ensurePathSanity(path)
return LuaValue.valueOf(!Files.isWritable(Paths.get(computer.getRealPath(path)).toAbsolutePath()))
}
}
/** we have 4GB file size limit */
class GetSize(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
FilesystemDir.ensurePathSanity(path)
return LuaValue.valueOf(Files.size(Paths.get(computer.getRealPath(path)).toAbsolutePath()).toInt())
}
}
// TODO class GetFreeSpace
/**
* difference with ComputerCraft: it returns boolean, true on successful.
*/
class Mkdir(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
FilesystemDir.ensurePathSanity(path)
return LuaValue.valueOf(File(computer.getRealPath(path)).absoluteFile.mkdir())
}
}
/**
* moves a directory, overwrites the target
*/
class Mv(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : TwoArgFunction() {
override fun call(from: LuaValue, to: LuaValue) : LuaValue {
FilesystemDir.ensurePathSanity(from)
FilesystemDir.ensurePathSanity(to)
val fromFile = File(computer.getRealPath(from)).absoluteFile
var success = fromFile.copyRecursively(
File(computer.getRealPath(to)).absoluteFile, overwrite = true
)
if (success) success = fromFile.deleteRecursively()
else return LuaValue.valueOf(false)
return LuaValue.valueOf(success)
}
}
/**
* copies a directory, overwrites the target
* difference with ComputerCraft: it returns boolean, true on successful.
*/
class Cp(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : TwoArgFunction() {
override fun call(from: LuaValue, to: LuaValue) : LuaValue {
FilesystemDir.ensurePathSanity(from)
FilesystemDir.ensurePathSanity(to)
return LuaValue.valueOf(
File(computer.getRealPath(from)).absoluteFile.copyRecursively(
File(computer.getRealPath(to)).absoluteFile, overwrite = true
)
)
}
}
/**
* difference with ComputerCraft: it returns boolean, true on successful.
*/
class Rm(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
FilesystemDir.ensurePathSanity(path)
return LuaValue.valueOf(
File(computer.getRealPath(path)).absoluteFile.deleteRecursively()
)
}
}
class ConcatPath(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : TwoArgFunction() {
override fun call(base: LuaValue, local: LuaValue) : LuaValue {
FilesystemDir.ensurePathSanity(base)
FilesystemDir.ensurePathSanity(local)
val combinedPath = combinePath(base.checkIBM437().validatePath(), local.checkIBM437().validatePath())
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: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : TwoArgFunction() {
override fun call(path: LuaValue, mode: LuaValue) : LuaValue {
FilesystemDir.ensurePathSanity(path)
val mode = mode.checkIBM437().toLowerCase()
val luaClass = LuaTable()
val file = File(computer.getRealPath(path)).absoluteFile
if (mode.contains(Regex("""[aw]""")) && !file.canWrite())
throw LuaError("Cannot open file for " +
"${if (mode.startsWith('w')) "read" else "append"} mode" +
": is readonly.")
when (mode) {
"r" -> {
try {
val fr = FileReader(file)
luaClass["close"] = FileClassClose(fr)
luaClass["readLine"] = FileClassReadLine(fr)
luaClass["readAll"] = FileClassReadAll(file.toPath())
}
catch (e: FileNotFoundException) {
e.printStackTrace()
throw LuaError(
if (e.message != null && e.message!!.contains(Regex("""[Aa]ccess (is )?denied""")))
"$path: access denied."
else
"$path: no such file."
)
}
}
"rb" -> {
try {
val fis = FileInputStream(file)
luaClass["close"] = FileClassClose(fis)
luaClass["read"] = FileClassReadByte(fis)
luaClass["readAll"] = FileClassReadAll(file.toPath())
}
catch (e: FileNotFoundException) {
e.printStackTrace()
throw LuaError("$path: no such file.")
}
}
"w", "a" -> {
try {
val fw = FileWriter(file, (mode.startsWith('a')))
luaClass["close"] = FileClassClose(fw)
luaClass["write"] = FileClassPrintText(fw)
luaClass["writeLine"] = FileClassPrintlnText(fw)
luaClass["flush"] = FileClassFlush(fw)
}
catch (e: FileNotFoundException) {
e.printStackTrace()
throw LuaError("$path: is a directory.")
}
}
"wb", "ab" -> {
try {
val fos = FileOutputStream(file, (mode.startsWith('a')))
luaClass["close"] = FileClassClose(fos)
luaClass["write"] = FileClassWriteByte(fos)
luaClass["writeBytes"] = FileClassWriteBytes(fos)
luaClass["flush"] = FileClassFlush(fos)
}
catch (e: FileNotFoundException) {
e.printStackTrace()
throw LuaError("$path: is a directory.")
}
}
}
return luaClass
}
}
class GetParentDir(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
FilesystemDir.ensurePathSanity(path)
var pathSB = StringBuilder(path.checkIBM437())
// backward travel, drop chars until '/' has encountered
while (!pathSB.endsWith('/'))
pathSB.deleteCharAt(pathSB.lastIndex - 1)
// drop trailing '/'
if (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.checkIBM437()
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.checkIBM437()
fw.write(text)
return LuaValue.NONE
}
}
private class FileClassPrintlnText(val fw: FileWriter) : OneArgFunction() {
override fun call(string: LuaValue) : LuaValue {
val text = string.checkIBM437() + "\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 FileClassReadAllBytes(val path: Path) : ZeroArgFunction() {
override fun call() : LuaValue {
val byteArr = Files.readAllBytes(path)
val s: String = java.lang.String(byteArr, "IBM437").toString()
return LuaValue.valueOf(s)
}
}
private class FileClassReadAll(val path: Path) : ZeroArgFunction() {
override fun call() : LuaValue {
return FileClassReadAllBytes(path).call()
}
}
/** returns NO line separator! */
private class FileClassReadLine(val fr: FileReader) : ZeroArgFunction() {
val scanner = Scanner(fr.readText()) // no closing; keep the scanner status persistent
override fun call() : LuaValue {
return if (scanner.hasNextLine()) LuaValue.valueOf(scanner.nextLine())
else LuaValue.NIL
}
}
}

View File

@@ -1,7 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi
/**
* Created by minjaesong on 2016-09-17.
*/
class FilesystemFactory {
}

View File

@@ -1,512 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi
import net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi.Term.Companion.checkIBM437
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.*
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.VDUtil.VDPath
import org.luaj.vm2.Globals
import org.luaj.vm2.LuaError
import org.luaj.vm2.LuaValue
import java.io.IOException
import java.nio.charset.Charset
import java.util.*
/**
* computer directory:
* .../computers/
* media/hda/ -> .../computers/<uuid for the hda>/
*
* Created by minjaesong on 2016-09-17.
*
*
* NOTES:
* Don't convert '\' to '/'! Rev-slash is used for escape character in sh, and we're sh-compatible!
* Use .absoluteFile whenever possible; there's fuckin oddity! (http://bugs.java.com/bugdatabase/view_bug.do;:YfiG?bug_id=4483097)
*/
internal class Filesystem(globals: Globals, computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) {
/*init {
// load things. WARNING: THIS IS MANUAL!
globals["fs"] = LuaValue.tableOf()
globals["fs"]["list"] = ListFiles(computer) // CC compliant
globals["fs"]["exists"] = FileExists(computer) // CC/OC compliant
globals["fs"]["isDir"] = IsDirectory(computer) // CC compliant
globals["fs"]["isFile"] = IsFile(computer)
globals["fs"]["isReadOnly"] = IsReadOnly(computer) // CC compliant
globals["fs"]["getSize"] = GetSize(computer) // CC compliant
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) // OC compliant
globals["fs"]["open"] = OpenFile(computer) //CC compliant
globals["fs"]["parent"] = GetParentDir(computer)
// fs.dofile defined in BOOT
// fs.fetchText defined in ROMLIB
}*/
companion object {
val sysCharset = Charset.forName("CP437")
fun LuaValue.checkPath(): String {
if (this.checkIBM437().contains(Regex("""\.\.""")))
throw LuaError("'..' on path is not supported.")
return this.checkIBM437().validatePath()
}
// 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("""[<>:"|?*\u0000-\u001F]""") // original OC uses Set(); we use regex
fun isValidFilename(name: String) = !name.contains(invalidChars)
fun String.validatePath() : String {
if (!isValidFilename(this)) {
throw IOException("path contains invalid characters")
}
return this
}
/**
* return value is there for chaining only.
*/
fun VDPath.dropMount(): VDPath {
if (this.hierarchy.size >= 2 && this[0].toCanonicalString(sysCharset) == "media") {
this.hierarchy.removeAt(0) // drop "media"
this.hierarchy.removeAt(0) // drop whatever mount symbol
}
return this
}
/**
* if path is {media, someUUID, subpath}, redirects to
* computer.diskRack[SOMEUUID]->subpath
* else, computer.diskRack["hda"]->subpath
*/
fun net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld.getFile(path: VDPath) : DiskEntry? {
val disk = this.getTargetDisk(path)
if (disk == null) return null
path.dropMount()
return VDUtil.getFile(disk, path)
}
/**
* if path is like {media, fd1, subpath}, return
* computer.diskRack["fd1"]
* else, computer.diskRack[<boot device>]
*/
fun net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld.getTargetDisk(path: VDPath) : VirtualDisk? {
if (path.hierarchy.size >= 2 &&
Arrays.equals(path[0], "media".toEntryName(DiskEntry.NAME_LENGTH, sysCharset))) {
val diskName = path[1].toCanonicalString(sysCharset)
val disk = this.diskRack[diskName]
return disk
}
else {
return this.diskRack[this.computerValue.getAsString("boot")]
}
}
fun net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld.getDirectoryEntries(path: VDPath) : Array<DiskEntry>? {
val directory = this.getFile(path)
if (directory == null) return null
return VDUtil.getDirectoryEntries(this.getTargetDisk(path)!!, directory)
}
fun combinePath(base: String, local: String) : String {
return "$base$local".replace("//", "/")
}
private fun tryBool(action: () -> Unit): LuaValue {
try {
action()
return LuaValue.valueOf(true)
}
catch (gottaCatchemAll: Exception) {
return LuaValue.valueOf(false)
}
}
} // end of Companion Object
/*
/**
* @param cname == UUID of the drive
*
* actual directory: <appdata>/Saves/<savename>/computers/<drivename>/
*/
class ListFiles(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
val path = VDPath(path.checkPath(), sysCharset)
val table = LuaTable()
try {
val directoryContents = computer.getDirectoryEntries(path)!!
println("[Filesystem] directoryContents size: ${directoryContents.size}")
directoryContents.forEachIndexed { index, diskEntry ->
table.insert(index + 1, LuaValue.valueOf(diskEntry.filename.toCanonicalString(sysCharset)))
}
}
catch (e: KotlinNullPointerException) {}
return table
}
}
class FileExists(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
val path = VDPath(path.checkPath(), sysCharset)
val disk = computer.getTargetDisk(path)
if (disk == null) return LuaValue.valueOf(false)
return LuaValue.valueOf(
VDUtil.getFile(disk, path.dropMount()) != null
)
}
}
class IsDirectory(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
val path = VDPath(path.checkPath(), sysCharset)
return LuaValue.valueOf(computer.getFile(path)?.contents is EntryDirectory)
}
}
class IsFile(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
val path = VDPath(path.checkPath(), sysCharset)
return LuaValue.valueOf(computer.getFile(path)?.contents is EntryFile)
}
}
class IsReadOnly(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
return LuaValue.valueOf(false)
}
}
/** we have 2 GB file size limit */
class GetSize(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
val path = VDUtil.VDPath(path.checkPath(), sysCharset)
val file = computer.getFile(path)
try {
if (file!!.contents is EntryFile)
return LuaValue.valueOf(file.contents.getSizePure().toInt())
else if (file.contents is EntryDirectory)
return LuaValue.valueOf(file.contents.entryCount)
}
catch (e: KotlinNullPointerException) {
}
return LuaValue.NONE
}
}
// TODO class GetFreeSpace
/**
* returns true on success
*/
class Mkdir(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
return tryBool {
val path = VDPath(path.checkPath(), sysCharset)
val disk = computer.getTargetDisk(path)!!
val dirList = computer.getDirectoryEntries(path.getParent())
var makeNew = true
// check dupes
if (dirList != null) {
for (entry in dirList) {
if (Arrays.equals(path.last(), entry.filename)) {
makeNew = false
break
}
}
}
if (makeNew) {
VDUtil.addDir(disk, path.getParent(), path.last())
}
}
}
}
/**
* moves a directory, overwrites the target
*/
class Mv(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : TwoArgFunction() {
override fun call(from: LuaValue, to: LuaValue) : LuaValue {
return tryBool {
val pathFrom = VDPath(from.checkPath(), sysCharset)
val disk1 = computer.getTargetDisk(pathFrom)
val pathTo = VDPath(to.checkPath(), sysCharset)
val disk2 = computer.getTargetDisk(pathTo)
VDUtil.moveFile(disk1!!, pathFrom, disk2!!, pathTo)
}
}
}
/**
* copies a directory, overwrites the target
* difference with ComputerCraft: it returns boolean, true on successful.
*/
class Cp(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : TwoArgFunction() {
override fun call(from: LuaValue, to: LuaValue) : LuaValue {
return tryBool {
val pathFrom = VDPath(from.checkPath(), sysCharset)
val disk1 = computer.getTargetDisk(pathFrom)!!
val pathTo = VDPath(to.checkPath(), sysCharset)
val disk2 = computer.getTargetDisk(pathTo)!!
val oldFile = VDUtil.getFile(disk2, pathTo)
try {
VDUtil.deleteFile(disk2, pathTo)
}
catch (e: FileNotFoundException) {
"Nothing to delete beforehand"
}
val file = VDUtil.getFile(disk1, pathFrom)!!
try {
VDUtil.addFile(disk2, pathTo.getParent(), file)
}
catch (e: FileNotFoundException) {
// roll back delete on disk2
if (oldFile != null) {
VDUtil.addFile(disk2, oldFile.parentEntryID, oldFile)
throw FileNotFoundException("No such destination")
}
}
}
}
}
/**
* difference with ComputerCraft: it returns boolean, true on successful.
*/
class Rm(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
return tryBool {
val path = VDPath(path.checkPath(), sysCharset)
val disk = computer.getTargetDisk(path)!!
VDUtil.deleteFile(disk, path)
}
}
}
class ConcatPath(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : TwoArgFunction() {
override fun call(base: LuaValue, local: LuaValue) : LuaValue {
TODO()
}
}
/**
* @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: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : TwoArgFunction() {
override fun call(path: LuaValue, mode: LuaValue) : LuaValue {
val path = VDPath(path.checkPath(), sysCharset)
val disk = computer.getTargetDisk(path)!!
path.dropMount()
val mode = mode.checkIBM437().toLowerCase()
val luaClass = LuaTable()
val fileEntry = computer.getFile(path)!!
if (fileEntry.contents is EntryDirectory) {
throw LuaError("File '${fileEntry.getFilenameString(sysCharset)}' is directory.")
}
val file = fileEntry.contents as EntryFile
if (mode.contains(Regex("""[aw]""")))
throw LuaError("Cannot open file for " +
"${if (mode.startsWith('w')) "read" else "append"} mode" +
": is readonly.")
when (mode) {
"r" -> {
try {
val fr = StringReader(String(file.bytes.toByteArray(), sysCharset))//FileReader(file)
luaClass["close"] = FileClassClose(fr)
luaClass["readLine"] = FileClassReadLine(fr)
luaClass["readAll"] = FileClassReadAll(file)
}
catch (e: FileNotFoundException) {
e.printStackTrace()
throw LuaError(
if (e.message != null && e.message!!.contains(Regex("""[Aa]ccess (is )?denied""")))
"$path: access denied."
else
"$path: no such file."
)
}
}
"rb" -> {
try {
val fis = ByteArrayInputStream(file.bytes.toByteArray())
luaClass["close"] = FileClassClose(fis)
luaClass["read"] = FileClassReadByte(fis)
luaClass["readAll"] = FileClassReadAll(file)
}
catch (e: FileNotFoundException) {
e.printStackTrace()
throw LuaError("$path: no such file.")
}
}
"w", "a" -> {
try {
val fw = VDFileWriter(fileEntry, mode.startsWith('a'), sysCharset)
luaClass["close"] = FileClassClose(fw)
luaClass["write"] = FileClassPrintText(fw)
luaClass["writeLine"] = FileClassPrintlnText(fw)
luaClass["flush"] = FileClassFlush(fw)
}
catch (e: FileNotFoundException) {
e.printStackTrace()
throw LuaError("$path: is a directory.")
}
}
"wb", "ab" -> {
try {
val fos = VDFileOutputStream(fileEntry, mode.startsWith('a'), sysCharset)
luaClass["close"] = FileClassClose(fos)
luaClass["write"] = FileClassWriteByte(fos)
luaClass["writeBytes"] = FileClassWriteBytes(fos)
luaClass["flush"] = FileClassFlush(fos)
}
catch (e: FileNotFoundException) {
e.printStackTrace()
throw LuaError("$path: is a directory.")
}
}
}
return luaClass
}
}
class GetParentDir(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(path: LuaValue) : LuaValue {
val path = VDPath(path.checkPath(), sysCharset).getParent()
return LuaValue.valueOf(path.toString())
}
}
//////////////////////////////
// OpenFile implementations //
//////////////////////////////
private class FileClassClose(val fo: Closeable) : ZeroArgFunction() {
override fun call() : LuaValue {
fo.close()
return LuaValue.NONE
}
}
private class FileClassWriteByte(val fos: VDFileOutputStream) : OneArgFunction() {
override fun call(byte: LuaValue) : LuaValue {
fos.write(byte.checkint())
return LuaValue.NONE
}
}
private class FileClassWriteBytes(val fos: VDFileOutputStream) : OneArgFunction() {
override fun call(byteString: LuaValue) : LuaValue {
val byteString = byteString.checkIBM437()
val bytearr = ByteArray(byteString.length, { byteString[it].toByte() })
fos.write(bytearr)
return LuaValue.NONE
}
}
private class FileClassPrintText(val fw: VDFileWriter) : OneArgFunction() {
override fun call(string: LuaValue) : LuaValue {
val text = string.checkIBM437()
fw.write(text)
return LuaValue.NONE
}
}
private class FileClassPrintlnText(val fw: VDFileWriter) : OneArgFunction() {
override fun call(string: LuaValue) : LuaValue {
val text = string.checkIBM437() + "\n"
fw.write(text)
return LuaValue.NONE
}
}
private class FileClassFlush(val fo: Flushable) : ZeroArgFunction() {
override fun call() : LuaValue {
fo.flush()
return LuaValue.NONE
}
}
private class FileClassReadByte(val fis: ByteArrayInputStream) : ZeroArgFunction() {
override fun call() : LuaValue {
val readByte = fis.read()
return if (readByte == -1) LuaValue.NIL else LuaValue.valueOf(readByte)
}
}
private class FileClassReadAllBytes(val file: EntryFile) : ZeroArgFunction() {
override fun call() : LuaValue {
return LuaValue.valueOf(String(file.bytes.toByteArray(), sysCharset))
}
}
private class FileClassReadAll(val file: EntryFile) : ZeroArgFunction() {
override fun call() : LuaValue {
return LuaValue.valueOf(String(file.bytes.toByteArray(), sysCharset))
}
}
/** returns NO line separator! */
private class FileClassReadLine(fr: Reader) : ZeroArgFunction() {
val scanner = Scanner(fr.readText()) // no closing; keep the scanner status persistent
override fun call() : LuaValue {
return if (scanner.hasNextLine()) LuaValue.valueOf(scanner.nextLine())
else LuaValue.NIL
}
}*/
}

View File

@@ -1,78 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi
import net.torvald.terrarum.gameactors.ai.toLua
import org.luaj.vm2.lib.OneArgFunction
import org.luaj.vm2.lib.ZeroArgFunction
import net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld
import net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi.Term.Companion.checkIBM437
import net.torvald.terrarum.modulecomputers.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 2016-09-19.
*/
internal class HostAccessProvider(globals: Globals, computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) {
init {
globals["machine"] = LuaTable()
globals["machine"]["println"] = PrintLn()
globals["machine"]["isHalted"] = IsHalted(computer)
globals["machine"]["__readFromStdin"] = NativeReadStdin(computer)
globals["machine"]["milliTime"] = NativeGetMilliTime(computer)
globals["machine"]["sleep"] = NativeThreadSleep(computer)
globals["__haltsystemexplicit__"] = HaltComputer(computer)
}
class PrintLn(): OneArgFunction() {
override fun call(p0: LuaValue): LuaValue {
if (p0.isnumber())
println(p0.checkdouble())
else
println(p0.checkIBM437())
return LuaValue.NONE
}
}
class IsHalted(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld): ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(computer.isHalted)
}
}
class NativeReadStdin(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : ZeroArgFunction() {
override fun call(): LuaValue {
return computer.stdin!!.read().toLua()
}
}
class HaltComputer(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : ZeroArgFunction() {
override fun call() : LuaValue {
computer.isHalted = true
computer.luaJ_globals.load("""print(DC4.."system halted")""").call()
return LuaValue.NONE
}
}
/** Time elapsed since the power is on. */
class NativeGetMilliTime(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(computer.milliTime)
}
}
class NativeThreadSleep(val computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : OneArgFunction() {
override fun call(mills: LuaValue): LuaValue {
computer.currentExecutionThread.join(mills.checklong())
return LuaValue.NONE
}
}
}

View File

@@ -1,16 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi
import com.badlogic.gdx.Gdx
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.modulecomputers.virtualcomputer.computer.TerrarumComputerOld
/**
* Created by minjaesong on 2016-09-25.
*/
class Input(globals: Globals, computer: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) {
}

View File

@@ -1,149 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi
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.modulecomputers.virtualcomputer.computer.TerrarumComputerOld
import org.luaj.vm2.LuaFunction
import org.luaj.vm2.lib.OneArgFunction
/**
* PC Speaker driver and arpeggiator (MONOTONE-style 4 channels)
*
* Notes are tuned to A440, equal temperament. This is an ISO standard.
*
* Created by minjaesong on 2016-09-27.
*/
class PcSpeakerDriver(val globals: Globals, host: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) {
init {
globals["speaker"] = LuaTable()
globals["speaker"]["enqueue"] = EnqueueTone(host)
globals["speaker"]["clear"] = ClearQueue(host)
globals["speaker"]["retune"] = Retune(globals)
globals["speaker"]["resetTune"] = ResetTune(globals)
globals["speaker"]["toFreq"] = StringToFrequency(globals)
globals["speaker"]["__basefreq__"] = LuaValue.valueOf(BASE_FREQ) // every other PSGs should use this very variable
// constants
// e.g. speaker.A0 returns number 1
fun Int.toNote(): String = NOTE_NAMES[this % 12] + this.plus(8).div(12).toString()
fun Int.toNoteAlt(): String = NOTE_NAMES_ALT[this % 12] + this.plus(8).div(12).toString()
for (i in 1..126) {
globals["speaker"][i.toNote()] = i // sharps
globals["speaker"][i.toNoteAlt()] = i // flats
}
}
companion object {
val BASE_FREQ = 27.5 // frequency of A0
val NOTE_NAMES = arrayOf("GS", "A", "AS", "B", "C", "CS",
"D", "DS", "E", "F", "FS", "G")
val NOTE_NAMES_ALT = arrayOf("Ab", "A", "Bb", "B", "C", "Db",
"D", "Eb", "E", "F", "Gb", "G")
/** @param basefreq: Frequency of A-0 */
fun Int.toFreq(basefreq: Double): Double = basefreq * Math.pow(2.0, (this - 1.0) / 12.0)
/** @param "A-5", "B4", "C#5", ... */
fun String.toNoteIndex(): Int {
var notestr = this.replace("-", "")
notestr = notestr.replace("#", "S")
val baseNote = if (notestr.contains("S") || notestr.contains("b"))
notestr.substring(0, 2)
else
notestr.substring(0, 1)
var note: Int = NOTE_NAMES.indexOf(baseNote) // [0-11]
if (note < 0) note = NOTE_NAMES_ALT.indexOf(baseNote) // search again
if (note < 0) throw IllegalArgumentException("Unknown note: $this") // failed to search
val octave: Int = notestr.replace(Regex("""[^0-9]"""), "").toInt()
return octave.minus(if (note >= 4) 1 else 0) * 12 + note
}
}
class EnqueueTone(val host: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : TwoArgFunction() {
/**
* @param freq: number (hertz) or string (A-4, A4, B#2, ...)
*/
override fun call(second: LuaValue, freq: LuaValue): LuaValue {
if (freq.isnumber())
host.enqueueBeep(second.checkdouble(), freq.checkdouble())
else {
host.enqueueBeep(second.checkdouble(),
freq.checkjstring().toNoteIndex()
.toFreq(host.luaJ_globals["speaker"]["__basefreq__"].checkdouble())
)
}
return LuaValue.NONE
}
}
class ClearQueue(val host: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld) : ZeroArgFunction() {
override fun call(): LuaValue {
host.clearBeepQueue()
return LuaValue.NONE
}
}
class Retune(val globals: Globals) : LuaFunction() {
/**
* Examples: C256, A440, A#440, ...
*/
override fun call(arg: LuaValue): LuaValue {
val tuneName = arg.checkjstring()
val baseNote = if (tuneName.contains("#") || tuneName.contains("b")) tuneName.substring(0, 2) else tuneName.substring(0, 1)
val freq = tuneName.replace(Regex("""[^0-9]"""), "").toInt()
// we're assuming the input to be C4, C#4, ... A4, A#4, B4
// diffPivot corsp. to G#4, A4, ...
val diffPivot = arrayOf(-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) // 2^(12 / n)
var diff = diffPivot[NOTE_NAMES.indexOf(baseNote)]
if (diff < 0) diff = diffPivot[NOTE_NAMES_ALT.indexOf(baseNote)] // search again
if (diff < 0) throw IllegalArgumentException("Unknown note: $baseNote") // failed to search
val exp = -diff / 12.0
val basefreq = freq * Math.pow(2.0, exp) / if (diff >= 3) 8.0 else 16.0 // converts whatever baseNote to A0
globals["speaker"]["__basefreq__"] = basefreq
return LuaValue.NONE
}
override fun call(): LuaValue {
globals["speaker"]["__basefreq__"] = LuaValue.valueOf(BASE_FREQ)
return LuaValue.NONE
}
}
class ResetTune(val globals: Globals) : ZeroArgFunction() {
override fun call(): LuaValue {
globals["speaker"]["__basefreq__"] = LuaValue.valueOf(BASE_FREQ)
return LuaValue.NONE
}
}
/**
* usage = speaker.toFreq(speaker.AS5) --'S' is a substitution for '#'
*/
class StringToFrequency(val globals: Globals) : OneArgFunction() {
/**
* @param arg: number (note index) or string (A-4, A4, B#2, ...)
*/
override fun call(arg: LuaValue): LuaValue {
val note = if (arg.isint()) arg.checkint()
else {
arg.checkjstring().toNoteIndex()
}
val basefreq = globals["speaker"]["__basefreq__"].checkdouble()
return LuaValue.valueOf(note.toFreq(basefreq))
}
}
}

View File

@@ -1,98 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi
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
import java.security.SecureRandom
/**
* Hashes, CSPRNG, Base64
*
* Created by minjaesong on 2016-09-15.
*/
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 */
class SHA256sum : OneArgFunction() {
override fun call(p0: LuaValue): LuaValue {
val hashBytes = DigestUtils.sha256(p0.checkjstring())
return LuaValue.valueOf(hashBytes.toStringRepresentation())
}
}
/** @return byteArray as String */
class SHA1sum: OneArgFunction() {
override fun call(p0: LuaValue): LuaValue {
val hashBytes = DigestUtils.sha1(p0.checkjstring())
return LuaValue.valueOf(hashBytes.toStringRepresentation())
}
}
/** @return byteArray as String */
class MD5sum: OneArgFunction() {
override fun call(p0: LuaValue): LuaValue {
val hashBytes = DigestUtils.md5(p0.checkjstring())
return LuaValue.valueOf(hashBytes.toStringRepresentation())
}
}
/** @return byteArray as String */
class SecureRandomHex: OneArgFunction() {
override fun call(byteSize: LuaValue): LuaValue {
val bytes = ByteArray(byteSize.checkint())
SecureRandom().nextBytes(bytes)
return LuaValue.valueOf(bytes.toStringRepresentation())
}
}
/** @return String */
class DecodeBase64: OneArgFunction() {
override fun call(base64: LuaValue): LuaValue {
val decodedBytes = Base64.decodeBase64(base64.checkjstring())
return LuaValue.valueOf(decodedBytes.toStringRepresentation())
}
}
/** @return byteArray as String */
class EncodeBase64: OneArgFunction() {
override fun call(inputString: LuaValue): LuaValue {
val inputBytes = inputString.checkjstring().toByteArray(charset("UTF-8"))
return LuaValue.valueOf(Base64.encodeBase64(inputBytes).toStringRepresentation())
}
}
companion object {
val hexLookup = charArrayOf(
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
)
fun Byte.toHexString(): String {
val bInt = this.toUint()
return "${hexLookup[bInt.shr(8).and(0xf)]}${hexLookup[bInt.and(0xf)]}"
}
/** essentially, 0xFC to 0xFC.toChar() */
fun ByteArray.toStringRepresentation(): String {
val sb = StringBuilder()
for (b in this)
sb.append(b.toChar())
return sb.toString()
}
}
}

View File

@@ -1,284 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi
import org.luaj.vm2.*
import org.luaj.vm2.lib.*
import net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Teletype
import net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal
import java.nio.charset.Charset
/**
* Controls terminal as if it was a monitor
* (not sending control sequences but just drives it directly)
*
* Created by minjaesong on 2016-09-12.
*/
internal class Term(globals: Globals, term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Teletype) {
init {
// load things. WARNING: THIS IS MANUAL!
globals["term"] = LuaValue.tableOf()
globals["term"]["write"] = Term.WriteString(term)
globals["term"]["print"] = Term.PrintString(term)
globals["term"]["newLine"] = Term.NewLine(term)
globals["term"]["moveCursor"] = Term.MoveCursor(term) // TTY function
globals["term"]["width"] = Term.GetWidth(term)
globals["term"]["scroll"] = Term.Scroll(term)
globals["term"]["isTeletype"] = Term.IsTeletype(term)
globals["term"]["bell"] = Term.Bell(term)
if (term is net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) {
globals["term"]["emitRaw"] = Term.EmitRaw(term)
globals["term"]["emit"] = Term.Emit(term)
globals["term"]["emitString"] = Term.EmitString(term)
globals["term"]["resetColor"] = Term.ResetColour(term)
globals["term"]["resetColour"] = Term.ResetColour(term)
globals["term"]["clear"] = Term.Clear(term)
globals["term"]["clearLine"] = Term.ClearLine(term)
globals["term"]["setCursor"] = Term.SetCursor(term)
globals["term"]["getCursor"] = Term.GetCursorPos(term)
globals["term"]["getX"] = Term.GetCursorX(term)
globals["term"]["getY"] = Term.GetCursorY(term)
globals["term"]["setX"] = Term.SetCursorX(term)
globals["term"]["setY"] = Term.SetCursorY(term)
globals["term"]["setCursorBlink"] = Term.SetCursorBlink(term)
globals["term"]["size"] = Term.GetSize(term)
globals["term"]["height"] = Term.GetHeight(term)
globals["term"]["isCol"] = Term.IsColour(term)
globals["term"]["setForeCol"] = Term.SetForeColour(term)
globals["term"]["setBackCol"] = Term.SetBackColour(term)
globals["term"]["foreCol"] = Term.GetForeColour(term)
globals["term"]["backCol"] = Term.GetBackColour(term)
}
}
companion object {
fun LuaValue.checkIBM437(): String {
if (this is LuaString)
return m_bytes.copyOfRange(m_offset, m_offset + m_length).toString(Charset.forName("CP437"))
// it only works if Charset is ISO-8859, despite of the name "IBM437"
// --> then would "CP437" work? -- Torvald at 2017-04-05
else
throw LuaError("bad argument (string expected, got ${this.typename()})")
}
}
class Bell(val tty: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Teletype) : OneArgFunction() {
override fun call(pattern: LuaValue): LuaValue {
tty.bell(pattern.checkjstring())
return LuaValue.NONE
}
}
class WriteString(val tty: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Teletype) : LuaFunction() {
override fun call(p0: LuaValue): LuaValue {
if (tty is net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal)
tty.writeString(p0.checkIBM437(), tty.cursorX, tty.cursorY)
else
tty.writeChars(p0.checkIBM437())
return LuaValue.NONE
}
override fun call(s: LuaValue, x: LuaValue, y: LuaValue): LuaValue {
if (tty is net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal)
tty.writeString(s.checkIBM437(), x.checkint(), y.checkint())
else
throw LuaError("couldn't move cursor; TTY is one-dimensional")
return LuaValue.NONE
}
}
class PrintString(val tty: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Teletype) : LuaFunction() {
override fun call(p0: LuaValue): LuaValue {
if (tty is net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal)
tty.printString(p0.checkIBM437(), tty.cursorX, tty.cursorY)
else
tty.printChars(p0.checkIBM437())
return LuaValue.NONE
}
override fun call(s: LuaValue, x: LuaValue, y: LuaValue): LuaValue {
if (tty is net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal)
tty.printString(s.checkIBM437(), x.checkint(), y.checkint())
else
throw LuaError("couldn't move cursor; TTY is one-dimensional")
return LuaValue.NONE
}
}
class NewLine(val tty: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Teletype) : ZeroArgFunction() {
override fun call(): LuaValue {
tty.newLine()
return LuaValue.NONE
}
}
class EmitRaw(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : ThreeArgFunction() {
override fun call(p0: LuaValue, x: LuaValue, y: LuaValue): LuaValue {
term.emitChar(p0.checkint(), x.checkint() - 1, y.checkint() - 1)
return LuaValue.NONE
}
}
// emitchar
class Emit(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : ThreeArgFunction() {
override fun call(p0: LuaValue, x: LuaValue, y: LuaValue): LuaValue {
term.emitChar(p0.checkint().toChar(), x.checkint() - 1, y.checkint() - 1)
return LuaValue.NONE
}
}
class EmitString(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : ThreeArgFunction() {
override fun call(p0: LuaValue, x: LuaValue, y: LuaValue): LuaValue {
term.emitString(p0.checkIBM437(), x.checkint() - 1, y.checkint() - 1)
return LuaValue.NONE
}
}
class ResetColour(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : ZeroArgFunction() {
override fun call(): LuaValue {
term.resetColour()
return LuaValue.NONE
}
}
class Clear(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : ZeroArgFunction() {
override fun call(): LuaValue {
term.clear()
return LuaValue.NONE
}
}
class ClearLine(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : ZeroArgFunction() {
override fun call(): LuaValue {
term.clearLine()
return LuaValue.NONE
}
}
/** term.setCursorPos(number x) */
class MoveCursor(val tty: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Teletype) : OneArgFunction() {
override fun call(p0: LuaValue): LuaValue {
for (i in 1..p0.checkint())
tty.printChar(' ')
return LuaValue.NONE
}
}
class SetCursor(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : TwoArgFunction() {
override fun call(x: LuaValue, y: LuaValue): LuaValue {
term.setCursor(x.checkint() - 1, y.checkint() - 1)
return LuaValue.NONE
}
}
/** One-based */
class GetCursorPos(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : VarArgFunction() {
override fun invoke(args: Varargs?): Varargs {
val ret = arrayOf(LuaValue.valueOf(term.cursorX + 1), LuaValue.valueOf(term.cursorY + 1))
return LuaValue.varargsOf(ret)
}
}
class GetCursorX(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(term.cursorX + 1)
}
}
class GetCursorY(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(term.cursorY + 1)
}
}
class SetCursorX(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : OneArgFunction() {
override fun call(p0: LuaValue): LuaValue {
term.setCursor(p0.checkint() - 1, term.cursorY)
return LuaValue.NONE
}
}
class SetCursorY(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : OneArgFunction() {
override fun call(p0: LuaValue): LuaValue {
term.setCursor(term.cursorX - 1, p0.checkint())
return LuaValue.NONE
}
}
/** term.setCursorBlink(boolean bool) */
class SetCursorBlink(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : OneArgFunction() {
override fun call(p0: LuaValue): LuaValue {
term.cursorBlink = p0.toboolean()
return LuaValue.NONE
}
}
class GetSize(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : VarArgFunction() {
override fun invoke(args: Varargs?): Varargs {
val ret = arrayOf(LuaValue.valueOf(term.width), LuaValue.valueOf(term.height))
return LuaValue.varargsOf(ret)
}
}
class GetWidth(val tty: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Teletype) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(tty.width)
}
}
class GetHeight(val terminal: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(terminal.height)
}
}
class IsColour(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(term.coloursCount > 4)
}
}
/** term.scroll(number n) */
class Scroll(val tty: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Teletype) : OneArgFunction() {
override fun call(p0: LuaValue): LuaValue {
if (tty is net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) tty.scroll(p0.checkint())
else for (i in 1..p0.checkint()) tty.newLine()
return LuaValue.NONE
}
}
/** term.setTextColor(number color) */
class SetForeColour(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : OneArgFunction() {
override fun call(p0: LuaValue): LuaValue {
term.foreColour = p0.checkint()
return LuaValue.NONE
}
}
/** term.setBackgroundColor(number color) */
class SetBackColour(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : OneArgFunction() {
override fun call(p0: LuaValue): LuaValue {
term.backColour = p0.checkint()
return LuaValue.NONE
}
}
class GetForeColour(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(term.foreColour)
}
}
class GetBackColour(val term: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Terminal) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(term.backColour)
}
}
class IsTeletype(val termInQuestion: net.torvald.terrarum.modulecomputers.virtualcomputer.terminal.Teletype) : ZeroArgFunction() {
override fun call(): LuaValue {
return LuaValue.valueOf(termInQuestion.coloursCount == 0)
}
}
}

View File

@@ -1,93 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.luaapi
import org.luaj.vm2.Globals
import org.luaj.vm2.LuaFunction
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
/**
* Implementation of lua's os.date, to return world info of the game world.
*
* Created by minjaesong on 2016-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()
val time = if (Terrarum.ingame != null) (Terrarum.ingame!!.world as GameWorldExtension).worldTime else WorldTime()
// 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
return t
}
val defaultDateFormat = "%a %d %B %Y %X"
/** evaluate single C date format */
fun String.evalAsDate(): String {
val time = if (Terrarum.ingame != null) (Terrarum.ingame!!.world as GameWorldExtension).worldTime else WorldTime()
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.rem(100).toString()
"%%" -> "%"
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)
}
}
}

View File

@@ -1,37 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral
/**
* Abstraction of the communication line. (e.g. serial cable)
*
* A cable may have multiple of CommLines (e.g. serial cable need two for Tx and Rx)
*
* Created by minjaesong on 2019-07-10.
*/
open class CommLine(val bandwidth: Int) {
open val postbox = StringBuilder()
/**
* Returns how many bytes are actually posted, e.g. 0 when band limit is exceeded.
*/
open fun post(msg: String): Int {
if (bandwidth >= msg.length) {
postbox.append(msg)
return msg.length
}
else if (postbox.length >= bandwidth) {
return 0
}
else {
postbox.append(msg.substring(0 until (bandwidth - postbox.length)))
return bandwidth - postbox.length
}
}
open fun get(): String {
val s = postbox.toString()
postbox.clear()
return s
}
}

View File

@@ -1,17 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral
import org.luaj.vm2.Globals
import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
/**
* Created by minjaesong on 2016-09-29.
*/
abstract class Peripheral(val tableName: String) {
abstract fun loadLib(globals: Globals)
override fun toString(): String = "Peripheral:$tableName"
abstract val memSize: Int
}

View File

@@ -1,51 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral
import com.badlogic.gdx.graphics.g2d.BitmapFont
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import net.torvald.terrarum.ModMgr
import org.luaj.vm2.Globals
/**
* Created by minjaesong on 2017-05-31.
*/
class PeripheralCharLCD(val width: Int, val height: Int) : net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral.Peripheral("charLCD") {
/*companion object {
private val fontSheet = BitmapFont(ModMgr.getPath("dwarventech", "mt-32.tga"), 16, 16)
private val font = BitmapFont(fontSheet, 0.toChar())
private val fontW = fontSheet.width / fontSheet.horizontalCount
private val fontH = fontSheet.height / fontSheet.verticalCount
}
override fun loadLib(globals: Globals) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun toString(): String {
return super.toString()
}
override val memSize = width * height
var cursor: Int = 0 // character LCDs are mostly single long line wrapped
val memory = ByteArray(memSize) // temporary; replace with proper VMPeripheralWrapper
/**
* @param g Frame Buffer that holds the display of LCD screen
*/
fun render(batch: SpriteBatch) {
memory.forEachIndexed { index, byte ->
font.draw(batch, "${byte.toChar()}", (index % width) * fontW.toFloat(), (index / width) * fontH.toFloat())
}
}*/
override fun loadLib(globals: Globals) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun toString(): String {
return super.toString()
}
override val memSize: Int
get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates.
}

View File

@@ -1,44 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral
import org.luaj.vm2.Globals
import net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld
import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
import org.luaj.vm2.lib.OneArgFunction
import java.io.BufferedReader
import java.io.InputStreamReader
import java.net.URL
/**
* Provides internet access.
*
* Created by minjaesong on 2016-09-24.
*/
internal class PeripheralInternet(val host: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld)
: net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral.Peripheral("internet"){
override val memSize = 1024
override fun loadLib(globals: Globals) {
globals["internet"] = LuaTable()
globals["internet"]["fetch"] = FetchWebPage()
}
class FetchWebPage() : OneArgFunction() {
override fun call(urlstr: LuaValue): LuaValue {
val url = URL(urlstr.checkjstring())
val inputstream = BufferedReader(InputStreamReader(url.openStream()))
var inline = ""
var readline = inputstream.readLine()
while (readline != null) {
inline += readline
readline = inputstream.readLine()
}
inputstream.close()
return LuaValue.valueOf(inline)
}
}
}

View File

@@ -1,23 +0,0 @@
package net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral
import net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld
import org.luaj.vm2.Globals
import org.luaj.vm2.LuaTable
import org.luaj.vm2.LuaValue
/**
* Virtual driver for 4-track squarewave PSG, which has no ability of changing a duty cycle
* but has a volume control (you'll need some other tracker than MONOTONE)
*
* Created by minjaesong on 2016-09-27.
*/
internal class PeripheralPSG(val host: net.torvald.terrarum.modulecomputers.virtualcomputer.computer.TerrarumComputerOld)
: net.torvald.terrarum.modulecomputers.virtualcomputer.peripheral.Peripheral("psg") {
override val memSize = 1024
override fun loadLib(globals: Globals) {
globals["psg"] = LuaTable()
}
}

Some files were not shown because too many files have changed in this diff Show More