202 lines
4.8 KiB
JavaScript
202 lines
4.8 KiB
JavaScript
var actor = {};
|
|
|
|
var actor_urs = {};
|
|
|
|
var actor_spawns = {};
|
|
|
|
var script_fns = {};
|
|
|
|
function use(file)
|
|
{
|
|
var par = script_fn(file)
|
|
if (!par.module_ret)
|
|
throw new Error(`File ${file} has no valid module definition`)
|
|
|
|
return par.module_ret;
|
|
}
|
|
|
|
var script_fn = function script_fn(file) {
|
|
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; ${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;
|
|
}
|
|
|
|
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 fn;
|
|
}
|
|
|
|
function parse_file(content) {
|
|
var parts = content.split(/\n\s*---\s*\n/)
|
|
if (parts.length === 1)
|
|
return {
|
|
program: parts[0]
|
|
}
|
|
}
|
|
|
|
var module = parts[0].trim();
|
|
if (!moduleCode.match(/return\s+[^;]+;?\s*$/))
|
|
throw new Error("Module section must end with a return statement");
|
|
|
|
return {
|
|
module,
|
|
program: parts[1]
|
|
}
|
|
}
|
|
|
|
globalThis.actor_use = function actor_use(script)
|
|
{
|
|
var file = Resources.find_script(script);
|
|
if (!file)
|
|
return;
|
|
|
|
return use(file)
|
|
}
|
|
|
|
globalThis.class_use = function class_use(script, config, base, callback) {
|
|
var file = Resources.find_script(script);
|
|
|
|
if (!file) {
|
|
var ret = Object.create(base);
|
|
if (callback) callback(ret);
|
|
return ret;
|
|
}
|
|
|
|
var prog = script_fn(file);
|
|
var padawan;
|
|
if (prog.module_ret)
|
|
padawan = Object.create(prog.module_ret);
|
|
else
|
|
padawan = {};
|
|
|
|
if (callback) callback(padawan)
|
|
prog.prog_fn.call(padawan)
|
|
if (typeof config === 'object') Object.merge(padawan,config);
|
|
|
|
return padawan;
|
|
};
|
|
|
|
globalThis.rmactor = function (e) {
|
|
if (!actor_spawns[e._file]) return;
|
|
actor_spawns[e._file].remove(e);
|
|
};
|
|
|
|
actor.__stats = function () {
|
|
var total = 0;
|
|
var stats = {};
|
|
game.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);
|
|
check_registers(a);
|
|
}
|
|
};
|
|
|
|
actor.spawn = function (script, config) {
|
|
if (typeof script !== "string") return undefined;
|
|
|
|
var padawan = class_use(script, config, actor);
|
|
|
|
padawan.padawans = [];
|
|
padawan.timers = [];
|
|
padawan.master = this;
|
|
Object.hide(padawan, "master", "padawans");
|
|
padawan.toString = function () {
|
|
return script;
|
|
};
|
|
check_registers(padawan);
|
|
this.padawans.push(padawan);
|
|
if (padawan.awake) padawan.awake();
|
|
return padawan;
|
|
};
|
|
|
|
actor.tween = function (from, to, time, fn) {
|
|
var stop = tween(from, to, time, fn);
|
|
this.timers.push(stop);
|
|
return stop;
|
|
};
|
|
|
|
actor.spawn.doc = `Create a new actor, using this actor as the master, initializing it with 'script' and with data (as a JSON or Nota file) from 'config'.`;
|
|
|
|
actor.rm_pawn = function (pawn) {
|
|
this.padawans.remove(pawn);
|
|
};
|
|
|
|
actor.timers = [];
|
|
actor.kill = function () {
|
|
if (this.__dead__) return;
|
|
this.timers.forEach(t => t());
|
|
input.do_uncontrol(this);
|
|
Event.rm_obj(this);
|
|
if (this.master) this.master.rm_pawn(this);
|
|
this.padawans.forEach(p => p.kill());
|
|
this.padawans = [];
|
|
this.__dead__ = true;
|
|
actor_spawns[this._file].remove(this);
|
|
if (typeof this.die === "function") this.die();
|
|
if (typeof this.stop === "function") this.stop();
|
|
if (typeof this.garbage === "function") this.garbage();
|
|
if (typeof this.then === "function") this.then();
|
|
};
|
|
|
|
actor.kill.doc = `Remove this actor and all its padawans from existence.`;
|
|
|
|
actor.delay = function (fn, seconds) { prosperon.add_timer(this, fn, seconds); }
|
|
actor.delay.doc = `Call 'fn' after 'seconds' with 'this' set to the actor.`;
|
|
|
|
actor.interval = function (fn, seconds) {
|
|
var self = this;
|
|
var stop;
|
|
var usefn = function () {
|
|
fn();
|
|
stop = self.delay(usefn, seconds);
|
|
};
|
|
stop = self.delay(usefn, seconds);
|
|
|
|
return stop;
|
|
};
|
|
|
|
actor.padawans = [];
|
|
|
|
global.app = Object.create(actor);
|
|
app.die = function () {
|
|
os.exit(0);
|
|
};
|
|
|
|
return { actor, app };
|