SOURCE / PINNED RELEASE
Made of little things.
Browser Side Quest
- Release
- b9d42f5768e4…
- Author-recorded commit
- c267690145fa…
- License
- LICENSE
- Author’s source reference
- nostr://npub1ye5ptcxfyyxl5vjvdjar2ua3f0hynkjzpx552mu5snj3qmx5pzjscpknpr/wss%3A%2F%2Fgit.shakespeare.diy%2F/browser-side-quest
Archive hash verified: 6d4b90b8a5f328f7…. The source-to-build association is the author’s claim; it has not been independently rebuilt.
import type { Message } from '../sim/entities.js';
import type { Player as SessionPlayer } from '../sim/player.js';
import type { World } from '../sim/world.js';
import type { Transport, TransportHandlers } from './transport.js';
/**
* Connects a client to a World running in the same tab. Delivery is async in
* both directions, like the original network round trip, so the ported client
* and world never re-enter each other mid-handler.
*/
export class LocalTransport implements Transport {
private session: SessionPlayer | null = null;
private handlers: TransportHandlers | null = null;
private closed = false;
constructor(
private readonly world: World,
private readonly resume?: { x: number; y: number; checkpoint?: number },
) {}
connect(handlers: TransportHandlers): void {
this.handlers = handlers;
const id = this.world.nextConnectionId();
this.session = this.world.connect(
{
id,
send: (messages: Message[]) => {
const batch = messages.slice();
queueMicrotask(() => {
if (!this.closed) this.handlers?.onMessage(batch);
});
},
close: (reason: string) => this.shutdown(reason),
},
this.resume,
);
queueMicrotask(() => {
if (!this.closed) handlers.onReady();
});
}
send(message: unknown[]): void {
const copy = JSON.parse(JSON.stringify(message)) as unknown[];
queueMicrotask(() => {
if (!this.closed) this.session?.receive(copy);
});
}
close(): void {
this.shutdown('closed');
}
private shutdown(reason: string): void {
if (this.closed) return;
this.closed = true;
this.session?.disconnect();
this.session = null;
const handlers = this.handlers;
this.handlers = null;
if (reason !== 'closed') handlers?.onClose(reason);
}
}
