game-freddies-adventure/assets/js/loader.js

169 lines
4.8 KiB
JavaScript
Raw Normal View History

2023-10-12 11:29:13 -04:00
var channelHandlers = {}
function addSimMessageHandler(channel, handler) {
channelHandlers[channel] = handler;
}
function makeCodeRun(options) {
var code = "";
var isReady = false;
var simState = {}
var simStateChanged = false
var started = false;
var meta = undefined;
// hide scrollbar
window.scrollTo(0, 1);
// init runtime
initSimState();
fetchCode();
// helpers
function fetchCode() {
sendReq(options.js, function (c, status) {
if (status != 200)
return;
code = c;
// find metadata
code.replace(/^\/\/\s+meta=([^\n]+)\n/m, function (m, metasrc) {
meta = JSON.parse(metasrc);
})
var vel = document.getElementById("version");
if (meta.version && meta.repo && vel) {
var ap = document.createElement("a");
ap.download = "arcade.uf2";
ap.href = "https://github.com/" + meta.repo + "/releases/download/v" + meta.version + "/arcade.uf2";
ap.innerText = "v" + meta.version;
vel.appendChild(ap);
}
// load simulator with correct version
document.getElementById("simframe")
.setAttribute("src", meta.simUrl);
initFullScreen();
})
}
function startSim() {
if (!code || !isReady || started)
return
setState("run");
started = true;
const runMsg = {
type: "run",
parts: [],
code: code,
partDefinitions: {},
cdnUrl: meta.cdnUrl,
version: meta.target,
storedState: simState,
frameCounter: 1,
options: {
"theme": "green",
"player": ""
},
id: "green-" + Math.random()
}
postMessage(runMsg);
}
function stopSim() {
setState("stopped");
postMessage({
type: "stop"
});
started = false;
}
window.addEventListener('message', function (ev) {
var d = ev.data
if (d.type == "ready") {
var loader = document.getElementById("loader");
if (loader)
loader.remove();
isReady = true;
startSim();
} else if (d.type == "simulator") {
switch (d.command) {
case "restart":
stopSim();
startSim();
break;
case "setstate":
if (d.stateValue === null)
delete simState[d.stateKey];
else
simState[d.stateKey] = d.stateValue;
simStateChanged = true;
break;
}
} else if (d.type === "messagepacket" && d.channel) {
const handler = channelHandlers[d.channel]
if (handler) {
try {
const buf = d.data;
const str = uint8ArrayToString(buf);
const data = JSON.parse(str)
handler(data);
} catch (e) {
console.log(`invalid simmessage`)
console.log(e)
}
}
}
}, false);
// helpers
function uint8ArrayToString(input) {
let len = input.length;
let res = ""
for (let i = 0; i < len; ++i)
res += String.fromCharCode(input[i]);
return res;
}
function setState(st) {
var r = document.getElementById("root");
if (r)
r.setAttribute("data-state", st);
}
function postMessage(msg) {
const frame = document.getElementById("simframe");
if (frame)
frame.contentWindow.postMessage(msg, meta.simUrl);
}
function sendReq(url, cb) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (xhttp.readyState == 4) {
cb(xhttp.responseText, xhttp.status)
}
};
xhttp.open("GET", url, true);
xhttp.send();
}
function initSimState() {
try {
simState = JSON.parse(localStorage["simstate"])
} catch (e) {
simState = {}
}
setInterval(function () {
if (simStateChanged)
localStorage["simstate"] = JSON.stringify(simState)
simStateChanged = false
}, 200)
}
function initFullScreen() {
var sim = document.getElementById("simframe");
var fs = document.getElementById("fullscreen");
if (fs && sim.requestFullscreen) {
fs.onclick = function() { sim.requestFullscreen(); }
} else if (fs) {
fs.remove();
}
}
}