2024-09-08 13:53:29 +02:00
|
|
|
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;
|
2024-09-08 13:53:29 +02:00
|
|
|
simulation = null;
|
2024-08-15 20:01:23 +02:00
|
|
|
|
|
|
|
constructor(wallInfo, nickname) {
|
|
|
|
this.nickname = nickname;
|
|
|
|
this.haku = new Haku(wallInfo.hakuLimits);
|
|
|
|
}
|
|
|
|
|
2024-08-22 20:49:24 +02:00
|
|
|
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);
|
2024-09-02 20:14:20 +02:00
|
|
|
console.log("compiling brush complete", compileResult);
|
|
|
|
console.groupEnd();
|
|
|
|
|
2024-08-15 20:01:23 +02:00
|
|
|
this.isBrushOk = compileResult.status == "ok";
|
2024-09-02 20:14:20 +02:00
|
|
|
|
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);
|
2024-09-02 20:14:20 +02:00
|
|
|
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
|
|
|
}
|
2024-09-08 13:53:29 +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;
|
|
|
|
}
|
|
|
|
}
|
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);
|
2024-08-22 20:49:24 +02:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|