diff --git a/src/Memories.ts b/src/Memories.ts new file mode 100644 index 0000000..af0e7aa --- /dev/null +++ b/src/Memories.ts @@ -0,0 +1,17 @@ +import { Game } from "@game"; +import { Pawn } from "./Pawn.js"; + +export function injectTravelMemory(target: Pawn) { + return { + type: "travel", + time: { + age: target.age, + locale: Game.current.clock.toString() + }, + location: Game.current.name + } +} + +function injectMemory(pawn: Pawn, memory: any) { + pawn.memories.push(memory); +} \ No newline at end of file diff --git a/src/Memory.ts b/src/Memory.ts index 75e6095..6d150cb 100644 --- a/src/Memory.ts +++ b/src/Memory.ts @@ -20,6 +20,10 @@ export type BirthMemory = ProtoMemory & { location: string, } +export type AnyMemory = + TravelMemory + | BirthMemory; + export function stringify(memory: Memory): string { switch(memory.type) { case "birth": { diff --git a/src/multiplayer/mDNS.ts b/src/multiplayer/mDNS.ts index 2aeeed6..1eb13b6 100644 --- a/src/multiplayer/mDNS.ts +++ b/src/multiplayer/mDNS.ts @@ -11,66 +11,60 @@ import { inspect } from 'util' import { Pawn } from '../Pawn.js'; import { Game } from '../Game.js'; import { Player } from './Player.js'; +import { injectTravelMemory } from '../Memories.js'; const mdns = bonjour(); const ID = uuid.v4(); let devices: Player[] = []; const network = { - get players() { - return devices; - } + get players() { + return devices; + } } export type GiftMessage = { - pawns: string[], - from: string + pawns: string[], + from: string } export default network; export async function ready(name: string) { - const port = await getPort({port: getPort.makeRange(52300, 52399)}); - mdns.publish({ - type: 'dfi', - name, - port: port - }); - const wss = new WebSocket.Server({ port }); - wss.on('connection', function connection(ws) { - ws.on('message', function incoming(message) { - const {pawns: pawnJsons, from} = JSON.parse(message.toString()); - const pawns = []; - for(const pawnJson of pawnJsons) { - const pawn: Pawn = Pawn.fromJson(pawnJson); - pawn.memories.push({ - type: "travel", - time: { - age: pawn.age, - locale: Game.current.clock.toString() - }, - location: Game.current.name - }) - pawns.push(pawn); - } - Popup.show(`${(() => { - if(pawns.length === 0) return `A care package has arrived from ${from}.`; - if(pawns.length === 1) return `A traveler from ${from} named ${pawns[0].toString()} has arrived.`; - if(pawns.length > 1) return `A caravan of ${pawns.length} people from ${from} has arrived.` - })()}`); - for(const pawn of pawns) Game.current.pawns.push(pawn); - }); - }); + const port = await getPort({port: getPort.makeRange(52300, 52399)}); + mdns.publish({ + type: 'dfi', + name, + port: port + }); + const wss = new WebSocket.Server({ port }); + wss.on('connection', function connection(ws) { + ws.on('message', function incoming(message) { + const {pawns: pawnJsons, from} = JSON.parse(message.toString()); + const pawns = []; + for(const pawnJson of pawnJsons) { + const pawn: Pawn = Pawn.fromJson(pawnJson); + pawns.push(pawn); + injectTravelMemory(pawn); + } + Popup.show(`${(() => { + if(pawns.length === 0) return `A care package has arrived from ${from}.`; + if(pawns.length === 1) return `A traveler from ${from} named ${pawns[0].toString()} has arrived.`; + if(pawns.length > 1) return `A caravan of ${pawns.length} people from ${from} has arrived.` + })()}`); + for(const pawn of pawns) Game.current.pawns.push(pawn); + }); + }); } mdns.find({ - type: 'dfi' + type: 'dfi' }, (service) => { - const p = new Player(); - p.name = service.name; - p.host = service.host; - p.port = service.port; - devices.push(p); + const p = new Player(); + p.name = service.name; + p.host = service.host; + p.port = service.port; + devices.push(p); }).on("down", (service) => { - // TODO remove player from MP + // TODO remove player from MP }) \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index acf9e23..b135c68 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,6 +20,7 @@ }, "include": [ "src/**/*.ts", - "content/**/*.ts" + "content/**/*.ts", + "ui-engine/**/*.ts" ] } \ No newline at end of file diff --git a/ui-engine/Node.ts b/ui-engine/Node.ts new file mode 100644 index 0000000..67695f8 --- /dev/null +++ b/ui-engine/Node.ts @@ -0,0 +1,55 @@ +export abstract class Node { + x: number; + y: number; + w: number; + h: number; + children: Node[] + + constructor() { + this.children = []; + } + + layout(w: number, h: number) { + this.w = w; + this.h = h; + + this.onResize(w, h); + + this.children.forEach(node => node.layout(w, h)); + } + + append(child: Node) { + this.children.push(child); + this.layout(this.w, this.h); + } + + abstract render(x: number, y: number): [number, string]; + + abstract onResize(w: number, h: number): void +} + + +export class TextNode extends Node { + _content: string; + + constructor(content: string) { + super(); + this.content = content; + } + + set content(val: string) { + this._content = val + this.layout(this.w, this.h); + } + + onResize(w: number, h: number): void { + return; + } + + render(x: number, y: number): [number, string] { + if(y !== this.y) return null; + if(x < this.x) return null; + if(x > this.x + this.content.length) return null; + return [0, this.content[x - this.x]]; + } +} \ No newline at end of file diff --git a/ui-engine/index.ts b/ui-engine/index.ts new file mode 100644 index 0000000..c055b4e --- /dev/null +++ b/ui-engine/index.ts @@ -0,0 +1,62 @@ +import ansi from 'sisteransi'; +import { Node, TextNode } from './Node.js'; + + +const TERMINAL_HIGH_BUFFER = '\x1b[?1049h'; +const TERMINAL_LOW_BUFFER = '\x1b[?1049l' + +class Screen extends Node { + buffer: ArrayBuffer; + bufferView: Uint8Array; + paletteBuffer: ArrayBuffer; + paletteBufferView: Uint8Array; + + constructor() { + super(); + process.stdout.write(TERMINAL_HIGH_BUFFER); + process.stdout.write(ansi.cursor.hide); + this.layout(process.stdout.columns, process.stdout.rows); + } + + onResize(w: number, h: number) { + this.buffer = new ArrayBuffer(w * h); + this.bufferView = new Uint8Array(this.buffer); + this.paletteBuffer = new ArrayBuffer(w * h); + this.paletteBufferView = new Uint8Array(this.paletteBuffer); + } + + // paletteAt(x: number, y: number) { + + // } + + offset(x: number, y: number) { + return y * this.h + x + } + + updateTerminal() { + process.stdout.write(ansi.cursor.to(0, 0)) + for(let y = 0; y < this.h; y ++) { + for(let x = 0; x < this.w; x ++) { + + } + process.stdout.write('\r\n') + } + } + + render(x: number, y: number): [number, string] { + throw new Error('Method not implemented.'); + } + + destroy() { + process.stdout.write(TERMINAL_LOW_BUFFER); + process.stdout.write(ansi.cursor.show); + } +} + +// class Palette { + +// } + + +const screen = new Screen(); +screen.append(new TextNode('Test')) \ No newline at end of file