Skip to main content

Architecture Overview

Hyperscape is built on a custom 3D multiplayer engine using Entity Component System (ECS) architecture. The engine lives in packages/shared/ and provides:
  • Entity Component System — Game object architecture
  • Three.js Integration — 3D rendering (v0.180.0)
  • PhysX Bindings — Physics simulation via WASM
  • Real-time Networking — WebSocket multiplayer sync
  • React UI Components — In-game interface
The engine is designed as a general-purpose 3D world engine. The RPG-specific code is conceptually isolated from core engine systems.

Core Package Structure

packages/shared/src/
├── components/          # ECS component definitions
├── constants/           # Game constants (combat, physics)
├── core/                # Core engine classes (World, etc.)
├── data/                # Game manifests (loaded at runtime)
├── entities/            # Entity definitions (Player, Mob, Item)
├── extras/              # Additional utilities
├── libs/                # Third-party integrations
├── nodes/               # Scene graph nodes
├── physics/             # PhysX wrapper
├── platform/            # Platform-specific code
├── runtime/             # Runtime environment
├── systems/             # ECS systems (combat, economy, etc.)
├── types/               # TypeScript type definitions
└── utils/               # Utility functions

ECS Architecture

The game uses a strict Entity Component System pattern where:
ConceptDescriptionLocation
EntitiesGame objects (players, mobs, items, trees)entities/
ComponentsData containers (position, health, inventory)components/
SystemsLogic processors (combat, skills, movement)systems/
All game logic runs through systems, not entity methods. Entities are pure data containers.

Components

Components are pure data containers attached to entities:
components/
├── ColliderComponent.ts      # Physics collision data
├── CombatComponent.ts        # Combat state and stats
├── Component.ts              # Base component class
├── DataComponent.ts          # Generic data storage
├── HealthComponent.ts        # Health and regeneration
├── InteractionComponent.ts   # Interactable state
├── MeshComponent.ts          # 3D mesh reference
├── StatsComponent.ts         # Skill levels and XP
├── TransformComponent.ts     # Position, rotation, scale
├── UsageComponent.ts         # Item usage data
└── VisualComponent.ts        # Visual appearance

Systems

Systems process entities and implement game logic:
systems/
├── client/                   # Client-only systems
├── server/                   # Server-only systems
└── shared/                   # Shared systems (run on both)
    ├── character/            # Character-related systems
    ├── combat/               # Combat system (20+ files)
    ├── death/                # Death and respawn
    ├── economy/              # Banks, shops, trading
    ├── entities/             # Entity management
    ├── infrastructure/       # Core infrastructure
    ├── interaction/          # Player interactions
    ├── movement/             # Movement and pathfinding
    ├── presentation/         # Visual presentation
    ├── tick/                 # Game tick system
    └── world/                # World management

The World Class

The World class is the central orchestrator that manages all entities, components, and systems:
// Getting systems from the world
const combatSystem = world.getSystem('combat') as CombatSystem;

// Querying entities by type
const players = world.getEntitiesByType('Player');

// Event handling
world.on('inventory:add', (event: InventoryAddEvent) => {
  // Handle event
});
Source: packages/shared/src/core/World.ts

Entity Types

The engine defines several entity types in entities/:
entities/
├── Entity.ts                 # Base entity class
├── CombatantEntity.ts        # Entity that can fight
├── InteractableEntity.ts     # Entity that can be interacted with
├── managers/                 # Entity management utilities
├── npc/
│   └── MobEntity.ts          # NPCs and monsters
├── player/
│   └── PlayerEntity.ts       # Player characters
└── world/
    ├── ItemEntity.ts         # Items in the world
    ├── ResourceEntity.ts     # Trees, fishing spots, etc.
    └── ...

Entity Hierarchy


Type System

Hyperscape uses a modular type system with types split across multiple files:
types/
├── core/
│   ├── core.ts               # Re-export hub (backward compat)
│   ├── base-types.ts         # Position3D, Vector types
│   ├── identifiers.ts        # EntityID, ItemID, etc.
│   └── misc-types.ts         # Shared miscellaneous types
├── entities/
│   ├── entity-types.ts       # ECS component types
│   ├── player-types.ts       # Player-related types
│   └── npc-mob-types.ts      # NPC and mob types
├── game/
│   ├── combat-types.ts       # Combat types
│   ├── item-types.ts         # Item/equipment types
│   ├── inventory-types.ts    # Inventory and banking
│   ├── interaction-types.ts  # Interaction system
│   └── spawning-types.ts     # Spawn points and respawn
├── world/
│   └── world-types.ts        # World, zones, biomes, chunks
├── systems/
│   └── system-types.ts       # System configuration
└── events/
    └── events.ts             # Event type definitions
New code should import from specific type files for better organization. All types are also re-exported from types/core/core.ts for backward compatibility.

TypeScript Rules

Hyperscape enforces strict TypeScript rules:
any is forbidden by ESLint. Use specific types, union types, or generic constraints instead.
// ❌ FORBIDDEN
const player: any = getEntity(id);

// ✅ CORRECT
const player = getEntity(id) as Player;
Classes provide runtime type information and better instanceof checks.
// ✅ Preferred
class Player {
  constructor(
    public id: string,
    public health: number
  ) {}
}
When you know the type from context, assert it confidently.
// ✅ Good - we know the world has these systems
const combatSystem = world.getSystem('combat') as CombatSystem;
For type-only imports, use import type to avoid circular dependencies.
import type { Player, Mob } from '../types';

Build System

The engine uses Turbo for monorepo builds with dependency ordering:
// turbo.json
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    }
  }
}
Build order is automatically handled:
  1. physx-js-webidl (PhysX WASM)
  2. shared (depends on physx)
  3. All other packages (depend on shared)

Detailed Documentation

ECS Deep Dive

Deep dive into entities, components, systems, and the World class with full code examples.

Combat System

OSRS-accurate tick-based combat mechanics, damage formulas, and aggro system.

Skills & XP

RuneScape XP curves, leveling, combat level calculation, and skill requirements.

Tile Movement

Discrete tile-based movement, pathfinding, and OSRS melee range rules.