add globals, constants, and helpers
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "hack.h"
|
||||
#include "dlb.h"
|
||||
#include "date.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -559,6 +560,7 @@ void
|
||||
sethanguphandler(handler)
|
||||
void FDECL((*handler), (int));
|
||||
{
|
||||
#ifndef NO_SIGNAL
|
||||
#ifdef SA_RESTART
|
||||
/* don't want reads to restart. If SA_RESTART is defined, we know
|
||||
* sigaction exists and can be used to ensure reads won't restart.
|
||||
@@ -580,6 +582,7 @@ void FDECL((*handler), (int));
|
||||
(void) signal(SIGXCPU, (SIG_RET_TYPE) handler);
|
||||
#endif
|
||||
#endif /* ?SA_RESTART */
|
||||
#endif /* !NO_SIGNAL */
|
||||
}
|
||||
|
||||
#ifdef PORT_HELP
|
||||
@@ -767,6 +770,8 @@ EM_JS(void, js_helpers_init, (), {
|
||||
|
||||
installHelper(mapglyphHelper);
|
||||
installHelper(displayInventory);
|
||||
installHelper(getPointerValue);
|
||||
installHelper(setPointerValue);
|
||||
|
||||
// used by print_glyph
|
||||
function mapglyphHelper(glyph, x, y, mgflags) {
|
||||
@@ -802,6 +807,83 @@ EM_JS(void, js_helpers_init, (), {
|
||||
// });
|
||||
}
|
||||
|
||||
// convert 'ptr' to the type indicated by 'type'
|
||||
function getPointerValue(name, ptr, type) {
|
||||
// console.log("getPointerValue", name, "0x" + ptr.toString(16), type);
|
||||
switch(type) {
|
||||
case "s": // string
|
||||
// var value = UTF8ToString(getValue(ptr, "*"));
|
||||
return UTF8ToString(ptr);
|
||||
case "p": // pointer
|
||||
if(!ptr) return 0; // null pointer
|
||||
return getValue(ptr, "*");
|
||||
case "c": // char
|
||||
return String.fromCharCode(getValue(ptr, "i8"));
|
||||
case "0": /* 2^0 = 1 byte */
|
||||
return getValue(ptr, "i8");
|
||||
case "1": /* 2^1 = 2 bytes */
|
||||
return getValue(ptr, "i16");
|
||||
case "2": /* 2^2 = 4 bytes */
|
||||
case "i": // integer
|
||||
case "n": // number
|
||||
return getValue(ptr, "i32");
|
||||
case "f": // float
|
||||
return getValue(ptr, "float");
|
||||
case "d": // double
|
||||
return getValue(ptr, "double");
|
||||
case "o": // overloaded: multiple types
|
||||
return ptr;
|
||||
default:
|
||||
throw new TypeError ("unknown type:" + type);
|
||||
}
|
||||
}
|
||||
|
||||
// sets the return value of the function to the type expected
|
||||
function setPointerValue(name, ptr, type, value = 0) {
|
||||
// console.log("setPointerValue", name, "0x" + ptr.toString(16), type, value);
|
||||
switch (type) {
|
||||
case "p":
|
||||
throw new Error("not implemented");
|
||||
case "s":
|
||||
if(typeof value !== "string")
|
||||
throw new TypeError(`expected ${name} return type to be string`);
|
||||
// value=value?value:"(no value)";
|
||||
// var strPtr = getValue(ptr, "i32");
|
||||
stringToUTF8(value, ptr, 1024); // TODO: uhh... danger will robinson
|
||||
break;
|
||||
case "i":
|
||||
if(typeof value !== "number" || !Number.isInteger(value))
|
||||
throw new TypeError(`expected ${name} return type to be integer`);
|
||||
setValue(ptr, value, "i32");
|
||||
break;
|
||||
case "c":
|
||||
if(typeof value !== "number" || value < 0 || value > 128)
|
||||
throw new TypeError(`expected ${name} return type to be integer representing an ASCII character`);
|
||||
setValue(ptr, value, "i8");
|
||||
break;
|
||||
case "f":
|
||||
if(typeof value !== "number" || isFloat(value))
|
||||
throw new TypeError(`expected ${name} return type to be float`);
|
||||
// XXX: I'm not sure why 'double' works and 'float' doesn't
|
||||
setValue(ptr, value, "double");
|
||||
break;
|
||||
case "d":
|
||||
if(typeof value !== "number" || isFloat(value))
|
||||
throw new TypeError(`expected ${name} return type to be double`);
|
||||
setValue(ptr, value, "double");
|
||||
break;
|
||||
case "v":
|
||||
break;
|
||||
default:
|
||||
throw new Error("unknown type");
|
||||
}
|
||||
|
||||
function isFloat(n){
|
||||
return n === +n && n !== (n|0) && !Number.isInteger(n);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function installHelper(fn, name) {
|
||||
name = name || fn.name;
|
||||
globalThis.nethackGlobal.helpers[name] = fn;
|
||||
@@ -815,10 +897,20 @@ EM_JS(void, js_helpers_init, (), {
|
||||
EM_JS(void, set_const, (char *scope_str, char *name_str, int num), {
|
||||
let scope = UTF8ToString(scope_str);
|
||||
let name = UTF8ToString(name_str);
|
||||
|
||||
globalThis.nethackGlobal.constants[scope] = globalThis.nethackGlobal.constants[scope] || {};
|
||||
globalThis.nethackGlobal.constants[scope][name] = num;
|
||||
globalThis.nethackGlobal.constants[scope][num] = name;
|
||||
});
|
||||
#define SET_CONSTANT_STRING(scope, name) set_const_str(scope, #name, name);
|
||||
EM_JS(void, set_const_str, (char *scope_str, char *name_str, char *input_str), {
|
||||
let scope = UTF8ToString(scope_str);
|
||||
let name = UTF8ToString(name_str);
|
||||
let str = UTF8ToString(input_str);
|
||||
|
||||
globalThis.nethackGlobal.constants[scope] = globalThis.nethackGlobal.constants[scope] || {};
|
||||
globalThis.nethackGlobal.constants[scope][name] = str;
|
||||
});
|
||||
|
||||
void js_constants_init() {
|
||||
EM_ASM({
|
||||
@@ -861,22 +953,175 @@ void js_constants_init() {
|
||||
SET_CONSTANT("STATUS_FIELD", BL_EXP)
|
||||
SET_CONSTANT("STATUS_FIELD", BL_CONDITION)
|
||||
SET_CONSTANT("STATUS_FIELD", MAXBLSTATS)
|
||||
|
||||
// text attributes
|
||||
SET_CONSTANT("ATTR", ATR_NONE);
|
||||
SET_CONSTANT("ATTR", ATR_BOLD);
|
||||
SET_CONSTANT("ATTR", ATR_DIM);
|
||||
SET_CONSTANT("ATTR", ATR_ULINE);
|
||||
SET_CONSTANT("ATTR", ATR_BLINK);
|
||||
SET_CONSTANT("ATTR", ATR_INVERSE);
|
||||
SET_CONSTANT("ATTR", ATR_URGENT);
|
||||
SET_CONSTANT("ATTR", ATR_NOHISTORY);
|
||||
|
||||
// conditions
|
||||
SET_CONSTANT("CONDITION", BL_MASK_BAREH);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_BLIND);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_BUSY);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_CONF);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_DEAF);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_ELF_IRON);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_FLY);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_FOODPOIS);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_GLOWHANDS);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_GRAB);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_HALLU);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_HELD);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_ICY);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_INLAVA);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_LEV);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_PARLYZ);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_RIDE);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_SLEEPING);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_SLIME);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_SLIPPERY);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_STONE);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_STRNGL);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_STUN);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_SUBMERGED);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_TERMILL);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_TETHERED);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_TRAPPED);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_UNCONSC);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_WOUNDEDL);
|
||||
SET_CONSTANT("CONDITION", BL_MASK_HOLDING);
|
||||
|
||||
// menu
|
||||
SET_CONSTANT("MENU_SELECT", PICK_NONE);
|
||||
SET_CONSTANT("MENU_SELECT", PICK_ONE);
|
||||
SET_CONSTANT("MENU_SELECT", PICK_ANY);
|
||||
|
||||
// copyright
|
||||
SET_CONSTANT_STRING("COPYRIGHT", COPYRIGHT_BANNER_A);
|
||||
SET_CONSTANT_STRING("COPYRIGHT", COPYRIGHT_BANNER_B);
|
||||
SET_CONSTANT_STRING("COPYRIGHT", COPYRIGHT_BANNER_C);
|
||||
SET_CONSTANT_STRING("COPYRIGHT", COPYRIGHT_BANNER_D);
|
||||
|
||||
// glyphs
|
||||
SET_CONSTANT("GLYPH", GLYPH_MON_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_PET_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_INVIS_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_DETECT_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_BODY_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_RIDDEN_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_OBJ_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_CMAP_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_EXPLODE_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_ZAP_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_SWALLOW_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_WARNING_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_STATUE_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_UNEXPLORED_OFF);
|
||||
SET_CONSTANT("GLYPH", GLYPH_NOTHING_OFF);
|
||||
SET_CONSTANT("GLYPH", MAX_GLYPH);
|
||||
SET_CONSTANT("GLYPH", NO_GLYPH);
|
||||
SET_CONSTANT("GLYPH", GLYPH_INVISIBLE);
|
||||
SET_CONSTANT("GLYPH", GLYPH_UNEXPLORED);
|
||||
SET_CONSTANT("GLYPH", GLYPH_NOTHING);
|
||||
|
||||
// colors
|
||||
SET_CONSTANT("COLORS", CLR_BLACK);
|
||||
SET_CONSTANT("COLORS", CLR_RED);
|
||||
SET_CONSTANT("COLORS", CLR_GREEN);
|
||||
SET_CONSTANT("COLORS", CLR_BROWN);
|
||||
SET_CONSTANT("COLORS", CLR_BLUE);
|
||||
SET_CONSTANT("COLORS", CLR_MAGENTA);
|
||||
SET_CONSTANT("COLORS", CLR_CYAN);
|
||||
SET_CONSTANT("COLORS", CLR_GRAY);
|
||||
SET_CONSTANT("COLORS", NO_COLOR);
|
||||
SET_CONSTANT("COLORS", CLR_ORANGE);
|
||||
SET_CONSTANT("COLORS", CLR_BRIGHT_GREEN);
|
||||
SET_CONSTANT("COLORS", CLR_YELLOW);
|
||||
SET_CONSTANT("COLORS", CLR_BRIGHT_BLUE);
|
||||
SET_CONSTANT("COLORS", CLR_BRIGHT_MAGENTA);
|
||||
SET_CONSTANT("COLORS", CLR_BRIGHT_CYAN);
|
||||
SET_CONSTANT("COLORS", CLR_WHITE);
|
||||
SET_CONSTANT("COLORS", CLR_MAX);
|
||||
|
||||
// color attributes (?)
|
||||
SET_CONSTANT("COLOR_ATTR", HL_ATTCLR_DIM);
|
||||
SET_CONSTANT("COLOR_ATTR", HL_ATTCLR_BLINK);
|
||||
SET_CONSTANT("COLOR_ATTR", HL_ATTCLR_ULINE);
|
||||
SET_CONSTANT("COLOR_ATTR", HL_ATTCLR_INVERSE);
|
||||
SET_CONSTANT("COLOR_ATTR", HL_ATTCLR_BOLD);
|
||||
SET_CONSTANT("COLOR_ATTR", BL_ATTCLR_MAX);
|
||||
}
|
||||
|
||||
/***
|
||||
* Globals
|
||||
***/
|
||||
#define CREATE_GLOBAL(var, type) create_global(#var, (void *)&var, type);
|
||||
#define CREATE_GLOBAL_FROM_ARRAY(base, iter, path, end_expr, type) \
|
||||
for(iter = 0; end_expr; iter++) { \
|
||||
snprintf(buf, BUFSZ, #base ".%d." #path, iter); \
|
||||
create_global(buf, (void *)(&(base[iter].path)), type); \
|
||||
}
|
||||
|
||||
void create_global (char *name, void *ptr, char *type);
|
||||
|
||||
void js_globals_init() {
|
||||
// printf("js_globals_init\n");
|
||||
// int i;
|
||||
// char buf[BUFSZ];
|
||||
printf("js_globals_init\n");
|
||||
|
||||
// player name
|
||||
// g.plname
|
||||
EM_ASM({
|
||||
globalThis.nethackGlobal = globalThis.nethackGlobal || {};
|
||||
globalThis.nethackGlobal.globals = globalThis.nethackGlobal.globals || {};
|
||||
});
|
||||
|
||||
// bottom line stats
|
||||
// g.blstats
|
||||
// g.now_or_before_idx
|
||||
/* globals */
|
||||
CREATE_GLOBAL(g.plname, "s");
|
||||
|
||||
/* window globals */
|
||||
CREATE_GLOBAL(WIN_MAP, "i");
|
||||
CREATE_GLOBAL(WIN_MESSAGE, "i");
|
||||
CREATE_GLOBAL(WIN_INVEN, "i");
|
||||
CREATE_GLOBAL(WIN_STATUS, "i");
|
||||
}
|
||||
|
||||
EM_JS(void, create_global, (char *name_str, void *ptr, char *type_str), {
|
||||
let name = UTF8ToString(name_str);
|
||||
let type = UTF8ToString(type_str);
|
||||
|
||||
// get helpers
|
||||
let getPointerValue = globalThis.nethackGlobal.helpers.getPointerValue;
|
||||
let setPointerValue = globalThis.nethackGlobal.helpers.setPointerValue;
|
||||
|
||||
let { obj, prop } = createPath(globalThis.nethackGlobal.globals, name);
|
||||
|
||||
// setters / getters with bound pointers
|
||||
Object.defineProperty(obj, prop, {
|
||||
get: getPointerValue.bind(null, name, ptr, type),
|
||||
set: setPointerValue.bind(null, name, ptr, type),
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
function createPath(obj, path) {
|
||||
path = path.split(".");
|
||||
let i;
|
||||
for (i = 0; i < path.length - 1; i++) {
|
||||
// obj[path[i]] = obj[path[i]] || {};
|
||||
if (obj[path[i]] === undefined) {
|
||||
obj[path[i]] = {};
|
||||
}
|
||||
obj = obj[path[i]];
|
||||
}
|
||||
|
||||
return { obj, prop: path[i] };
|
||||
}
|
||||
})
|
||||
|
||||
#endif
|
||||
|
||||
/*libnethack.c*/
|
||||
|
||||
Reference in New Issue
Block a user