Skip to main content

Overview

The @hyperscape/shared package is the core Hyperscape engine, providing:
  • Entity Component System (ECS)
  • Three.js 3D rendering
  • PhysX physics simulation
  • Real-time networking
  • React UI components
  • Game data manifests

Package Location

packages/shared/
├── src/
│   ├── components/     # ECS components
│   ├── constants/      # Game constants
│   ├── core/           # Core engine classes
│   ├── data/           # Game manifests (npcs, items, etc.)
│   ├── entities/       # Entity definitions
│   │   ├── player/     # PlayerEntity, PlayerLocal, PlayerRemote
│   │   ├── npc/        # MobEntity, NPCEntity
│   │   ├── world/      # World entities
│   │   └── managers/   # Entity managers
│   ├── extras/         # Additional utilities
│   ├── libs/           # External integrations
│   ├── nodes/          # Scene graph nodes
│   ├── physics/        # PhysX wrapper
│   ├── platform/       # Platform detection
│   ├── runtime/        # Game loop
│   ├── systems/        # ECS systems
│   │   ├── client/     # Client-only systems
│   │   ├── server/     # Server-only systems
│   │   └── shared/     # Shared systems (combat, economy, etc.)
│   ├── types/          # TypeScript types
│   └── utils/          # Helper functions
├── index.ts            # Server exports
└── index.client.ts     # Client exports

Rendering

WebGPU with WebGL Fallback

The shared package includes renderer factory utilities for creating renderers with automatic fallback:
// From src/utils/rendering/RendererFactory.ts
import { createRenderer, isWebGPURenderer, getRendererBackend } from '@hyperscape/shared';

// Create renderer (WebGPU preferred, WebGL fallback)
const renderer = await createRenderer({
  antialias: true,
  powerPreference: "high-performance",
});

// Check backend
const isWebGPU = isWebGPURenderer(renderer);  // true or false
const backend = getRendererBackend(renderer); // "webgpu" or "webgl"
Renderer Features:
  • Automatic WebGPU detection and fallback to WebGL
  • Works in WKWebView (Tauri), older Safari, and browsers without WebGPU
  • Configurable shadow maps and post-processing
  • Max anisotropy detection
Environment System:
  • Auto exposure for day/night cycle (mimics eye adaptation)
  • Cascaded shadow maps (WebGPU) or single directional shadows (WebGL)
  • Dynamic ambient lighting based on time of day
  • Fog color transitions

Key Exports

Entity Hierarchy

The entity system follows a clear inheritance pattern:
// From packages/shared/src/entities/Entity.ts (lines 26-38)
// Entity (base class)
// ├── InteractableEntity (can be interacted with)
// │   ├── ResourceEntity (trees, rocks, fishing spots)
// │   ├── ItemEntity (ground items)
// │   └── NPCEntity (dialogue, shops)
// ├── CombatantEntity (can fight)
// │   ├── PlayerEntity (base player)
// │   │   ├── PlayerLocal (client-side local player)
// │   │   └── PlayerRemote (client-side remote players)
// │   └── MobEntity (enemies)
// └── HeadstoneEntity (player death markers)
ExportPurpose
EntityBase entity class with components, physics, networking
CombatantEntityCombat-capable entities with health, damage
InteractableEntityObjects players can interact with
PlayerEntityServer-side player with full stats, inventory
PlayerLocalClient-side local player with input handling
PlayerRemoteClient-side representation of other players
MobEntityNPCs and hostile mobs with AI states
HeadstoneEntityDeath marker for item retrieval

Systems (Shared)

Located in src/systems/shared/:
CategorySystems
character/Character stats, equipment, skills, inventory
combat/Combat mechanics, damage, death, aggro
death/Death handling, respawn, safe zones
economy/Banks, shops, trading, loot
entities/Entity lifecycle, spawning, resource management
interaction/Player-world interactions, dialogue, processing
movement/Tile-based movement, collision, pathfinding
presentation/Visual rendering, particles, music
progression/Quest system, achievements
tick/Game tick processing, NPC AI
world/Terrain generation, flat zones, biomes, vegetation

Collision System

The movement system includes a unified collision matrix for OSRS-accurate tile blocking:
// From packages/shared/src/systems/shared/movement/
export { CollisionMatrix } from './CollisionMatrix';
export { CollisionFlag, CollisionMask } from './CollisionFlags';
export { EntityOccupancyMap } from './EntityOccupancyMap';
export { TileSystem } from './TileSystem';
Key Exports:
ExportPurpose
CollisionMatrixZone-based collision storage (8×8 tile zones)
CollisionFlagBitmask flags (BLOCKED, WATER, OCCUPIED, walls)
CollisionMaskCombined masks (BLOCKS_WALK, BLOCKS_MOVEMENT)
EntityOccupancyMapEntity tracking facade over CollisionMatrix
tilesWithinRangeOfFootprintMulti-tile interaction range checks
Usage:
import { CollisionMatrix, CollisionMask } from '@hyperscape/shared';

