Skip to content

Rebuild spatial video chat in a Minecraft-like 3D world (/world) - #36

Merged
souramoo merged 4 commits into
masterfrom
claude/spatial-video-chat-merge-823rz2
Jun 11, 2026
Merged

Rebuild spatial video chat in a Minecraft-like 3D world (/world)#36
souramoo merged 4 commits into
masterfrom
claude/spatial-video-chat-merge-823rz2

Conversation

@souramoo

Copy link
Copy Markdown
Owner

What this is

This PR merges the Fable5-mc voxel engine into party and rebuilds the spatial video chat concept with full functionality inside a Minecraft-like world, served at /world. The classic 2D experience stays untouched at /join.

How it works

Spatial video chat, but in 3D:

  • Walk up to someone to start a WebRTC call (PeerJS, same proximity-call model as the 2D app — lower id dials to avoid glare, walking away hangs up with hysteresis).
  • Voice is routed through WebAudio PannerNodes positioned at each avatar, so people are quieter with distance and panned by direction — real spatial audio.
  • Every player is a blocky avatar whose head face becomes their live webcam feed (THREE.VideoTexture) while a call is up, with a floating name tag and walk animation.
  • Joining without a camera/mic is allowed (you can still listen and build).

Shared persistent worlds:

  • A room code deterministically seeds the terrain (hash("party:" + room)), so the same code always generates the same world; the code travels in the URL hash (/world#treehouse).
  • Every block placed/broken is recorded server-side per room and replayed to late joiners; live edits, player positions (~12 Hz, interpolated client-side) and TNT ignitions are relayed within the room. Time of day is shared per room.
  • The full sandbox carries over: biomes, caves, ores, day/night, 35 block types, falling sand, synchronized TNT explosions (deterministic craters keep clients consistent), swimming, sprinting, sneaking, flying, F3 debug.

Architecture

  • src/client3d/ — the voxel engine (unchanged modules: noise, textures, blocks, worldgen, mesher, player, sky, particles, audio, entities) plus new multiplayer modules:
    • net.js — socket.io wrapper (w3:* messages)
    • rtc.js — PeerJS calls + WebAudio spatialization
    • avatar.js — avatar models, video faces, name tags, interpolation
    • world.js — gained onEdit broadcast hook + applyRemoteEdit/loadWorldEdits (remote edits apply silently and also into not-yet-generated chunks)
    • main.js/ui.js/index.html — join-a-room flow (name + room + webcam preview), self-view with mic/cam toggles, room status HUD; the menu no longer freezes the world (the party keeps going)
    • Served as native ES modules — no build step; three and peerjs are vendored straight from node_modules via express static routes.
  • src/server/world3d.js — room manager (seed, edit log with per-cell latest-wins, player list, input validation, room sweep), wired into the existing socket.io server alongside the 2D game with namespaced message types.
  • server.js — now loads webpack only in development, so the production server boots on modern Node (the webpack 4 build of the 2D client still needs Node ≤ 16 or --openssl-legacy-provider, as before).

Testing

  • npm test now runs:
    • 15 jest tests for the server room/edit/state logic (seed determinism, edit replay & dedup, room isolation, input validation, cleanup) — all passing.
    • 17 headless engine smoke tests (ported from Fable5-mc and extended with the multiplayer edit-sync paths) — all passing.
  • Verified end-to-end with the production server on Node 22: /world, vendored three.module.js/peerjs.min.js and the socket.io client all serve correctly, and a two-client socket.io session confirmed shared seed, edit replay to a late joiner, live block/state/leave relay.
  • The existing 2D webpack build still compiles (NODE_OPTIONS=--openssl-legacy-provider npm run build).

Not verified here: actual WebRTC media flow and WebGL rendering (no browser in this environment) — worth a quick two-tab manual test on a deployed instance.

https://claude.ai/code/session_01PucZtRi8jZbvQS1y11NKdb


Generated by Claude Code

Merge the Fable5-mc voxel engine into party to recreate the spatial
video chat concept in full 3D:

- src/client3d: the Three.js voxel engine (procedural terrain, biomes,
  caves, day/night, mining/placing, TNT, physics) served as native ES
  modules at /world with no build step, plus new multiplayer modules:
  - net.js: socket.io world sync (seed, block edits, player state)
  - rtc.js: PeerJS proximity calls with WebAudio-spatialized voice
  - avatar.js: blocky avatars with live webcam-texture faces & name tags
  - main.js/ui.js: join-a-room flow replacing the singleplayer title
- src/server/world3d.js: room manager — room codes deterministically
  seed worlds, block edits are stored and replayed to late joiners,
  positions/TNT relayed within the room; jest unit tests included
- server.js: wires the 3D handlers, serves /world and vendors
  three.js + peerjs from node_modules; webpack is now only loaded in
  development so production boots on modern Node
- test/engine.smoke.mjs: headless engine smoke tests incl. the new
  multiplayer edit-sync paths (npm test runs jest + smoke)
- landing page links to the 3D world; classic 2D app remains at /join

https://claude.ai/code/session_01PucZtRi8jZbvQS1y11NKdb
@socket-security

socket-security Bot commented Jun 11, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm cssom is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: package-lock.jsonnpm/cssom@0.3.8

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/cssom@0.3.8. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm doctrine is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: package-lock.jsonnpm/eslint-plugin-import@2.18.2npm/doctrine@1.5.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/doctrine@1.5.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

Copy link
Copy Markdown
Owner Author

Re the Socket alerts above: both cssom@0.3.8 and doctrine@1.5.0 are pre-existing transitive dev dependencies already present at these exact versions in master's lockfile (cssom@0.3.8 via jest → jsdom, doctrine@1.5.0 via eslint-plugin-import@2.18.2). They show up in the diff only because adding three regenerated package-lock.json in the newer lockfile v3 format, which rewrote those entries. This PR's only new dependency is three@0.169.0, which Socket raised no alerts for. The check concluded as neutral (non-blocking) — if you want to silence the warnings, reply @SocketSecurity ignore npm/cssom@0.3.8 and @SocketSecurity ignore npm/doctrine@1.5.0.


Generated by Claude Code

claude added 3 commits June 11, 2026 21:17
- Mic/camera are now controllable in game: M / V hotkeys with toasts,
  and the self-view (with its buttons) moved above the pause overlay
  so it stays clickable while the menu is open — previously the
  pointer lock plus menu backdrop made the toggles unreachable
- Call reliability: dials that never produce a media stream time out
  after 8s and are redialed on the next proximity tick; the PeerJS
  signalling connection auto-reconnects when dropped; peer-unavailable
  errors clear the stale attempt so it retries
- Runescape-style text chat: T or Enter opens a chat bar, messages
  appear as yellow word-wrapped bubbles above the sender's head for
  ~6s; server sanitizes (control chars, 120-char cap) and rate limits
  (1 msg / 750ms); covered by three new jest tests

https://claude.ai/code/session_01PucZtRi8jZbvQS1y11NKdb
- New touch.js: virtual joystick (analog move, push fully forward to
  sprint), drag-anywhere-to-look, and on-screen buttons for jump
  (double-tap toggles fly), sneak/fly-down, mine (hold) and place,
  plus menu / chat / block-picker taps along the top
- Touch UI is created only when the primary pointer is coarse and is
  display:none'd otherwise — desktop input is completely unchanged
- Pointer lock is skipped on touch devices; interaction (mining,
  outline, placing) now works without it in touch mode
- Layout adapts: self-view docks top-left, chat bar docks to the top
  (clear of the on-screen keyboard), hotbar becomes tappable, picker
  gains a close button, and the HUD/menus scale down on small screens
- Viewport meta pins scale so drags steer the camera instead of
  zooming the page

https://claude.ai/code/session_01PucZtRi8jZbvQS1y11NKdb
…ra switching

- / now serves the 3D world join screen (classic landing remains at
  /index.html, the 2D app at /join); client asset URLs made absolute
  so the page works from both / and /world/
- Join screen shows a live room preview via new GET /world-info/:room —
  who's in the room right now and how many blocks have been built
  (polled while typing and every 4s on the title screen)
- Worlds persist to disk: rooms + edits + day-clock save to
  data/world3d.json (WORLD3D_FILE to override) every 30s when dirty,
  atomically via tmp+rename, and on SIGINT/SIGTERM — builds survive
  server restarts; covered by new jest tests
- Minimap (north-up radar, HUD corner): height-shaded terrain sampled
  from loaded chunks at 2 Hz, white view arrow for you, a colored dot
  + initial per player, clamped to the edge when out of range
- Camera switching for multi-camera devices: C key or the new 🔄
  button cycles video inputs, preserving mute state and live calls
  via RTCRtpSender.replaceTrack

https://claude.ai/code/session_01PucZtRi8jZbvQS1y11NKdb
@souramoo
souramoo merged commit fd41617 into master Jun 11, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants