diff options
| author | LLLL Colonq <llll@colonq> | 2024-11-05 02:58:33 -0500 |
|---|---|---|
| committer | LLLL Colonq <llll@colonq> | 2024-11-05 02:58:33 -0500 |
| commit | cf0070ac5a78d8042fa74d407fb9cb65352e2066 (patch) | |
| tree | 85fb5cee6c7533b7ae6de846ed447772d7b67296 /src/Model.js | |
Initial commit
Diffstat (limited to 'src/Model.js')
| -rw-r--r-- | src/Model.js | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/src/Model.js b/src/Model.js new file mode 100644 index 0000000..797bae4 --- /dev/null +++ b/src/Model.js @@ -0,0 +1,108 @@ +let canvas = document.getElementById("lcolonq-canvas"); +let socket = null; +let currentFrame = null; + +async function decompress(blob) { + let ds = new DecompressionStream("gzip"); + let stream = blob.stream(); + let out = await new Response(stream.pipeThrough(ds)); + return out.arrayBuffer(); +} + +function readCell(dv, base) { + let cell = {}; + let o = base; + if (dv.getUint8(o) == 0) { + return [{type: "bg"}, o + 1]; + } else { + cell.type = "fg"; + cell.custom = dv.getUint8(o + 1); + cell.r = dv.getUint8(o + 2); + cell.g = dv.getUint8(o + 3); + cell.b = dv.getUint8(o + 4); + cell.g0 = dv.getUint32(o + 5); + if (dv.getUint8(o + 9) == 0) { + return [cell, o + 10]; + } else { + cell.g1 = dv.getUint32(o + 10); + return [cell, o + 14]; + } + } +} + +function readKeyframe(dv, base) { + let ret = []; + let o = base; + for (let idx = 0; idx < (64 * 64); ++idx) { + let res = readCell(dv, o); + ret.push(res[0]); + o = res[1]; + } + currentFrame = ret; +} + +function readDiff(dv, base) { + if (currentFrame) { + let len = dv.getUint32(base); + let o = base + 4; + for (let idx = 0; idx < len; ++idx) { + let x = dv.getUint8(o); + let y = dv.getUint8(o + 1); + let c = readCell(dv, o + 2); + currentFrame[x + (y * 64)] = c[0]; + o = c[1]; + } + } +} + +function readPacket(dv) { + if (dv.getUint8(0) == 0) { + readKeyframe(dv, 1); + } else { + readDiff(dv, 1); + } +} + +function renderCellCanvas(ctx, x, y, c) { + if (c && c.type === "fg") { + let msg = c.g1 ? String.fromCodePoint(c.g0, c.g1) : String.fromCodePoint(c.g0); + if (msg.trim().length) { + ctx.fillStyle = "black"; + ctx.fillRect(13 * y, 13 * x, 13, 13); + ctx.fillStyle = `rgba(${c.r}, ${c.g}, ${c.b}, 1.0)`; + ctx.fillText(msg, 13 * y, 13 * x + 10); + } + } +} + +function renderCanvas() { + if (canvas.width != canvas.clientWidth) { + canvas.width = canvas.clientWidth; + } + if (canvas.height != canvas.clientHeight) { + canvas.height = canvas.clientHeight; + } + if (currentFrame) { + let ctx = canvas.getContext("2d"); + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.font = "12px Iosevka Comfy"; + for (let y = 0; y < 64; ++y) { + for (let x = 0; x < 64; ++x) { + renderCellCanvas(ctx, x, y, currentFrame[(x * 64) + y]); + } + } + } +} + +export const _startModel = () => { + socket = new WebSocket("wss://colonq.computer/bullfrog/api/channel/listen/model"); + socket.addEventListener("open", (ev) => { + console.log("connected"); + }); + socket.addEventListener("message", async (ev) => { + let arr = await decompress(ev.data); + let view = new DataView(arr); + readPacket(view); + renderCanvas(); + }); +}; |
