Overview
Hyperscape is a real-time multiplayer game using WebSocket connections for low-latency communication between clients and the authoritative server.Network Architecture
Server Authority
The server is the single source of truth:Clients predict movement locally but server corrects if needed.
Entity Synchronization
Sync Flow
- Server processes game tick (600ms)
- Entity changes collected via
markNetworkDirty() - Delta updates sent to clients at 20 Hz
- Clients apply updates and interpolate
Entity Network Data
Sync Data
Equipment Synchronization
Equipment visibility is synchronized across all players with proper VRM avatar loading:- On player join: Server sends existing players’ equipment to joiner
- On player join: Server broadcasts joiner’s equipment to all other players
- On equipment change: Server broadcasts update to all nearby players
- On reconnect: Server re-sends all equipment (packets may be lost during disconnect)
getAvatar() helper resolves VRM from both PlayerLocal and PlayerRemote:
Position Synchronization
Player positions are synchronized with spatial index updates to ensure proper network visibility:sendToNearby() queries:
- Spatial index now updated after teleport (fixes invisible combat movement in duels)
- Spatial index updated after respawn (fixes missing entity broadcasts)
- Authoritative position broadcast to all players on join (fixes initial transform sync)
Remote Avatar Transform Sync
Remote player avatars are positioned and animated before being made visible to prevent T-pose flashing:visible=true before instance.move() positioned it, causing one frame of T-pose at (0,0,0)
After Fix: Avatar positioned and animated into idle pose before visibility enabled
Quaternion Sync:
Remote player quaternions are now properly synced to prevent sideways-facing avatars:
base.quaternion not synced, causing remote players to face sideways
After Fix: Both position and quaternion synced to base transform for correct orientation
WebSocket Protocol
Connection
Message Types
Persistence
Database Schema
Player data stored in PostgreSQL using Drizzle ORM:Save Strategy
- Immediate: Critical changes (item transactions)
- Periodic: Stats, position (every 30 seconds)
- On disconnect: Full state save
Authentication
Using Privy for identity:- Client authenticates with Privy
- JWT token sent to server
- Server validates token
- Session established
LiveKit Integration
Optional voice chat via LiveKit:- Spatial audio based on position
- Push-to-talk or voice activation
- Server-managed rooms
LIVEKIT_API_KEY and LIVEKIT_API_SECRET.
Scalability
Current Architecture
- Single server instance
- All players in shared world
- SQLite for development, PostgreSQL for production
Future Considerations
- Multiple server instances
- Zone-based sharding
- Load balancing