const collision = new CollisionMatrix();

// Check if tile is walkable
if (!collision.hasFlags(x, z, CollisionMask.BLOCKS_WALK)) {
  // Safe to move
}

// Add blocking for a tree
collision.addFlags(x, z, CollisionFlag.BLOCKED);

Data Manifests

Game content is defined in TypeScript files in src/data/:
FilePurpose
DataManager.tsRuntime loader for manifests
npcs.tsNPC/mob definitions with drops, stats
items.tsItem definitions with stats, requirements
world-areas.tsZone configuration
banks-stores.tsShop inventories and bank locations
avatars.tsVRM avatar options
playerEmotes.tsEmote animation URLs
world-structure.tsWorld layout and spawn points
equipment-stats.jsonEquipment bonuses
equipment-requirements.jsonLevel requirements
NPC data is loaded from JSON manifests at runtime by DataManager. Add new NPCs in world/assets/manifests/npcs.json.

Skill Unlocks API

The skill unlocks system provides functions for querying what players unlock at each level:
import { 
  getAllSkillUnlocks,
  getUnlocksAtLevel,
  getUnlocksUpToLevel,
  loadSkillUnlocks,
  type SkillUnlock
} from '@hyperscape/shared';

// Load from manifest (called by DataManager)
loadSkillUnlocks(manifest);

// Get all unlocks for a skill
const attackUnlocks = getAllSkillUnlocks()["attack"];

// Get unlocks at specific level
const level40Unlocks = getUnlocksAtLevel("attack", 40);
// Returns: [{ level: 40, description: "Rune weapons", type: "item" }]

// Get all unlocks up to level
const unlockedSoFar = getUnlocksUpToLevel("attack", 45);
Defence/Defense Normalization: The system automatically handles British/American spelling:
// skill-unlocks.json uses "defence" (OSRS-accurate)
// UI uses "defense" (codebase convention)
// Both work - normalization happens at load time
const defenceUnlocks = getAllSkillUnlocks()["defence"];  // Works
const defenseUnlocks = getAllSkillUnlocks()["defense"];  // Also works
This allows the manifest to use OSRS-accurate British spelling while the codebase uses American spelling consistently.

Entry Points

Server (index.ts)

Exports for server-side usage:
import { 
  Entity, 
  DataManager, 
  PlayerEntity,
  MobEntity 
} from '@hyperscape/shared';

Client (index.client.ts)

Exports for client-side usage:
import { 
  Entity, 
  PlayerLocal,
  PlayerRemote 
} from '@hyperscape/shared/client';

Dependencies

PackageVersionPurpose
three0.181.03D rendering
@pixiv/three-vrm3.4.3VRM avatar support
@hyperscape/physx-js-webidlworkspacePhysics
react^19.2.0UI components
fastify^5.0.0HTTP server (server builds)
livekit-client^2.9.9Voice chat

Recent Changes

Terrain Flattening System (PR #644)

The terrain system now supports flat zones under stations for proper building placement:
  • FlatZone interface — Defines rectangular flat areas with smooth blending
  • Spatial indexing — O(1) flat zone lookup using terrain tiles
  • Manifest-driven — Stations configure flattenGround, flattenPadding, flattenBlendRadius
  • Dynamic registrationregisterFlatZone(), unregisterFlatZone(), getFlatZoneAt()
See Terrain System for details.

Equipment System Fixes (PR #641)

Atomic equip/unequip operations prevent item duplication:
  • Transaction locks prevent race conditions
  • Order of operations — Remove from inventory FIRST (equip), clear equipment FIRST (unequip)
  • Rollback on failure — Restores state if operation fails
  • New helper methodshasSpace(), hasItemAtSlot(), removeItemDirect(), addItemDirect()

Building

cd packages/shared
bun run build    # Production build
bun run dev      # Watch mode with auto-rebuild
Shared must be built before other packages that depend on it. Turbo handles this automatically.

Key Patterns

ECS Architecture

All game logic uses Entity Component System. See ECS Concepts.

Manifest-Driven Data

Game content defined in src/data/. See Manifests.

Type Safety

Strong TypeScript typing throughout—no any types allowed. ESLint enforces this rule.

Dual Entry Points

  • index.ts: Server-side exports (includes Fastify, database utilities)
  • index.client.ts: Client-side exports (browser-compatible)