Back to Browser Side Quest
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.

src/net/local.ts
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);
  }
}