Download Game! Currently 73 players and visitors. Last logged in:DefaultCorrelPaziIberiamssp

Blitzer's Blog >> 72032

Back to blogs index
Posted: 05 Sep 2026 09:53 [ permalink ]
This is a classic Message Broker (or Actor Model) pattern. By completely
decoupling the game state from the physical networking layer, your VM becomes
a pure state machine. It doesn't care if the data arrived via TCP, an IRC
signaling bridge, or a Cloudflare Worker edge tunnelit just reads from an
inbox and writes to an outbox.
Here is how we can architect this in-memory mailbox system to be entirely
plug-and-play.
1. The Memory Boundaries (The Queues)
At the boundary between the Node.js host and the GEM Virtual Machine, we
establish two simple arrays to act as our universal queues.
 * rt.__OUTBOX: A queue for outgoing messages generated by the game.
 * rt.__INBOX: A queue for incoming messages validated by the host.
2. The EFUN Facade (LPC Side)
To avoid rewriting all your legacy .c files immediately, we update
efuns.d/08_sockets.js to act as a facade. We map the old port-binding concepts
to pub/sub topics and routing keys.
 * socket_listen(port) becomes subscribe(topic). The LPC object registers
itself to receive messages tagged with a specific routing key.
 * socket_send(fd, msg) becomes publish(target, msg). The EFUN packages the
payload into a standard JSON envelopee.g., { target: "node-x", payload: msg,
timestamp: Date.now() }and pushes it to rt.__OUTBOX.
3. The Tick Processor (The Dispatcher)
Inside the VMs heart_beat cycle (or a dedicated process_messages tick), the
engine inspects rt.__INBOX.
 * If a message exists, it pops it from the queue and inspects the routing
metadata.
 * It then dynamically triggers the legacy callback (e.g., rt.call_other(target
_ob, "receive_bytes", payload)) on the correct LPC object.
4. The Transport Adapters (Host Side)
This is where the magic happens. Outside the VM, the Node.js event loop acts
as the router. You can plug in any transport adapter you want without touching
the game code.
 * Outbound: Node.js continuously polls (or uses an EventEmitter) to flush
rt.__OUTBOX. If the adapter is a mesh network, it grabs the payload, perhaps
encrypts it via AES-GCM, and routes it through a Tailscale tunnel or an
omega-mesh-edge endpoint.
 * Inbound: When your FastAPI service or peer node receives a payload, it
handles all the cryptographic verification and decryption outside the VM. Once
validated, it simply pushes the raw JSON envelope into rt.__INBOX.
This completely isolates your game logic. The VM operates in a zero-trust
vacuum, processing validated state changes from its inbox and handing off
updates to its outbox.
Do you want the VM to poll the __INBOX synchronously during its internal
heartbeat, or would you prefer the Node.js host to asynchronously inject
events directly into the VM's execution context?