computer item 'almost' workign

This commit is contained in:
minjaesong
2021-12-03 20:19:34 +09:00
parent f456ed3de3
commit 4a4290dc35
21 changed files with 585 additions and 10 deletions

View File

@@ -0,0 +1,23 @@
<component name="libraryTable">
<library name="jetbrains.kotlinx.coroutines.core" type="repository">
<properties maven-id="org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1" />
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/kotlinx-coroutines-core-1.4.1.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-1.4.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/annotations-13.0.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-common-1.4.0.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$PROJECT_DIR$/lib/kotlinx-coroutines-core-1.4.1-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-1.4.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/annotations-13.0-javadoc.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-common-1.4.0-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$PROJECT_DIR$/lib/kotlinx-coroutines-core-1.4.1-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-1.4.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/annotations-13.0-sources.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-common-1.4.0-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@@ -13,5 +13,6 @@
<orderEntry type="library" name="com.badlogicgames.gdx:gdx-backend-lwjgl3:1.10.0" level="project" /> <orderEntry type="library" name="com.badlogicgames.gdx:gdx-backend-lwjgl3:1.10.0" level="project" />
<orderEntry type="library" name="com.badlogicgames.gdx:gdx:1.10.0" level="project" /> <orderEntry type="library" name="com.badlogicgames.gdx:gdx:1.10.0" level="project" />
<orderEntry type="library" name="graalvm-js-21.1.0 and graalvm-js-scriptengine-21.1.0" level="project" /> <orderEntry type="library" name="graalvm-js-21.1.0 and graalvm-js-scriptengine-21.1.0" level="project" />
<orderEntry type="library" name="jetbrains.kotlinx.coroutines.core" level="project" />
</component> </component>
</module> </module>

View File

