rkgk/static/online-users.js

145 lines
4.4 KiB
JavaScript
Raw Normal View History

import { ContKind, Haku } from "rkgk/haku.js";
import { renderToChunksInArea, dotterRenderArea } from "rkgk/painter.js";
2024-08-15 20:01:23 +02:00
export class User {
nickname = "";
brush = "";
reticle = null;
isBrushOk = false;
simulation = null;
2024-08-15 20:01:23 +02:00
constructor(wallInfo, nickname) {
this.nickname = nickname;
this.haku = new Haku(wallInfo.hakuLimits);
}
destroy() {
this.haku.destroy();
}
2024-08-15 20:01:23 +02:00
setBrush(brush) {
2024-09-03 22:16:28 +02:00
console.groupCollapsed("setBrush", this.nickname);
2024-08-15 20:01:23 +02:00
let compileResult = this.haku.setBrush(brush);
console.log("compiling brush complete", compileResult);
console.groupEnd();
2024-08-15 20:01:23 +02:00
this.isBrushOk = compileResult.status == "ok";
2024-08-15 20:01:23 +02:00
return compileResult;
}
renderBrushToChunks(wall, x, y) {
2024-09-03 22:16:28 +02:00
console.groupCollapsed("renderBrushToChunks", this.nickname);
let result = this.painter.renderBrushToWall(this.haku, x, y, wall);
console.log("rendering brush to chunks complete");
console.groupEnd();
return result;
2024-08-15 20:01:23 +02:00
}
simulate(wall, interactions) {
console.group("simulate");
for (let interaction of interactions) {
if (interaction.kind == "setBrush") {
this.simulation = null;
this.setBrush(interaction.brush);
}
if (this.isBrushOk) {
if (this.simulation == null) {
console.log("no simulation -- beginning brush");
this.simulation = { renderArea: { left: 0, top: 0, right: 0, bottom: 0 } };
this.haku.beginBrush();
}
if (interaction.kind == "dotter" && this.#expectContKind(ContKind.Dotter)) {
let dotter = {
fromX: interaction.from.x,
fromY: interaction.from.y,
toX: interaction.to.x,
toY: interaction.to.y,
num: interaction.num,
};
this.haku.contDotter(dotter);
this.simulation.renderArea = dotterRenderArea(wall, dotter);
}
if (interaction.kind == "scribble" && this.#expectContKind(ContKind.Scribble)) {
renderToChunksInArea(
wall,
this.simulation.renderArea,
(pixmap, translationX, translationY) => {
return this.haku.contScribble(pixmap, translationX, translationY);
},
);
console.log("ended simulation");
this.simulation = null;
}
}
}
console.groupEnd();
}
#expectContKind(kind) {
if (this.haku.expectedContKind() == kind) {
return true;
} else {
console.error(`expected cont kind: ${kind}`);
return false;
}
}
getStats(wallInfo) {
return {
astSize: this.haku.astSize,
astSizeMax: wallInfo.hakuLimits.ast_capacity,
numRefs: this.haku.numRefs,
numRefsMax: wallInfo.hakuLimits.ref_capacity,
fuel: wallInfo.hakuLimits.fuel - this.haku.remainingFuel,
fuelMax: wallInfo.hakuLimits.fuel,
memory: wallInfo.hakuLimits.memory - this.haku.remainingMemory,
memoryMax: wallInfo.hakuLimits.memory,
};
}
2024-08-15 20:01:23 +02:00
}
2024-08-10 23:13:20 +02:00
export class OnlineUsers extends EventTarget {
2024-08-15 20:01:23 +02:00
#wallInfo;
2024-08-10 23:13:20 +02:00
#users = new Map();
2024-08-15 20:01:23 +02:00
constructor(wallInfo) {
2024-08-10 23:13:20 +02:00
super();
2024-08-15 20:01:23 +02:00
this.#wallInfo = wallInfo;
2024-08-10 23:13:20 +02:00
}
2024-08-15 20:01:23 +02:00
addUser(sessionId, { nickname, brush }) {
if (!this.#users.has(sessionId)) {
console.info("user added", sessionId, nickname);
let user = new User(this.#wallInfo, nickname);
user.setBrush(brush);
this.#users.set(sessionId, user);
return user;
} else {
console.info("user already exists", sessionId, nickname);
return this.#users.get(sessionId);
}
2024-08-10 23:13:20 +02:00
}
getUser(sessionId) {
return this.#users.get(sessionId);
}
removeUser(sessionId) {
2024-08-15 20:01:23 +02:00
if (this.#users.has(sessionId)) {
let user = this.#users.get(sessionId);
user.destroy();
2024-08-15 20:01:23 +02:00
console.info("user removed", sessionId, user.nickname);
// TODO: Cleanup reticles
this.#users.delete(sessionId);
}
2024-08-10 23:13:20 +02:00
}
}