fix resource loading
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
var render = use('render')
|
||||
var debug = os.use('debug')
|
||||
var debug = this
|
||||
var util = use('util')
|
||||
|
||||
debug.build = function (fn) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var Color = use('color')
|
||||
var os = use('os')
|
||||
|
||||
var ex = {}
|
||||
|
||||
@@ -112,4 +113,5 @@ this.dead = []
|
||||
|
||||
this.transform = this.overling.transform
|
||||
|
||||
|
||||
$.emitters.add(this)
|
||||
|
||||
@@ -1,162 +1,11 @@
|
||||
globalThis.prosperon = {}
|
||||
var io = os.use('io')
|
||||
|
||||
os.mem_limit.doc = "Set the memory limit of the runtime in bytes.";
|
||||
os.gc_threshold.doc = "Set the threshold before a GC pass is triggered in bytes. This is set to malloc_size + malloc_size>>1 after a GC pass.";
|
||||
os.max_stacksize.doc = "Set the max stack size in bytes.";
|
||||
|
||||
globalThis.Resources = {};
|
||||
var os = use_embed('os')
|
||||
|
||||
prosperon.SIGINT = function() {
|
||||
os.exit();
|
||||
}
|
||||
|
||||
Resources.rm_fn = function rm_fn(fn, text) {
|
||||
var reg = new RegExp(fn.source + "\\s*\\(");
|
||||
var match;
|
||||
while ((match = text.match(reg))) {
|
||||
var last = match.index + match[0].length;
|
||||
var par = 1;
|
||||
while (par !== 0) {
|
||||
if (text[last] === "(") par++;
|
||||
if (text[last] === ")") par--;
|
||||
last++;
|
||||
}
|
||||
text = text.rm(match.index, last);
|
||||
}
|
||||
|
||||
return text;
|
||||
};
|
||||
Resources.rm_fn.doc = "Remove calls to a given function from a given text script.";
|
||||
|
||||
// Normalizes paths for use in prosperon
|
||||
Resources.replpath = function replpath(str, path) {
|
||||
if (!str) return str;
|
||||
if (str[0] === "/") return str.rm(0);
|
||||
|
||||
if (!path) return str;
|
||||
|
||||
var stem = path.dir();
|
||||
while (stem) {
|
||||
var tr = stem + "/" + str;
|
||||
if (io.exists(tr)) return tr;
|
||||
stem = stem.updir();
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
||||
// Given a script path, loads it, and replaces certain function calls to conform to environment
|
||||
Resources.replstrs = function replstrs(path) {
|
||||
if (!path) return;
|
||||
var script = io.slurp(path);
|
||||
if (!script) return;
|
||||
var regexp = /"[^"\s]*?\.[^"\s]+?"/g;
|
||||
|
||||
var stem = path.dir();
|
||||
|
||||
// if (!console.enabled) script = Resources.rm_fn(/console\.(spam|info|warn|error)/, script);
|
||||
/* if (!profile.enabled) script = Resources.rm_fn(/profile\.(cache|frame|endcache|endframe)/, script);
|
||||
|
||||
if (!debug.enabled) {
|
||||
script = Resources.rm_fn(/assert/, script);
|
||||
script = Resources.rm_fn(/debug\.(build|fn_break)/, script);
|
||||
}
|
||||
*/
|
||||
script = script.replace(regexp, function (str) {
|
||||
var newstr = Resources.replpath(os.trimchr(str,'"'), path);
|
||||
return `"${newstr}"`;
|
||||
});
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
Resources.is_sound = function (path) {
|
||||
var ext = path.ext();
|
||||
return Resources.sounds.any(x => x === ext);
|
||||
};
|
||||
|
||||
Resources.is_animation = function (path) {
|
||||
if (path.ext() === "gif" && Resources.gif.frames(path) > 1) return true;
|
||||
if (path.ext() === "ase") return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
Resources.is_path = function (str) {
|
||||
return !/[\\\/:*?"<>|]/.test(str);
|
||||
};
|
||||
|
||||
globalThis.json = {};
|
||||
json.encode = function json_encode(value, replacer, space = 1) {
|
||||
return JSON.stringify(value, replacer, space);
|
||||
};
|
||||
|
||||
json.decode = function json_decode(text, reviver) {
|
||||
if (!text) return undefined;
|
||||
return JSON.parse(text, reviver);
|
||||
};
|
||||
|
||||
json.readout = function (obj) {
|
||||
var j = {};
|
||||
for (var k in obj)
|
||||
if (typeof obj[k] === "function") j[k] = "function " + obj[k].toString();
|
||||
else j[k] = obj[k];
|
||||
|
||||
return json.encode(j);
|
||||
};
|
||||
|
||||
json.doc = {
|
||||
doc: "json implementation.",
|
||||
encode: "Encode a value to json.",
|
||||
decode: "Decode a json string to a value.",
|
||||
readout: "Encode an object fully, including function definitions.",
|
||||
};
|
||||
|
||||
Resources.scripts = ["jsoc", "jsc", "jso", "js"];
|
||||
Resources.images = ["qoi", "png", "gif", "jpg", "jpeg", "ase", "aseprite"];
|
||||
Resources.sounds = ["wav", "flac", "mp3", "qoa"];
|
||||
Resources.fonts = ["ttf"];
|
||||
Resources.is_image = function (path) {
|
||||
var ext = path.ext();
|
||||
return Resources.images.some(x => x === ext);
|
||||
};
|
||||
|
||||
Resources.shaders = ["hlsl", "glsl", "cg"]
|
||||
Resources.is_shader = function(path) {
|
||||
var ext = path.ext();
|
||||
return Resources.shaders.some(x => x === ext)
|
||||
}
|
||||
|
||||
var res_cache = {};
|
||||
|
||||
// ext is a list of extensions to search
|
||||
function find_ext(file, ext) {
|
||||
if (!file) return;
|
||||
|
||||
var file_ext = file.ext();
|
||||
var has_ext = file_ext.length > 0;
|
||||
|
||||
for (var e of ext) {
|
||||
var nf = `${file}.${e}`;
|
||||
if (io.exists(nf)) return nf;
|
||||
}
|
||||
|
||||
var glob_pat = has_ext ? `**/${file}` : `**/${file}.*`;
|
||||
|
||||
var all_files = io.glob(glob_pat);
|
||||
var find = undefined;
|
||||
for (var e of ext) {
|
||||
var finds = all_files.filter(x => x.ext() === e);
|
||||
if (finds.length > 1) {
|
||||
console.warn(`Found conflicting files when searching for '${file}': ${json.encode(finds)}. Returning the topmost one.`);
|
||||
finds.sort((a,b) => a.length-b.length);
|
||||
return finds[0];
|
||||
}
|
||||
if (finds.length === 1) return finds[0];
|
||||
}
|
||||
|
||||
return find;
|
||||
}
|
||||
var use_cache = {}
|
||||
|
||||
Object.defineProperty(Function.prototype, "hashify", {
|
||||
value: function () {
|
||||
@@ -172,74 +21,72 @@ Object.defineProperty(Function.prototype, "hashify", {
|
||||
},
|
||||
});
|
||||
|
||||
Resources.find_image = function (file, root = "") {
|
||||
return find_ext(file, Resources.images, root);
|
||||
var io = use_embed('io')
|
||||
io.mount(io.basedir() + "core/scripts/")
|
||||
io.mount(io.basedir() + "core/")
|
||||
|
||||
var canonical = io.realdir('resources.js') + 'resources.js'
|
||||
var content = io.slurp('resources.js')
|
||||
var resources = os.eval('resources.js', `(function setup_resources(){${content}})`).call({})
|
||||
console.print(resources.canonical('resources.js'))
|
||||
use_cache[resources.canonical('resources.js')] = resources
|
||||
|
||||
// path is the path of a module or script to resolve
|
||||
var script_fn = function script_fn(path) {
|
||||
var parsed = {}
|
||||
var file = resources.find_script(path);
|
||||
if (!file) {
|
||||
// attempt to bare load
|
||||
parsed.module_ret = bare_load(path);
|
||||
|
||||
if (!parsed.module_ret) throw new Error(`Module ${path} could not be created`)
|
||||
return parsed
|
||||
}
|
||||
var content = io.slurp(file)
|
||||
var parsed = parse_file(content);
|
||||
var module_name = file.name();
|
||||
|
||||
parsed.module_ret = bare_load(path)
|
||||
parsed.module_ret ??= {}
|
||||
|
||||
if (parsed.module) {
|
||||
var mod_script = `(function setup_${module_name}_module(){ var self = this; var $ = this; var exports = {}; var module = {exports: exports}; var define = undefined; ${parsed.module}})`;
|
||||
var module_fn = os.eval(file, mod_script);
|
||||
parsed.module_ret = module_fn.call(parsed.module_ret);
|
||||
if (parsed.module_ret === undefined || parsed.module_ret === null)
|
||||
throw new Error(`Module ${module_name} must return a value`);
|
||||
parsed.module_fn = module_fn;
|
||||
}
|
||||
|
||||
if (parsed.program) {
|
||||
var prog_script = `(function use_${module_name}() { var self = this; var $ = this.__proto__; ${parsed.program}})`;
|
||||
parsed.prog_fn = os.eval(file, prog_script);
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}.hashify();
|
||||
|
||||
Resources.find_sound = function (file, root = "") {
|
||||
return find_ext(file, Resources.sounds, root);
|
||||
}.hashify();
|
||||
|
||||
Resources.find_script = function (file, root = "") {
|
||||
return find_ext(file, Resources.scripts, root);
|
||||
}.hashify();
|
||||
|
||||
Resources.find_font = function(file, root = "") {
|
||||
return find_ext(file, Resources.fonts, root);
|
||||
}.hashify();
|
||||
|
||||
var tmpslurp = io.slurp;
|
||||
io.slurp = function slurp(path)
|
||||
{
|
||||
var findpath = Resources.replpath(path);
|
||||
var ret = tmpslurp(findpath, true); //|| core_db.slurp(findpath, true);
|
||||
return ret;
|
||||
function bare_load(file) {
|
||||
try {
|
||||
return use_embed(file)
|
||||
} catch (e) { }
|
||||
try {
|
||||
return use_dyn(file + so_ext)
|
||||
} catch(e) { }
|
||||
return undefined
|
||||
}
|
||||
|
||||
io.slurpbytes = function(path)
|
||||
{
|
||||
path = Resources.replpath(path);
|
||||
var ret = tmpslurp(path);// || core_db.slurp(path);
|
||||
if (!ret) throw new Error(`Could not find file ${path} anywhere`);
|
||||
return ret;
|
||||
}
|
||||
var res_cache = {};
|
||||
|
||||
var ignore = io.slurp('.prosperonignore').split('\n');
|
||||
var allpaths;
|
||||
io.glob = function glob(pat) {
|
||||
if (!allpaths)
|
||||
allpaths = io.globfs(ignore);
|
||||
|
||||
return allpaths.filter(str => io.match(pat,str)).sort();
|
||||
}
|
||||
|
||||
io.invalidate = function()
|
||||
{
|
||||
allpaths = undefined;
|
||||
}
|
||||
|
||||
|
||||
console.transcript = "";
|
||||
console.say = function (msg) {
|
||||
console.print(msg);
|
||||
if (debug.termout) console.term_print(msg);
|
||||
console.transcript += msg;
|
||||
};
|
||||
|
||||
console.rec = function(category, priority, line, file, msg)
|
||||
function console_rec(category, priority, line, file, msg)
|
||||
{
|
||||
return `${file}:${line}: [${category} ${priority}]: ${msg}` + "\n";
|
||||
}
|
||||
|
||||
|
||||
|
||||
var logfile = io.open('.prosperon/log.txt')
|
||||
//logfile.buffer(1024*1024) // 1MB buffer
|
||||
|
||||
console.stdout_lvl = 0;
|
||||
|
||||
function pprint(msg, lvl = 0) {
|
||||
if (lvl < console.stdout_lvl && !logfile) return;
|
||||
if (!logfile) return;
|
||||
|
||||
if (typeof msg === "object") msg = JSON.stringify(msg, null, 2);
|
||||
|
||||
@@ -255,10 +102,9 @@ function pprint(msg, lvl = 0) {
|
||||
m = md ? md[1] : 0;
|
||||
if (m) line = m;
|
||||
}
|
||||
var fmt = console.rec("script", lvl, line,file, msg);
|
||||
var fmt = console_rec("script", lvl, line,file, msg);
|
||||
|
||||
if (lvl >= console.stdout_lvl)
|
||||
console.print(fmt)
|
||||
console.print(fmt)
|
||||
|
||||
if (logfile)
|
||||
logfile.write(fmt)
|
||||
@@ -284,8 +130,9 @@ console.log = function(msg)
|
||||
pprint(msg, 2)
|
||||
}
|
||||
|
||||
console.log(io.searchpath())
|
||||
|
||||
console.error = function(e) {
|
||||
console.print(e.message)
|
||||
if (!e)
|
||||
e = new Error();
|
||||
|
||||
@@ -294,7 +141,7 @@ ${e.stack}`, 4)
|
||||
};
|
||||
|
||||
console.panic = function (e) {
|
||||
console.pprint(e , 5)
|
||||
pprint(e , 5)
|
||||
os.quit();
|
||||
};
|
||||
|
||||
@@ -336,7 +183,7 @@ prosperon.SIGSEGV = function()
|
||||
|
||||
function add_timer(obj, fn, seconds)
|
||||
{
|
||||
var timers = obj.timers;
|
||||
var timers = obj[TIMERS]
|
||||
|
||||
var stop = function () {
|
||||
if (!timer) return
|
||||
@@ -366,6 +213,14 @@ function add_timer(obj, fn, seconds)
|
||||
return stop;
|
||||
}
|
||||
|
||||
var DEAD = Symbol()
|
||||
var GARBAGE = Symbol()
|
||||
var FILE = Symbol()
|
||||
var TIMERS = Symbol()
|
||||
var REGGIES = Symbol()
|
||||
var UNDERLINGS = Symbol()
|
||||
var OVERLING = Symbol()
|
||||
|
||||
var actor = {};
|
||||
|
||||
var so_ext;
|
||||
@@ -378,101 +233,18 @@ switch(os.sys()) {
|
||||
break;
|
||||
}
|
||||
|
||||
var use_cache = {}
|
||||
|
||||
function load_mod(file)
|
||||
{
|
||||
try {
|
||||
var par = script_fn(file)
|
||||
if (par?.module_ret) {
|
||||
use_cache[file] = par.module_
|
||||
return par.module_ret
|
||||
}
|
||||
} catch(e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
try {
|
||||
return os.use('./lib' + file + so_ext)
|
||||
} catch(e) { console.error(e) }
|
||||
|
||||
return os.use(file)
|
||||
}
|
||||
|
||||
var use = function use(file) {
|
||||
|
||||
if (use_cache[file]) return use_cache[file];
|
||||
|
||||
use_cache[file] = load_mod(file)
|
||||
var mod = script_fn(file)
|
||||
|
||||
use_cache[file] = mod.module_ret
|
||||
return use_cache[file]
|
||||
}
|
||||
|
||||
use.hotreload = function(file)
|
||||
{
|
||||
console.log(`hot reloading ${file}`)
|
||||
var oldval = use_cache[file]
|
||||
var newval = load_mod(file)
|
||||
if (!oldval) {
|
||||
use_cache[file] = newval;
|
||||
return newval;
|
||||
}
|
||||
|
||||
if (typeof oldval !== 'object' || typeof newval !== 'object' || !oldval || !newval) {
|
||||
use_cache[file] = newval;
|
||||
return newval;
|
||||
}
|
||||
|
||||
use_patch(oldval, newval);
|
||||
return oldval;
|
||||
}
|
||||
|
||||
function use_patch(target, source)
|
||||
{
|
||||
// First remove properties that aren’t in source at all
|
||||
for (let key of Object.keys(target)) {
|
||||
if (!(key in source)) {
|
||||
delete target[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Then shallow-copy the source’s own properties
|
||||
for (let key of Object.keys(source)) {
|
||||
target[key] = source[key];
|
||||
}
|
||||
|
||||
// Update the prototype if needed so that new or changed methods come along
|
||||
let oldProto = Object.getPrototypeOf(target);
|
||||
let newProto = Object.getPrototypeOf(source);
|
||||
if (oldProto !== newProto) {
|
||||
Object.setPrototypeOf(target, newProto);
|
||||
}
|
||||
}
|
||||
|
||||
var script_fn = function script_fn(path) {
|
||||
var file = Resources.find_script(path)
|
||||
if (!file) throw new Error(`File ${path} could not be found`)
|
||||
var content = Resources.replstrs(file);
|
||||
var parsed = parse_file(content)
|
||||
var module_name = file.name()
|
||||
|
||||
if (parsed.module) {
|
||||
var mod_script = `(function setup_${module_name}_module(){ var self = this; var $ = this; var exports = {}; var module = {exports:exports}; var define = undefined; ${parsed.module}})`;
|
||||
var module_fn = os.eval(file, mod_script)
|
||||
var module_ret = module_fn.call();
|
||||
if (module_ret === undefined || module_ret === null)
|
||||
throw new Error(`Module ${module_name} must return a value`);
|
||||
|
||||
parsed.module_fn = module_fn;
|
||||
parsed.module_ret = module_ret;
|
||||
} else
|
||||
parsed.module_ret = {}
|
||||
|
||||
if (parsed.program) {
|
||||
var prog_script = `(function use_${module_name}() { var self = this; var $ = this.__proto__; ${parsed.program}})`;
|
||||
parsed.prog_fn = os.eval(file, prog_script);
|
||||
}
|
||||
|
||||
return parsed;
|
||||
}.hashify()
|
||||
globalThis.json = use('json')
|
||||
|
||||
function parse_file(content) {
|
||||
if (!content) return {}
|
||||
@@ -494,68 +266,6 @@ function parse_file(content) {
|
||||
}
|
||||
}
|
||||
|
||||
actor.__stats = function () {
|
||||
var total = 0;
|
||||
var stats = {};
|
||||
search.all_objects(obj => {
|
||||
if (!actor_spawns[obj._file]) return;
|
||||
stats[obj._file] ??= 0;
|
||||
stats[obj._file]++;
|
||||
total++;
|
||||
});
|
||||
/* for (var i in actor_spawns) {
|
||||
stats[i] = actor_spawns[i].length;
|
||||
total += stats[i];
|
||||
}*/
|
||||
// stats.total = total;
|
||||
return stats;
|
||||
};
|
||||
|
||||
actor.hotreload = function hotreload(file) {
|
||||
var script = Resources.replstrs(file);
|
||||
script = `(function() { var self = this; var $ = this.__proto__;${script};})`;
|
||||
var fn = os.eval(file, script);
|
||||
/*
|
||||
for (var obj of actor_spawns[file]) {
|
||||
var a = obj;
|
||||
a.timers.forEachRight(t=>t());
|
||||
a.timers = [];
|
||||
var save = json.decode(json.encode(a));
|
||||
fn.call(a);
|
||||
Object.merge(a, save);
|
||||
Register.check_registers(a);
|
||||
}
|
||||
*/
|
||||
};
|
||||
|
||||
//////////
|
||||
/// EVENT
|
||||
/////////
|
||||
|
||||
var Event = {
|
||||
events: {},
|
||||
|
||||
observe(name, obj, fn) {
|
||||
this.events[name] ??= [];
|
||||
this.events[name].push([obj, fn]);
|
||||
},
|
||||
|
||||
unobserve(name, obj) {
|
||||
this.events[name] = this.events[name].filter(x => x[0] !== obj);
|
||||
},
|
||||
|
||||
rm_obj(obj) {
|
||||
Object.keys(this.events).forEach(name => Event.unobserve(name, obj));
|
||||
},
|
||||
|
||||
notify(name, ...args) {
|
||||
if (!this.events[name]) return;
|
||||
this.events[name].forEach(function (x) {
|
||||
x[1].call(x[0], ...args);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
//////////////////
|
||||
///////REGISTRANT
|
||||
/////////////////
|
||||
@@ -635,15 +345,15 @@ Register.register_obj = function register_obj(obj, reg)
|
||||
var fn = obj[reg].bind(obj);
|
||||
fn.layer = obj[reg].layer;
|
||||
var name = obj.ur ? obj.ur.name : obj.toString();
|
||||
obj.timers.push(Register.registries[reg].register(fn, name));
|
||||
obj[TIMERS].push(Register.registries[reg].register(fn, name));
|
||||
if (!obj[reg].name) Object.defineProperty(obj[reg], 'name', {value:`${obj._file}_${reg}`});
|
||||
}
|
||||
|
||||
Register.check_registers = function check_registers(obj) {
|
||||
if (obj.__reggies) {
|
||||
if (obj.__reggies.length == 0) return;
|
||||
if (obj[REGGIES]) {
|
||||
if (obj[REGGIES].length == 0) return;
|
||||
// fast path
|
||||
for (var reg of obj.__reggies)
|
||||
for (var reg of obj[REGGIES])
|
||||
Register.register_obj(obj,reg);
|
||||
|
||||
return;
|
||||
@@ -653,12 +363,6 @@ Register.check_registers = function check_registers(obj) {
|
||||
if (typeof obj[reg] === "function")
|
||||
Register.register_obj(obj,reg);
|
||||
}
|
||||
|
||||
/* for (var k in obj) {
|
||||
if (!k.startsWith("on_")) continue;
|
||||
var signal = k.fromfirst("on_");
|
||||
Event.observe(signal, obj, obj[k]);
|
||||
}*/
|
||||
};
|
||||
|
||||
Register.add_cb("appupdate");
|
||||
@@ -676,9 +380,9 @@ function cant_kill()
|
||||
throw Error("Can't kill an object in its spawning code. Move the kill command to awake.");
|
||||
}
|
||||
|
||||
actor.toString = function() { return this.__file }
|
||||
actor.toString = function() { return this[FILE] }
|
||||
actor.spawn = function spawn(script, config, callback) {
|
||||
if (this.__dead__) throw Error("Attempting to spawn on a dead actor")
|
||||
if (this[DEAD]) throw Error("Attempting to spawn on a dead actor")
|
||||
var prog
|
||||
if (!script) {
|
||||
prog = {}
|
||||
@@ -692,11 +396,43 @@ actor.spawn = function spawn(script, config, callback) {
|
||||
var underling;
|
||||
prog.module_ret.__proto__ = actor;
|
||||
underling = Object.create(prog.module_ret);
|
||||
underling.overling = this;
|
||||
underling.__file = script
|
||||
underling[OVERLING] = this;
|
||||
underling[FILE] = script
|
||||
underling[TIMERS] = []
|
||||
underling[UNDERLINGS] = new Set()
|
||||
|
||||
underling.timers = []
|
||||
underling.underlings = new Set()
|
||||
Object.defineProperty(underling, 'overling', {
|
||||
get() { return this[OVERLING] },
|
||||
enumerable:true,
|
||||
configurable:false
|
||||
})
|
||||
|
||||
Object.defineProperty(underling, 'underlings', {
|
||||
get() { return new Set(this[UNDERLINGS]) },
|
||||
enumerable:true,
|
||||
configurable:false
|
||||
})
|
||||
|
||||
Object.defineProperty(underling, 'spawn', {
|
||||
value: actor.spawn,
|
||||
writable:false,
|
||||
enumerable:true,
|
||||
configurable:false
|
||||
})
|
||||
|
||||
Object.defineProperty(underling, 'kill', {
|
||||
value: actor.kill,
|
||||
writable:false,
|
||||
enumerable:true,
|
||||
configurable:false
|
||||
})
|
||||
|
||||
Object.defineProperty(underling, 'delay', {
|
||||
value: actor.delay,
|
||||
writable:false,
|
||||
enumerable:true,
|
||||
configurable:false
|
||||
})
|
||||
|
||||
if (callback) callback(underling, {
|
||||
message:"created"
|
||||
@@ -705,28 +441,23 @@ actor.spawn = function spawn(script, config, callback) {
|
||||
try{
|
||||
prog.prog_fn.call(underling)
|
||||
} catch(e) {throw e}
|
||||
if (underling.__dead__)
|
||||
if (underling[DEAD])
|
||||
return undefined
|
||||
|
||||
if (typeof config === 'object') Object.assign(underling,config);
|
||||
|
||||
if (!underling.__reggies)
|
||||
underling.__proto__.__reggies = Register.pull_registers(underling)
|
||||
if (!underling[REGGIES])
|
||||
underling.__proto__[REGGIES] = Register.pull_registers(underling)
|
||||
|
||||
Register.check_registers(underling);
|
||||
|
||||
if (underling.awake) underling.awake();
|
||||
|
||||
this.underlings.add(underling);
|
||||
this[UNDERLINGS].add(underling);
|
||||
if (underling.tag)
|
||||
search.tag_add(underling.tag, underling)
|
||||
|
||||
Object.defineProperty(underling, 'garbage', {
|
||||
configurable: false,
|
||||
writable: false,
|
||||
value: underling.garbage
|
||||
})
|
||||
|
||||
underling[GARBAGE] = underling.garbage
|
||||
return underling;
|
||||
};
|
||||
|
||||
@@ -734,25 +465,24 @@ actor.spawn.doc = `Create a new actor, using this actor as the overling, initial
|
||||
|
||||
actor.clear = function actor_clear()
|
||||
{
|
||||
this.underlings.forEach(p => {
|
||||
this[UNDERLINGS].forEach(p => {
|
||||
p.kill();
|
||||
})
|
||||
this.underlings.clear()
|
||||
this[UNDERLINGS].clear()
|
||||
}
|
||||
|
||||
var input = use('input')
|
||||
|
||||
actor.kill = function kill() {
|
||||
if (this.__dead__) return;
|
||||
this.__dead__ = true;
|
||||
this.timers.slice().forEach(t => t()) // slice in case something is removed from timers while running
|
||||
delete this.timers
|
||||
if (this[DEAD]) return
|
||||
this[DEAD] = true
|
||||
this[TIMERS].slice().forEach(t => t()) // slice in case something is removed from timers while running
|
||||
delete this[TIMERS]
|
||||
input.do_uncontrol(this);
|
||||
Event.rm_obj(this);
|
||||
|
||||
this.clear()
|
||||
this.overling.underlings.delete(this)
|
||||
delete this.underlings
|
||||
this[OVERLING][UNDERLINGS].delete(this)
|
||||
delete this[UNDERLINGS]
|
||||
|
||||
if (typeof this.garbage === "function") this.garbage();
|
||||
if (typeof this.then === "function") this.then();
|
||||
@@ -765,21 +495,9 @@ actor.kill.doc = `Remove this actor and all its underlings from existence.`;
|
||||
actor.delay = function (fn, seconds) { add_timer(this, fn, seconds) }
|
||||
actor.delay.doc = `Call 'fn' after 'seconds' with 'this' set to the actor.`;
|
||||
|
||||
actor.interval = function interval(fn, seconds) {
|
||||
var self = this;
|
||||
var stop;
|
||||
var usefn = function () {
|
||||
fn();
|
||||
stop = self.delay(usefn, seconds);
|
||||
};
|
||||
stop = self.delay(usefn, seconds);
|
||||
|
||||
return stop;
|
||||
};
|
||||
|
||||
var search = use('search')
|
||||
|
||||
actor.underlings = new Set()
|
||||
actor[UNDERLINGS] = new Set()
|
||||
|
||||
globalThis.mixin("color");
|
||||
globalThis.mixin("std")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var geometry = os.use('geometry')
|
||||
var geometry = this
|
||||
var vector = use('vector')
|
||||
|
||||
var shape = {};
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
var graphics = {}
|
||||
var os = use('os')
|
||||
var io = use('io')
|
||||
var res = use('resources')
|
||||
|
||||
function calc_image_size(img)
|
||||
{
|
||||
@@ -97,7 +100,7 @@ graphics.texture = function texture(path) {
|
||||
throw new Error('need a string for graphics.texture')
|
||||
}
|
||||
var parts = path.split(':');
|
||||
var ipath = Resources.find_image(parts[0]);
|
||||
var ipath = res.find_image(parts[0]);
|
||||
|
||||
graphics.texture.cache[ipath] ??= create_image(ipath);
|
||||
return graphics.texture.cache[ipath];
|
||||
@@ -134,7 +137,6 @@ graphics.tex_hotreload = function tex_hotreload(file) {
|
||||
var oldimg = graphics.texture.cache[file];
|
||||
console.log(`new image:${json.encode(img)}`)
|
||||
console.log(`old image: ${json.encode(oldimg)}`)
|
||||
|
||||
|
||||
merge_objects(oldimg,img, ['surface', 'texture', 'loop', 'time']);
|
||||
// graphics.texture.cache[file] = img;
|
||||
@@ -168,11 +170,13 @@ graphics.get_font = function get_font(path,size)
|
||||
path = parts[0];
|
||||
size = Number(parts[1]);
|
||||
}
|
||||
path = Resources.find_font(path);
|
||||
var fontstr = `${path}.${size}`;
|
||||
var fullpath = res.find_font(path);
|
||||
if (!fullpath) throw new Error(`Cannot load font ${path}`)
|
||||
|
||||
var fontstr = `${fullpath}.${size}`;
|
||||
if (fontcache[fontstr]) return fontcache[fontstr];
|
||||
|
||||
var data = io.slurpbytes(path);
|
||||
var data = io.slurpbytes(fullpath);
|
||||
fontcache[fontstr] = os.make_font(data,size);
|
||||
fontcache[fontstr].texture = prosperon.gpu.load_texture(fontcache[fontstr].surface);
|
||||
return fontcache[fontstr];
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
var input = os.use('input')
|
||||
var input = this
|
||||
|
||||
var util = use('util')
|
||||
|
||||
var downkeys = {};
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
io path rules. Starts with, meaning:
|
||||
"@": user path
|
||||
"/": root game path
|
||||
"" : relative game path
|
||||
*/
|
||||
|
||||
var io = os.use('io')
|
||||
|
||||
var tmpslurp = io.slurp;
|
||||
io.slurp = function slurp(path)
|
||||
{
|
||||
var findpath = Resources.replpath(path);
|
||||
var ret = tmpslurp(findpath, true); //|| core_db.slurp(findpath, true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
io.slurpbytes = function(path)
|
||||
{
|
||||
path = Resources.replpath(path);
|
||||
var ret = tmpslurp(path);// || core_db.slurp(path);
|
||||
if (!ret) throw new Error(`Could not find file ${path} anywhere`);
|
||||
return ret;
|
||||
}
|
||||
|
||||
var ignore = io.slurp('.prosperonignore').split('\n');
|
||||
var allpaths;
|
||||
var tmpglob = io.glob;
|
||||
io.glob = function glob(pat) {
|
||||
if (!allpaths)
|
||||
allpaths = io.globfs(ignore);
|
||||
|
||||
return allpaths.filter(str => game.glob(pat,str)).sort();
|
||||
}
|
||||
|
||||
/*var ignore;
|
||||
if (ignore = io.slurp('.prosperonignore')) {
|
||||
ignore = ignore.split('\n');
|
||||
for (var ig of ignore) {
|
||||
if (!ig) continue;
|
||||
allpaths = allpaths.filter(x => !x.startsWith(ig));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
io.invalidate = function()
|
||||
{
|
||||
allpaths = undefined;
|
||||
}
|
||||
|
||||
io.mkpath = function (dir) {
|
||||
if (!dir) return;
|
||||
var mkstack = [];
|
||||
while (!io.exists(dir)) {
|
||||
mkstack.push(dir.fromlast("/"));
|
||||
dir = dir.dir();
|
||||
}
|
||||
for (var d of mkstack) {
|
||||
dir = dir + "/" + d;
|
||||
say(`making ${dir}`);
|
||||
io.mkdir(dir);
|
||||
}
|
||||
};
|
||||
|
||||
io.doc = {
|
||||
doc: "Functions for filesystem input/output commands.",
|
||||
exists: "Returns true if a file exists.",
|
||||
slurp: "Returns the contents of given file as a string.",
|
||||
slurpbytes: "Return the contents of a file as a byte array.",
|
||||
slurpwrite: "Write a given string to a given file.",
|
||||
cp: "Copy file f1 to f2.",
|
||||
mv: "Rename file f1 to f2.",
|
||||
rm: "Remove file f.",
|
||||
mkdir: "Make dir.",
|
||||
ls: "List contents of the game directory.",
|
||||
glob: "Glob files in game directory.",
|
||||
};
|
||||
|
||||
return io
|
||||
13
scripts/json.js
Normal file
13
scripts/json.js
Normal file
@@ -0,0 +1,13 @@
|
||||
var json = {}
|
||||
|
||||
json.encode = function(val,space,replacer,whitelist)
|
||||
{
|
||||
return JSON.stringify(val, replacer, space ? 1 : 0)
|
||||
}
|
||||
|
||||
json.decode = function(text,reviver)
|
||||
{
|
||||
return JSON.parse(text,reviver)
|
||||
}
|
||||
|
||||
return json
|
||||
3
scripts/log.js
Normal file
3
scripts/log.js
Normal file
@@ -0,0 +1,3 @@
|
||||
var log = {}
|
||||
|
||||
return log
|
||||
@@ -1,4 +1,4 @@
|
||||
var profile = os.use('profile')
|
||||
var profile = this
|
||||
|
||||
var pmath = use('pmath')
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ var config = use('config.js')
|
||||
var gizmo = use('gizmos')
|
||||
var vector = use('vector')
|
||||
var search = use('search')
|
||||
var io = use('io')
|
||||
var os = use('os')
|
||||
|
||||
var input = use('input')
|
||||
|
||||
@@ -30,7 +32,6 @@ appy.inputs["M-f4"] = os.exit;
|
||||
|
||||
input.player[0].control(appy);
|
||||
|
||||
|
||||
prosperon.window = os.engine_start(config);
|
||||
|
||||
var driver = "vulkan"
|
||||
|
||||
58
scripts/resources.js
Normal file
58
scripts/resources.js
Normal file
@@ -0,0 +1,58 @@
|
||||
var Resources = {}
|
||||
|
||||
var so_ext;
|
||||
switch(os.sys()) {
|
||||
case 'Windows':
|
||||
so_ext = '.dll';
|
||||
break;
|
||||
default:
|
||||
so_ext = '.so';
|
||||
break;
|
||||
}
|
||||
|
||||
Resources.scripts = ["jsoc", "jsc", "jso", "js"]
|
||||
Resources.images = ["qoi", "png", "gif", "jpg", "jpeg", "ase", "aseprite"]
|
||||
Resources.sounds = ["wav", "flac", "mp3", "qoa"]
|
||||
Resources.fonts = ["ttf"]
|
||||
Resources.lib = [so_ext]
|
||||
|
||||
Resources.canonical = function(file)
|
||||
{
|
||||
return io.realdir(file) + file
|
||||
}
|
||||
|
||||
// ext is a list of extensions to search
|
||||
// returns the file to load
|
||||
function find_ext(file, ext) {
|
||||
if (!file) return;
|
||||
|
||||
var file_ext = file.ext()
|
||||
if (file_ext && ext.some(e => e === file_ext))
|
||||
if (io.exists(file)) return file
|
||||
|
||||
for (var e of ext) {
|
||||
var attempt = `${file}.${e}`;
|
||||
if (io.exists(attempt)) return attempt
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
Resources.find_image = function (file) {
|
||||
return find_ext(file, Resources.images);
|
||||
}.hashify();
|
||||
|
||||
Resources.find_sound = function (file) {
|
||||
return find_ext(file, Resources.sounds);
|
||||
}.hashify();
|
||||
|
||||
Resources.find_script = function (file) {
|
||||
return find_ext(file, Resources.scripts);
|
||||
}.hashify();
|
||||
|
||||
Resources.find_font = function(file) {
|
||||
return find_ext(file, Resources.fonts);
|
||||
}.hashify();
|
||||
|
||||
|
||||
return Resources
|
||||
@@ -1,5 +1,6 @@
|
||||
//var soloud = use('soloud')
|
||||
var tween = use('tween')
|
||||
var io = use('io')
|
||||
soloud.init();
|
||||
|
||||
var audio = {};
|
||||
|
||||
@@ -204,6 +204,7 @@ return sprite;
|
||||
---
|
||||
|
||||
var Color = use('color')
|
||||
var os = use('os')
|
||||
|
||||
this.transform = os.make_transform();
|
||||
if (this.overling.transform)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
var profile = use('profile')
|
||||
var io = use('io')
|
||||
|
||||
var dumpfolder = ".prosperon";
|
||||
@@ -24,7 +25,7 @@ Cmdline.register_order(
|
||||
"edit",
|
||||
function () {
|
||||
if (!io.exists(projectfile)) {
|
||||
say("No game to edit. Try making one with 'prosperon init'.");
|
||||
console.print("No game to edit. Try making one with 'prosperon init'.");
|
||||
return;
|
||||
}
|
||||
},
|
||||
@@ -36,7 +37,7 @@ Cmdline.register_order(
|
||||
"init",
|
||||
function () {
|
||||
if (io.exists(projectfile)) {
|
||||
say("Already a game here.");
|
||||
console.print("Already a game here.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -102,14 +103,14 @@ Cmdline.register_order(
|
||||
return;
|
||||
} else packname = str[0];
|
||||
|
||||
say(`Packing into ${packname}`);
|
||||
console.print(`Packing into ${packname}`);
|
||||
|
||||
io.pack_start(packname);
|
||||
files = allfiles.filter(f => !f.startsWith(".git"));
|
||||
files = files.filter(f => !f.startsWith(".nova"));
|
||||
files = files.filter(f => !f.includes(".DS_Store"));
|
||||
files = files.filter(f => !f.startsWith(".gitignore"));
|
||||
say(files);
|
||||
console.print(files);
|
||||
for (var f of files) io.pack_add(f);
|
||||
io.pack_end();
|
||||
},
|
||||
@@ -122,11 +123,11 @@ Cmdline.register_order(
|
||||
function (argv) {
|
||||
var cdb = "game.zip";
|
||||
if (!io.exists(cdb)) {
|
||||
say(`No 'game.zip' present.`);
|
||||
console.print(`No 'game.zip' present.`);
|
||||
return;
|
||||
}
|
||||
if (argv.length === 0) {
|
||||
say(`cdb name: ${cdb}`);
|
||||
console.print(`cdb name: ${cdb}`);
|
||||
}
|
||||
},
|
||||
"CDB commands.",
|
||||
@@ -138,7 +139,7 @@ Cmdline.register_order(
|
||||
var sounds = Resources.sounds.filter(x => x !== "qoa");
|
||||
for (var file of argv) {
|
||||
if (!sounds.includes(file.ext())) continue;
|
||||
say(`converting ${file}`);
|
||||
console.print(`converting ${file}`);
|
||||
io.save_qoa(file);
|
||||
}
|
||||
},
|
||||
@@ -149,13 +150,13 @@ Cmdline.register_order(
|
||||
"about",
|
||||
function (argv) {
|
||||
if (!argv[0]) {
|
||||
say("About your game");
|
||||
say(`Prosperon version ${prosperon.version}`);
|
||||
say(`Total entities ${ur._list.length}`);
|
||||
console.print("About your game");
|
||||
console.print(`Prosperon version ${prosperon.version}`);
|
||||
console.print(`Total entities ${ur._list.length}`);
|
||||
}
|
||||
switch (argv[0]) {
|
||||
case "entities":
|
||||
for (var i of ur._list) say(i);
|
||||
for (var i of ur._list) console.print(i);
|
||||
break;
|
||||
}
|
||||
},
|
||||
@@ -166,7 +167,7 @@ Cmdline.register_order(
|
||||
"ur",
|
||||
function (argv) {
|
||||
// game.loadurs();
|
||||
for (var i of ur._list.sort()) say(i);
|
||||
for (var i of ur._list.sort()) console.print(i);
|
||||
},
|
||||
"Get information about the ur types in your game.",
|
||||
);
|
||||
@@ -177,21 +178,21 @@ Cmdline.register_order(
|
||||
if (argv.length > 2) return;
|
||||
var gg = json.decode(io.slurp(projectfile));
|
||||
if (argv.length === 0) {
|
||||
say(json.encode(gg, null, 1));
|
||||
console.print(json.encode(gg, null, 1));
|
||||
return;
|
||||
}
|
||||
|
||||
if (argv.length === 1) {
|
||||
var v = gg[argv[0]];
|
||||
if (!v) {
|
||||
say(`Value ${argv[0]} not found.`);
|
||||
console.print(`Value ${argv[0]} not found.`);
|
||||
return;
|
||||
}
|
||||
say(`${argv[0]}:${v}`);
|
||||
console.print(`${argv[0]}:${v}`);
|
||||
} else {
|
||||
gg[argv[0]] = argv[1];
|
||||
say(`Set ${argv[0]}:${v}`);
|
||||
say(json.encode(gg, null, 1));
|
||||
console.print(`Set ${argv[0]}:${v}`);
|
||||
console.print(json.encode(gg, null, 1));
|
||||
io.slurpwrite(projectfile, json.encode(gg));
|
||||
}
|
||||
},
|
||||
@@ -201,7 +202,7 @@ Cmdline.register_order(
|
||||
Cmdline.register_order(
|
||||
"unpack",
|
||||
function () {
|
||||
say("Unpacking not implemented.");
|
||||
console.print("Unpacking not implemented.");
|
||||
},
|
||||
"Unpack this binary's contents into this folder for editing.",
|
||||
);
|
||||
@@ -209,7 +210,7 @@ Cmdline.register_order(
|
||||
Cmdline.register_order(
|
||||
"build",
|
||||
function () {
|
||||
say("Building not implemented.");
|
||||
console.print("Building not implemented.");
|
||||
},
|
||||
"Build static assets for this project.",
|
||||
);
|
||||
@@ -219,7 +220,7 @@ Cmdline.register_order(
|
||||
function (argv) {
|
||||
for (var file of argv) {
|
||||
if (!io.exists(file)) {
|
||||
say(`File ${file} does not exist.`);
|
||||
console.print(`File ${file} does not exist.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -236,10 +237,10 @@ Cmdline.register_order(
|
||||
function (argv) {
|
||||
for (var file of argv) {
|
||||
if (!io.exists(file)) {
|
||||
say(`File ${file} does not exist.`);
|
||||
console.print(`File ${file} does not exist.`);
|
||||
continue;
|
||||
}
|
||||
say(file.ext());
|
||||
console.print(file.ext());
|
||||
var obj = nota.decode(io.slurp(file));
|
||||
var nn = json.encode(obj);
|
||||
io.slurpwrite(file.strip_ext() + ".json", nn);
|
||||
@@ -260,7 +261,7 @@ Cmdline.register_order(
|
||||
var api = debug.api.print_doc(obj[0]);
|
||||
if (!api) return;
|
||||
|
||||
say(api);
|
||||
console.print(api);
|
||||
},
|
||||
"Print the API for an object as markdown. Give it a file to save the output to.",
|
||||
"OBJECT",
|
||||
@@ -270,8 +271,8 @@ Cmdline.register_order(
|
||||
"input",
|
||||
function (pawn) {
|
||||
use("editor.js");
|
||||
say(`## Input for ${pawn}`);
|
||||
eval(`say(input.print_md_kbm(${pawn}));`);
|
||||
console.print(`## Input for ${pawn}`);
|
||||
eval(`console.print(input.print_md_kbm(${pawn}));`);
|
||||
},
|
||||
"Print input documentation for a given object as markdown. Give it a file to save the output to",
|
||||
"OBJECT ?FILE?",
|
||||
@@ -280,13 +281,14 @@ Cmdline.register_order(
|
||||
Cmdline.register_order(
|
||||
"run",
|
||||
function (script) {
|
||||
var s = os.now()
|
||||
script = script.join(" ");
|
||||
if (!script) {
|
||||
say("Need something to run.");
|
||||
console.print("Need something to run.");
|
||||
return;
|
||||
}
|
||||
|
||||
say(eval(script));
|
||||
console.print(eval(script));
|
||||
},
|
||||
"Run a given script. SCRIPT can be the script itself, or a file containing the script",
|
||||
"SCRIPT",
|
||||
@@ -298,8 +300,8 @@ Cmdline.print_order = function (fn) {
|
||||
if (typeof fn === "string") fn = Cmdline.orders[fn];
|
||||
|
||||
if (!fn) return;
|
||||
say(`Usage: prosperon ${fn.usage}`);
|
||||
say(fn.doc);
|
||||
console.print(`Usage: prosperon ${fn.usage}`);
|
||||
console.print(fn.doc);
|
||||
};
|
||||
|
||||
Cmdline.register_order(
|
||||
@@ -319,7 +321,7 @@ Cmdline.register_order(
|
||||
|
||||
Cmdline.print_order("help");
|
||||
|
||||
for (var cmd of Object.keys(Cmdline.orders).sort()) say(cmd);
|
||||
for (var cmd of Object.keys(Cmdline.orders).sort()) console.print(cmd);
|
||||
|
||||
Cmdline.orders.version();
|
||||
},
|
||||
@@ -330,7 +332,7 @@ Cmdline.register_order(
|
||||
Cmdline.register_order(
|
||||
"version",
|
||||
function () {
|
||||
say(`Prosperon version ${prosperon.version} [${prosperon.revision}]`);
|
||||
console.print(`Prosperon version ${prosperon.version} [${prosperon.revision}]`);
|
||||
},
|
||||
"Display Prosperon info.",
|
||||
);
|
||||
@@ -346,13 +348,12 @@ function cmd_args(cmdargs) {
|
||||
}
|
||||
|
||||
Cmdline.orders[cmds[0]](cmds.slice(1));
|
||||
if (!game.startengine) os.exit(0);
|
||||
}
|
||||
|
||||
Cmdline.register_order(
|
||||
"clean",
|
||||
function (argv) {
|
||||
say("Cleaning not implemented.");
|
||||
console.print("Cleaning not implemented.");
|
||||
},
|
||||
"Clean up a given object file.",
|
||||
"JSON ...",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
var time = os.use('time')
|
||||
var time = this
|
||||
|
||||
/* Time values are always expressed in terms of real earth-seconds */
|
||||
Object.assign(time, {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* VECTORS */
|
||||
var vector = os.use('vector')
|
||||
var vector = this
|
||||
|
||||
vector.random = function () {
|
||||
var vec = [Math.random() - 0.5, Math.random() - 0.5];
|
||||
|
||||
169
source/jsffi.c
169
source/jsffi.c
@@ -5581,6 +5581,22 @@ JSC_SCALL(io_stat,
|
||||
JS_SetPropertyStr(js,ret,"accesstime", number2js(js,stat.accesstime));
|
||||
)
|
||||
|
||||
JSC_SCALL(io_slurpbytes,
|
||||
PHYSFS_File *f = PHYSFS_openRead(str);
|
||||
if (!f) {
|
||||
ret = JS_ThrowReferenceError(js,"physfs error when slurping %s: %s", str, PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
goto END;
|
||||
}
|
||||
PHYSFS_Stat stat;
|
||||
PHYSFS_stat(str,&stat);
|
||||
void *data = malloc(stat.filesize);
|
||||
PHYSFS_readBytes(f,data,stat.filesize);
|
||||
PHYSFS_close(f);
|
||||
ret = JS_NewArrayBufferCopy(js,data,stat.filesize);
|
||||
|
||||
END:
|
||||
)
|
||||
|
||||
JSC_SCALL(io_slurp,
|
||||
PHYSFS_File *f = PHYSFS_openRead(str);
|
||||
if (!f) {
|
||||
@@ -5592,10 +5608,7 @@ JSC_SCALL(io_slurp,
|
||||
void *data = malloc(stat.filesize);
|
||||
PHYSFS_readBytes(f,data,stat.filesize);
|
||||
PHYSFS_close(f);
|
||||
if (JS_ToBool(js,argv[1]))
|
||||
ret = JS_NewStringLen(js,data, stat.filesize);
|
||||
else
|
||||
ret = JS_NewArrayBufferCopy(js,data,stat.filesize);
|
||||
ret = JS_NewStringLen(js,data, stat.filesize);
|
||||
|
||||
END:
|
||||
)
|
||||
@@ -5621,8 +5634,8 @@ JSC_SCALL(io_slurpwrite,
|
||||
END:
|
||||
)
|
||||
|
||||
JSC_SCALL(io_mount,
|
||||
if (!PHYSFS_mount(str,NULL,0)) ret = JS_ThrowReferenceError(js,"%s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
JSC_SSCALL(io_mount,
|
||||
if (!PHYSFS_mount(str,str2,0)) ret = JS_ThrowReferenceError(js,"%s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
)
|
||||
|
||||
JSC_SCALL(io_unmount,
|
||||
@@ -5710,13 +5723,27 @@ JSC_CCALL(io_globfs,
|
||||
)
|
||||
|
||||
JSC_CCALL(io_basedir, return JS_NewString(js,PHYSFS_getBaseDir()))
|
||||
JSC_CCALL(io_userdir, return JS_NewString(js,PHYSFS_getUserDir()))
|
||||
|
||||
JSC_SCALL(io_open,
|
||||
PHYSFS_File *f = PHYSFS_openWrite(str);
|
||||
if (!f)
|
||||
return JS_ThrowReferenceError(js,"%s", PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()));
|
||||
|
||||
return PHYSFS_File2js(js,f);
|
||||
ret = PHYSFS_File2js(js,f);
|
||||
)
|
||||
|
||||
JSC_SCALL(io_realdir,
|
||||
const char *real = PHYSFS_getRealDir(str);
|
||||
if (!real) return JS_UNDEFINED;
|
||||
ret = JS_NewString(js,real);
|
||||
)
|
||||
|
||||
JSC_CCALL(io_searchpath,
|
||||
ret = JS_NewArray(js);
|
||||
char **paths = PHYSFS_getSearchPath();
|
||||
for (int i = 0; paths[i] != NULL; i++)
|
||||
JS_SetPropertyUint32(js,ret,i,JS_NewString(js,paths[i]));
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_io_funcs[] = {
|
||||
@@ -5726,14 +5753,18 @@ static const JSCFunctionListEntry js_io_funcs[] = {
|
||||
MIST_FUNC_DEF(io, globfs, 1),
|
||||
MIST_FUNC_DEF(io, match, 2),
|
||||
MIST_FUNC_DEF(io, exists, 1),
|
||||
MIST_FUNC_DEF(io, mount, 1),
|
||||
MIST_FUNC_DEF(io, mount, 2),
|
||||
MIST_FUNC_DEF(io,unmount,1),
|
||||
MIST_FUNC_DEF(io,slurp,2),
|
||||
MIST_FUNC_DEF(io,slurp,1),
|
||||
MIST_FUNC_DEF(io,slurpbytes,1),
|
||||
MIST_FUNC_DEF(io,slurpwrite,2),
|
||||
MIST_FUNC_DEF(io,writepath, 1),
|
||||
MIST_FUNC_DEF(io,basedir, 0),
|
||||
MIST_FUNC_DEF(io, userdir, 0),
|
||||
MIST_FUNC_DEF(io, realdir, 1),
|
||||
MIST_FUNC_DEF(io, gamemode, 2),
|
||||
MIST_FUNC_DEF(io, open, 2),
|
||||
MIST_FUNC_DEF(io, searchpath, 0),
|
||||
};
|
||||
|
||||
JSC_CCALL(file_close,
|
||||
@@ -6167,6 +6198,7 @@ JSC_CCALL(os_exit, exit(js2number(js,argv[0]));)
|
||||
JSC_CCALL(os_gc,
|
||||
return JS_RunGC(JS_GetRuntime(js), js)
|
||||
)
|
||||
JSC_CCALL(os_now, return number2js(js, (double)SDL_GetTicksNS()/1000000000.0))
|
||||
JSC_CCALL(os_mem_limit, JS_SetMemoryLimit(JS_GetRuntime(js), js2number(js,argv[0])))
|
||||
JSC_CCALL(os_gc_threshold, JS_SetGCThreshold(JS_GetRuntime(js), js2number(js,argv[0])))
|
||||
JSC_CCALL(os_max_stacksize, JS_SetMaxStackSize(JS_GetRuntime(js), js2number(js,argv[0])))
|
||||
@@ -6308,28 +6340,6 @@ void script_report_gc_time(double t, double startmem, double mem)
|
||||
gc_startmem = startmem;
|
||||
}
|
||||
|
||||
static FILE *cycles;
|
||||
|
||||
JSC_CCALL(os_check_cycles,
|
||||
if (ftell(cycles) == 0) return JS_UNDEFINED;
|
||||
cycles = tmpfile();
|
||||
quickjs_set_cycleout(cycles);
|
||||
ret = tmp2js(js,cycles);
|
||||
)
|
||||
|
||||
JSC_CCALL(os_check_gc,
|
||||
if (gc_t == 0) return JS_UNDEFINED;
|
||||
|
||||
JSValue gc = JS_NewObject(js);
|
||||
JS_SetPropertyStr(js, gc, "time", number2js(js,gc_t));
|
||||
JS_SetPropertyStr(js, gc, "mem", number2js(js,gc_mem));
|
||||
JS_SetPropertyStr(js, gc, "startmem", number2js(js,gc_startmem));
|
||||
gc_t = 0;
|
||||
gc_mem = 0;
|
||||
gc_startmem = 0;
|
||||
return gc;
|
||||
)
|
||||
|
||||
JSC_SSCALL(os_eval, return ret = script_eval(js,str, str2))
|
||||
JSC_CCALL(os_make_timer, return timer2js(js,timer_make(js,argv[0])))
|
||||
JSC_CCALL(os_update_timers, timer_update(js, js2number(js,argv[0])))
|
||||
@@ -7182,45 +7192,6 @@ typedef struct {
|
||||
size_t fn_count;
|
||||
} ModuleEntry;
|
||||
|
||||
#define MISTLINE(NAME) { #NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs) }
|
||||
|
||||
static ModuleEntry module_registry[] = {
|
||||
MISTLINE(io),
|
||||
MISTLINE(input),
|
||||
MISTLINE(time),
|
||||
MISTLINE(profile),
|
||||
MISTLINE(debug),
|
||||
MISTLINE(vector),
|
||||
MISTLINE(spline),
|
||||
MISTLINE(performance),
|
||||
MISTLINE(geometry),
|
||||
MISTLINE(camera),
|
||||
};
|
||||
|
||||
JSC_SCALL(os_use,
|
||||
SDL_SharedObject *ptr;
|
||||
if (access(str, F_OK) != 0 || !(ptr = SDL_LoadObject(str))) {
|
||||
for (int i = 0; i < sizeof(module_registry)/sizeof(module_registry[0]); i++) {
|
||||
if (strcmp(str,module_registry[i].name) == 0) {
|
||||
JSValue mod = JS_NewObject(js);
|
||||
JS_SetPropertyFunctionList(js,mod,module_registry[i].fn, module_registry[i].fn_count);
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
return JS_ThrowReferenceError(js, "%s\nAnd could not find a static module.", SDL_GetError());
|
||||
}
|
||||
|
||||
JSValue (*js_use)(JSContext*);
|
||||
js_use = (JSValue (*)(JSContext*))SDL_LoadFunction(ptr, "use");
|
||||
|
||||
if (!js_use)
|
||||
ret = JS_ThrowReferenceError(js, "Shared library %s has no use function", str);
|
||||
else
|
||||
ret = js_use(js);
|
||||
|
||||
SDL_UnloadObject(ptr);
|
||||
)
|
||||
|
||||
JSC_SSCALL(os_trimchr,
|
||||
int len;
|
||||
JS_GETPROP(js,len,argv[0],length,number)
|
||||
@@ -7254,6 +7225,7 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
MIST_FUNC_DEF(os, system, 1),
|
||||
MIST_FUNC_DEF(os, exit, 1),
|
||||
MIST_FUNC_DEF(os, gc, 0),
|
||||
MIST_FUNC_DEF(os, now, 0),
|
||||
MIST_FUNC_DEF(os, guid, 0),
|
||||
MIST_FUNC_DEF(os, openurl, 1),
|
||||
MIST_FUNC_DEF(os, push_event, 1),
|
||||
@@ -7291,8 +7263,6 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
MIST_FUNC_DEF(os, dump_shapes, 0),
|
||||
MIST_FUNC_DEF(os, dump_atoms,0),
|
||||
MIST_FUNC_DEF(os, calc_mem, 1),
|
||||
MIST_FUNC_DEF(os, check_gc, 0),
|
||||
MIST_FUNC_DEF(os, check_cycles, 0),
|
||||
MIST_FUNC_DEF(os, memstate, 0),
|
||||
MIST_FUNC_DEF(os, value_id, 1),
|
||||
MIST_FUNC_DEF(os, gltf_buffer, 3),
|
||||
@@ -7309,10 +7279,57 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
MIST_FUNC_DEF(os, cull_sprites, 2),
|
||||
MIST_FUNC_DEF(os, rects_to_sprites,2),
|
||||
MIST_FUNC_DEF(os, on, 2),
|
||||
MIST_FUNC_DEF(os, use, 1),
|
||||
MIST_FUNC_DEF(os, trimchr, 2),
|
||||
|
||||
};
|
||||
|
||||
#define MISTLINE(NAME) { #NAME, js_##NAME##_funcs, countof(js_##NAME##_funcs) }
|
||||
|
||||
static ModuleEntry module_registry[] = {
|
||||
MISTLINE(io),
|
||||
MISTLINE(os),
|
||||
MISTLINE(input),
|
||||
MISTLINE(time),
|
||||
MISTLINE(profile),
|
||||
MISTLINE(debug),
|
||||
MISTLINE(vector),
|
||||
MISTLINE(spline),
|
||||
MISTLINE(performance),
|
||||
MISTLINE(geometry),
|
||||
MISTLINE(camera),
|
||||
};
|
||||
|
||||
JSC_SCALL(os_use_embed,
|
||||
for (int i = 0; i < sizeof(module_registry)/sizeof(module_registry[0]); i++) {
|
||||
if (strcmp(str,module_registry[i].name) == 0) {
|
||||
JSValue mod = JS_NewObject(js);
|
||||
JS_SetPropertyFunctionList(js,mod,module_registry[i].fn, module_registry[i].fn_count);
|
||||
return mod;
|
||||
}
|
||||
}
|
||||
return JS_ThrowReferenceError(js,"Library %s could not be found embedded");
|
||||
)
|
||||
|
||||
JSC_SCALL(os_use_dyn,
|
||||
SDL_SharedObject *ptr = SDL_LoadObject(str);
|
||||
if (!ptr)
|
||||
return JS_ThrowReferenceError(js, "Shared library %s could not be loaded", SDL_GetError());
|
||||
|
||||
JSValue (*js_use)(JSContext*);
|
||||
js_use = (JSValue (*)(JSContext*))SDL_LoadFunction(ptr, "use");
|
||||
|
||||
if (!js_use)
|
||||
ret = JS_ThrowReferenceError(js, "Shared library %s has no use function", str);
|
||||
else
|
||||
ret = js_use(js);
|
||||
|
||||
SDL_UnloadObject(ptr);
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
JSC_CCALL(qtree_insert,
|
||||
qtree tree = js2qtree(js,self);
|
||||
JSValue v = argv[0];
|
||||
@@ -7590,9 +7607,6 @@ static void exit_handler()
|
||||
}
|
||||
|
||||
void ffi_load(JSContext *js) {
|
||||
cycles = tmpfile();
|
||||
quickjs_set_cycleout(cycles);
|
||||
|
||||
JSValue globalThis = JS_GetGlobalObject(js);
|
||||
|
||||
QJSCLASSPREP_FUNCS(qtree)
|
||||
@@ -7628,6 +7642,9 @@ void ffi_load(JSContext *js) {
|
||||
QJSCLASSPREP_FUNCS(datastream);
|
||||
QJSCLASSPREP_FUNCS(timer);
|
||||
|
||||
JS_SetPropertyStr(js, globalThis, "use_dyn", JS_NewCFunction(js,js_os_use_dyn,"use_dyn", 1));
|
||||
JS_SetPropertyStr(js, globalThis, "use_embed", JS_NewCFunction(js,js_os_use_embed,"use_embed", 1));
|
||||
|
||||
QJSGLOBALCLASS(os);
|
||||
QJSGLOBALCLASS(console);
|
||||
|
||||
|
||||
@@ -19,8 +19,10 @@
|
||||
)
|
||||
|
||||
#define JSC_SSCALL(NAME, ...) JSC_CCALL(NAME, \
|
||||
const char *str = JS_ToCString(js,argv[0]); \
|
||||
const char *str2 = JS_ToCString(js,argv[1]); \
|
||||
const char *str = NULL; \
|
||||
const char *str2 = NULL; \
|
||||
if (!JS_IsUndefined(argv[0])) str = JS_ToCString(js,argv[0]); \
|
||||
if (!JS_IsUndefined(argv[1])) str2 = JS_ToCString(js,argv[1]); \
|
||||
__VA_ARGS__ ; \
|
||||
JS_FreeCString(js,str2); \
|
||||
JS_FreeCString(js,str); \
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
#include "script.h"
|
||||
#include <string.h>
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
#include "physfs.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
@@ -9,6 +11,7 @@ int main(int argc, char **argv) {
|
||||
char *base = PHYSFS_getBaseDir();
|
||||
PHYSFS_setWriteDir(base);
|
||||
PHYSFS_mount(base,NULL,0);
|
||||
PHYSFS_mount(base,"/",0);
|
||||
script_startup(); // runs engine.js
|
||||
|
||||
int argsize = 0;
|
||||
|
||||
Reference in New Issue
Block a user