@@ -5,6 +5,10 @@ import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g2d.TextureRegion import com.badlogic.gdx.graphics.g2d.TextureRegion
import com.badlogic.gdx.utils.Disposable import com.badlogic.gdx.utils.Disposable
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import net.torvald.terrarum.App import net.torvald.terrarum.App
import net.torvald.terrarum.CommonResourcePool import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.ModMgr import net.torvald.terrarum.ModMgr
@@ -17,9 +21,7 @@ import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulecomputers.tsvmperipheral.WorldRadar import net.torvald.terrarum.modulecomputers.tsvmperipheral.WorldRadar
import net.torvald.terrarum.ui.Toolkit import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.ui.UICanvas import net.torvald.terrarum.ui.UICanvas
import net.torvald.tsvm.PeripheralEntry import net.torvald.tsvm.*
import net.torvald.tsvm.TheRealWorld
import net.torvald.tsvm.VM
import net.torvald.tsvm.peripheral.ExtDisp import net.torvald.tsvm.peripheral.ExtDisp
import net.torvald.tsvm.peripheral.VMProgramRom import net.torvald.tsvm.peripheral.VMProgramRom
@@ -41,11 +43,13 @@ class ItemWearableWorldRadar(originalID: String) : GameItem(originalID) {
override var baseToolSize: Double? = baseMass override var baseToolSize: Double? = baseMass
val vm = VM(32768, TheRealWorld(), arrayOf( private val vm = VM(32768, TheRealWorld(), arrayOf(
VMProgramRom(ModMgr.getPath("dwarventech", "bios/pipboot.rom")), VMProgramRom(ModMgr.getPath("dwarventech", "bios/pipboot.rom")),
VMProgramRom(ModMgr.getPath("dwarventech", "bios/pipcode.bas")) VMProgramRom(ModMgr.getPath("dwarventech", "bios/pipcode.bas"))
)) ))
val ui = WearableWorldRadarUI(vm) private val vmRunner: VMRunner
private val coroutineJob: Job
private val ui = WearableWorldRadarUI(vm)
init { init {
super.equipPosition = EquipPosition.HAND_GRIP super.equipPosition = EquipPosition.HAND_GRIP
@@ -55,8 +59,22 @@ class ItemWearableWorldRadar(originalID: String) : GameItem(originalID) {
ExtDisp(vm, 160, 140), 32768, 1, 0 ExtDisp(vm, 160, 140), 32768, 1, 0
) )
App.disposables.add(Disposable { vm.dispose() }) vm.getPrintStream = { System.out }
vm.getErrorStream = { System.err }
vm.getInputStream = { System.`in` }
vmRunner = VMRunnerFactory(vm, "js")
coroutineJob = GlobalScope.launch {
vmRunner.executeCommand(vm.roms[0]!!.readAll())
}
App.disposables.add(Disposable {
vmRunner.close()
coroutineJob.cancel("item disposal")
vm.dispose()
})
App.disposables.add(ui) App.disposables.add(ui)
} }
override fun effectWhenEquipped(actor: ActorWithBody, delta: Float) { override fun effectWhenEquipped(actor: ActorWithBody, delta: Float) {
@@ -79,11 +97,14 @@ class WearableWorldRadarUI(val device: VM) : UICanvas() {
} }
override fun renderUI(batch: SpriteBatch, camera: Camera) { override fun renderUI(batch: SpriteBatch, camera: Camera) {
batch.end()
batch.color = Color.WHITE batch.color = Color.WHITE
(device.peripheralTable[1].peripheral as? ExtDisp)?.render(batch, posX.toFloat(), posY.toFloat()) (device.peripheralTable[1].peripheral as? ExtDisp)?.render(batch, posX.toFloat(), posY.toFloat())
batch.begin()
batch.color = Toolkit.Theme.COL_INACTIVE batch.color = Toolkit.Theme.COL_INACTIVE
Toolkit.drawBoxBorder(batch, posX-1, posY-1, width+2, height+2) Toolkit.drawBoxBorder(batch, posX - 1, posY - 1, width + 2, height + 2)
} }
override fun doOpening(delta: Float) { override fun doOpening(delta: Float) {

522
assets/JS_INIT.js Normal file
View File

@@ -0,0 +1,522 @@
// Polyfilling some functions from ECMAScript6+
if (!String.prototype.repeat) {
String.prototype.repeat = function(count) {
'use strict';
if (this == null)
throw new TypeError('can\'t convert ' + this + ' to object');
var str = '' + this;
// To convert string to integer.
count = +count;
// Check NaN
if (count != count)
count = 0;
if (count < 0)
throw new RangeError('repeat count must be non-negative');
if (count == Infinity)
throw new RangeError('repeat count must be less than infinity');
count = Math.floor(count);
if (str.length == 0 || count == 0)
return '';
// Ensuring count is a 31-bit integer allows us to heavily optimize the
// main part. But anyway, most current (August 2014) browsers can't handle
// strings 1 << 28 chars or longer, so:
if (str.length * count >= 1 << 28)
throw new RangeError('repeat count must not overflow maximum string size');
var maxCount = str.length * count;
count = Math.floor(Math.log(count) / Math.log(2));
while (count) {
str += str;
count--;
}
str += str.substring(0, maxCount - str.length);
return str;
}
}
if (!String.prototype.startsWith) {
Object.defineProperty(String.prototype, 'startsWith', {
value: function(search, rawPos) {
var pos = rawPos > 0 ? rawPos|0 : 0;
return this.substring(pos, pos + search.length) === search;
}
});
}
if (!String.prototype.endsWith) {
Object.defineProperty(String.prototype, 'endsWith', {
value: function(search, this_len) {
if (this_len === undefined || this_len > this.length) {
this_len = this.length;
}
return this.substring(this_len - search.length, this_len) === search;
}
});
}
/**
* String.prototype.replaceAll() polyfill
* https://gomakethings.com/how-to-replace-a-section-of-a-string-with-another-one-with-vanilla-js/
* @author Chris Ferdinandi
* @license MIT
*/
if (!String.prototype.replaceAll) {
String.prototype.replaceAll = function(str, newStr){
// If a regex pattern
if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]') {
return this.replace(str, newStr);
}
// If a string
return this.replace(new RegExp(str, 'g'), newStr);
};
}
if (!Array.prototype.filter){
Array.prototype.filter = function(func, thisArg) {
'use strict';
if ( ! ((typeof func === 'Function' || typeof func === 'function') && this) )
throw new TypeError();
var len = this.length >>> 0,
res = new Array(len), // preallocate array
t = this, c = 0, i = -1;
var kValue;
if (thisArg === undefined){
while (++i !== len){
// checks to see if the key was set
if (i in this){
kValue = t[i]; // in case t is changed in callback
if (func(t[i], i, t)){
res[c++] = kValue;
}
}
}
}
else{
while (++i !== len){
// checks to see if the key was set
if (i in this){
kValue = t[i];
if (func.call(thisArg, t[i], i, t)){
res[c++] = kValue;
}
}
}
}
res.length = c; // shrink down array to proper size
return res;
};
}
if (!String.prototype.padStart) {
String.prototype.padStart = function(l, c) {
return (this.length >= l) ? this : (c.repeat(l - this.length) + this);
};
}
// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.io/#x15.4.4.19
if (!Array.prototype.map) {
Array.prototype.map = function(callback/*, thisArg*/) {
var T, A, k;
if (this == null) {
throw new TypeError('this is null or not defined');
}
// 1. Let O be the result of calling ToObject passing the |this|
// value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal
// method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 1) {
T = arguments[1];
}
// 6. Let A be a new array created as if by the expression new Array(len)
// where Array is the standard built-in constructor with that name and
// len is the value of len.
A = new Array(len);
// 7. Let k be 0
k = 0;
// 8. Repeat, while k < len
while (k < len) {
var kValue, mappedValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal
// method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal
// method of O with argument Pk.
kValue = O[k];
// ii. Let mappedValue be the result of calling the Call internal
// method of callback with T as the this value and argument
// list containing kValue, k, and O.
mappedValue = callback.call(T, kValue, k, O);
// iii. Call the DefineOwnProperty internal method of A with arguments
// Pk, Property Descriptor
// { Value: mappedValue,
// Writable: true,
// Enumerable: true,
// Configurable: true },
// and false.
// In browsers that support Object.defineProperty, use the following:
// Object.defineProperty(A, k, {
// value: mappedValue,
// writable: true,
// enumerable: true,
// configurable: true
// });
// For best browser support, use the following:
A[k] = mappedValue;
}
// d. Increase k by 1.
k++;
}
// 9. return A
return A;
};
}
// Production steps of ECMA-262, Edition 5, 15.4.4.21
// Reference: http://es5.github.io/#x15.4.4.21
// https://tc39.github.io/ecma262/#sec-array.prototype.reduce
if (!Array.prototype.reduce) {
Object.defineProperty(Array.prototype, 'reduce', {
value: function(callback /*, initialValue*/) {
if (this === null) {
throw new TypeError( 'Array.prototype.reduce ' +
'called on null or undefined' );
}
if (typeof callback !== 'function') {
throw new TypeError( callback +
' is not a function');
}
// 1. Let O be ? ToObject(this value).
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length")).
var len = o.length >>> 0;
// Steps 3, 4, 5, 6, 7
var k = 0;
var value;
if (arguments.length >= 2) {
value = arguments[1];
} else {
while (k < len && !(k in o)) {
k++;
}
// 3. If len is 0 and initialValue is not present,
// throw a TypeError exception.
if (k >= len) {
throw new TypeError( 'Reduce of empty array ' +
'with no initial value' );
}
value = o[k++];
}
// 8. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kPresent be ? HasProperty(O, Pk).
// c. If kPresent is true, then
// i. Let kValue be ? Get(O, Pk).
// ii. Let accumulator be ? Call(
// callbackfn, undefined,
// « accumulator, kValue, k, O »).
if (k in o) {
value = callback(value, o[k], k, o);
}
// d. Increase k by 1.
k++;
}
// 9. Return accumulator.
return value;
}
});
}
// Production steps of ECMA-262, Edition 5, 15.4.4.22
// Reference: http://es5.github.io/#x15.4.4.22
if ('function' !== typeof Array.prototype.reduceRight) {
Array.prototype.reduceRight = function(callback /*, initialValue*/) {
'use strict';
if (null === this || 'undefined' === typeof this) {
throw new TypeError('Array.prototype.reduce called on null or undefined');
}
if ('function' !== typeof callback) {
throw new TypeError(callback + ' is not a function');
}
var t = Object(this), len = t.length >>> 0, k = len - 1, value;
if (arguments.length >= 2) {
value = arguments[1];
} else {
while (k >= 0 && !(k in t)) {
k--;
}
if (k < 0) {
throw new TypeError('Reduce of empty array with no initial value');
}
value = t[k--];
}
for (; k >= 0; k--) {
if (k in t) {
value = callback(value, t[k], k, t);
}
}
return value;
};
}
if (!Array.prototype.includes) {
Array.prototype.includes = function(e) {
var k;
for (k = 0; k < this.length; k++) {
if (e === this[k]) return true;
}
return false;
}
}
if (!Object.entries) {
Object.entries = function( obj ){
var ownProps = Object.keys( obj ),
i = ownProps.length,
resArray = new Array(i); // preallocate the Array
while (i--)
resArray[i] = [ownProps[i], obj[ownProps[i]]];
return resArray;
};
}
// haskell-inspired array functions
Array.prototype.head = function() {
return this[0]
}
Array.prototype.last = function() {
return this[this.length - 1]
}
Array.prototype.tail = function() {
return this.slice(1)
}
Array.prototype.init = function() {
return this.slice(0, this.length - 1)
}
Array.prototype.shuffle = function() {
let counter = this.length;
// While there are elements in the array
while (counter > 0) {
// Pick a random index
let index = Math.floor(Math.random() * counter);
// Decrease counter by 1
counter--;
// And swap the last element with it
let temp = this[counter];
this[counter] = this[index];
this[index] = temp;
}
return this;
}
Array.prototype.sum = function(selector) {
return this.reduce((acc,val) => acc + ((selector === undefined) ? val : selector(val)), 0)
}
Array.prototype.max = function(selector) {
return this.reduce((acc,val) => (((selector === undefined) ? val : selector(val)) > acc) ? ((selector === undefined) ? val : selector(val)) : acc, 0)
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// NOTE TO PROGRAMMERS: this JS_INIT script does not, and must not be invoked with strict mode //
///////////////////////////////////////////////////////////////////////////////////////////////////
// disabling and re-installing JS/Nashorn functions
// alse see: https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions
load = undefined;
loadWithNewGlobal = undefined;
exit = undefined;
quit = undefined;
printErr = undefined;
readbuffer = undefined;
readline = undefined;
/*var eval = function(s) { // this impl is flawed; it does not return any, and cannot alter Global which may not you actually want
return Function('"use strict";return(function(){'+s+'}())')();
}*/
//
function javaArrayToJs(jarr) {
if (!jarr.toString.startsWith("[")) return jarr;
var arr = [];
for (var k = 0; k < jarr.length; k++) {
arr.push(jarr[k]);
}
return arr;
}
// standard print functions
function print(s) {
sys.print(s);
}
function println(s) {
if (s === undefined)
sys.print("\n");
else
sys.println(s);
}
function printerr(s) {
print("\x1B[31m"+s+"\x1B[m");
}
function printerrln(s) {
println("\x1B[31m"+s+"\x1B[m");
}
function read() {
return sys.read();
}
String.prototype.trimNull = function() {
let cnt = this.length - 1
while (cnt >= 0) {
if (this.charCodeAt(cnt) != 0) break;
cnt -= 1;
}
return this.slice(0, cnt + 1);
}
// ncurses-like terminal control
var con = {};
con.KEY_HOME = 199;
con.KEY_UP = 200;
con.KEY_PAGE_UP = 201;
con.KEY_LEFT = 203;
con.KEY_RIGHT = 205;
con.KEY_END = 207;
con.KEY_DOWN = 208
con.KEY_PAGE_DOWN = 209;
con.KEY_INSERT = 210;
con.KEY_DELETE = 211;
con.KEY_BACKSPACE = 8;
con.KEY_TAB = 9;
con.KEY_RETURN = 10;
con.getch = function() {
return sys.readKey();
};
con.move = function(y, x) {
print("\x1B["+(y|0)+";"+(x|0)+"H");
};
con.addch = function(c) {
graphics.putSymbol(c|0);
};
con.mvaddch = function(y, x, c) {
con.move(y, x); con.addch(c);
};
con.getmaxyx = function() {
return graphics.getTermDimension();
};
con.getyx = function() {
return graphics.getCursorYX();
};
con.curs_up = function() {
let c = graphics.getCursorYX();
con.move(c[0]-1,c[1]);
};
con.curs_down = function() {
let c = graphics.getCursorYX();
con.move(c[0]+1,c[1]);
};
con.curs_left = function() {
let c = graphics.getCursorYX();
con.move(c[0],c[1]-1);
};
con.curs_right = function() {
let c = graphics.getCursorYX();
con.move(c[0],c[1]+1);
};
con.hitterminate = function() { // ^C
sys.poke(-40, 1);
return (sys.peek(-41) == 31 && (sys.peek(-42) == 129 || sys.peek(-42) == 130));
};
con.hiteof = function() { // ^D
sys.poke(-40, 1);
return (sys.peek(-41) == 32 && (sys.peek(-42) == 129 || sys.peek(-42) == 130));
};
con.resetkeybuf = function() {
sys.poke(-40, 0);
sys.poke(-41, 0); sys.poke(-42, 0); sys.poke(-43, 0); sys.poke(-44, 0);
sys.poke(-45, 0); sys.poke(-46, 0); sys.poke(-47, 0); sys.poke(-48, 0);
};
con.video_reverse = function() {
print("\x1B[7m");
};
con.color_fore = function(n) { // 0..7; -1 for transparent
if (n < 0)
print("\x1B[38;5;255m");
else
print("\x1B["+(((n|0) % 8)+30)+"m");
};
con.color_back = function(n) { // 0..7; -1 for transparent
if (n < 0)
print("\x1B[48;5;255m");
else
print("\x1B["+(((n|0) % 8)+40)+"m");
};
con.color_pair = function(fore, back) { // 0..255
print("\x1B[38;5;"+fore+"m");
print("\x1B[48;5;"+back+"m");
};
con.clear = function() {
print("\x1B[2J");
};
// @params arg 0 to hide, nonzero to show
con.curs_set = function(arg) {
print("\x1B[?25"+(((arg|0) == 0) ? "l" : "h"));
};
con.reset_graphics = function() {
print("\x1B[m");
};
// returns current key-down status
con.poll_keys = function() {
sys.poke(-40, 1);
return [-41,-42,-43,-44,-45,-46,-47,-48].map(it => sys.peek(it));
};
Object.freeze(con);
// system management function
var system = {};
system.maxmem = function() {
return sys.peek(-65) | (sys.peek(-66) << 8) | (sys.peek(-67) << 16) | (sys.peek(-68) << 24);
};
Object.freeze(system);
// some utilities functions
if (Graal !== undefined && !Graal.isGraalRuntime()) {
serial.printerr("GraalVM compiler is not running, expect low performance");
}

View File

@@ -2,7 +2,7 @@
20 s=cput(1,"POLL") 20 s=cput(1,"POLL")
30 if s><0 then goto 900 30 if s><0 then goto 900
40 l=cget(1,0) 40 l=cget(1,0)
41 REM print("length: "+l+", pixels: "+l/3) 41 print("length: "+l+", pixels: "+l/3)
50 for i=0 to l-1 step 3 50 for i=0 to l-1 step 3
60 m=peek(i)*160+peek(i+1) 60 m=peek(i)*160+peek(i+1)
62 p=peek(i+2) 62 p=peek(i+2)

View File

@@ -0,0 +1,5 @@
10 print("Polling...")
50 for i=0 to 160*140-1
63 poke(-1048576-i,int(rnd(1)*16))
70 next
80 goto 10

Binary file not shown.

Binary file not shown.

BIN
lib/annotations-13.0.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/kotlin-stdlib-1.4.0.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -168,15 +168,17 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
private var uiFixture: UICanvas? = null private var uiFixture: UICanvas? = null
set(value) { set(value) {
printdbg(this, "uiFixture change: $uiFixture -> $value") printdbg(this, "uiFixture change: $uiFixture -> $value")
field?.let { it.setAsClose() } field?.setAsClose()
value?.let { uiFixturesHistory.add(it) } value?.let { uiFixturesHistory.add(it) }
field = value field = value
} }
var wearableDeviceUI: UICanvas? = null var wearableDeviceUI: UICanvas? = null
set(value) { set(value) {
field?.setAsClose()
value?.setAsOpen()
value?.setPosition(App.scr.tvSafeGraphicsWidth/2, App.scr.tvSafeActionHeight/2)
field = value field = value
value?.setPosition(100, 100) // TODO
} }
val getUIFixture = object : Id_UICanvasNullable { // quick workaround for the type erasure (you can't use lambda...) val getUIFixture = object : Id_UICanvasNullable { // quick workaround for the type erasure (you can't use lambda...)

View File

@@ -22,5 +22,6 @@
<orderEntry type="library" name="jxinput-1.0.0" level="project" /> <orderEntry type="library" name="jxinput-1.0.0" level="project" />
<orderEntry type="library" name="gdx-platform-1.10.0-natives-desktop" level="project" /> <orderEntry type="library" name="gdx-platform-1.10.0-natives-desktop" level="project" />
<orderEntry type="library" name="graalvm-js-21.1.0 and graalvm-js-scriptengine-21.1.0" level="project" /> <orderEntry type="library" name="graalvm-js-21.1.0 and graalvm-js-scriptengine-21.1.0" level="project" />
<orderEntry type="library" name="jetbrains.kotlinx.coroutines.core" level="project" />
</component> </component>
</module> </module>