Skip to content

Modules: Equipment

Reusable gear & equipment slot system — registry, equip/unequip, stat modifiers, and rarity tiers (@broblox/equipment). Status: Implemented (54 tests).

Purpose

  • Typed gear definitions with rarity tiers (Common → Legendary).
  • Per-player equipment slots with equip/unequip/swap operations.
  • Stat modifier system (additive bonuses to speed, jump, stamina, etc.).
  • Generic — works for any game that needs equippable items with stat effects.

Core rules

  • Gear definitions are registered once in a GearRegistry; shared across all players.
  • Each player has an EquipmentStore — one gear per slot; slots are game-defined strings (e.g. "feet", "back", "body").
  • Equip operations validate ownership, slot match, level requirements, and duplicate prevention.
  • Stat modifiers are summed at query time — no mutation of base player attributes.

Data model

  • GearDefinition — static gear template: id, name, description?, rarity, slot, modifiers, levelRequirement?, price?, tags?.
  • StatModifier{ stat: string; flat: number } — additive bonus applied when gear is equipped.
  • GearRarity"common" | "uncommon" | "rare" | "epic" | "legendary" | "mythic".
  • EquipmentData — per-player serializable state: { equipped: Record<string, string>, ownedGear: string[] } (slot → gearId map + owned list).
  • EquipmentResult — operation result: { ok: boolean; status: EquipmentResultStatus }.

Public API

GearRegistry

Method Description
register(def) Register a gear definition
registerAll(defs) Register an array of definitions
get(id) Retrieve a definition by ID
getAll() Get all registered definitions
getBySlot(slot) Filter definitions by slot
has(id) Check if a gear ID is registered
count() Total registered definitions

EquipmentStore (per-player)

Constructed with (playerId, registry). One instance per player, managed by the factory.

Method Description
loadFrom(data) Hydrate from serialized EquipmentData
serialize() Export current state as EquipmentData
grantGear(gearId) Grant ownership of a gear item
ownsGear(gearId) Check if player owns a gear item
getOwnedGear() Get all owned gear IDs
equip(gearId, level?) Equip a gear item (validates ownership, slot, level req)
unequip(slot) Remove gear from a slot
getEquipped(slot) Get gear ID equipped in a slot
getAllEquipped() Get all equipped gear as Record<string, string>
computeBonuses() Sum all stat modifiers from equipped gear
getStatBonus(stat) Sum modifiers for a specific stat
getGearModifiers(gearId) Get modifiers for a specific gear item
onEquipChanged(cb) Subscribe to equip/unequip events
isDirty() / clearDirty() Track unsaved changes

Factory

import { createEquipmentService } from "@broblox/equipment";

const handle = createEquipmentService({
  gear: [
    {
      id: "speed_boots",
      name: "Speed Boots",
      rarity: "common",
      slot: "feet",
      modifiers: [{ stat: "speed", flat: 2 }],
      tags: ["speed"],
    },
    {
      id: "rocket_pack",
      name: "Rocket Pack",
      rarity: "rare",
      slot: "back",
      modifiers: [{ stat: "jump", flat: 5 }],
      tags: ["jump"],
    },
  ],
  onPlayerAdded: (cb) => PlayerLifecycleService.onPlayerAdded(cb),
  onPlayerRemoving: (cb) => PlayerLifecycleService.onPlayerRemoving(cb),
});

// handle.getGearRegistry()          → shared GearRegistry
// handle.getEquipmentStore(playerId) → per-player EquipmentStore
// handle.initPlayer(playerId)        → create store for player
// handle.cleanupPlayer(playerId)     → remove store on disconnect

Config

Key Required Description
gear Yes Array of GearDefinition to register
onPlayerAdded No Callback to wire player join → initPlayer
onPlayerRemoving No Callback to wire player leave → cleanupPlayer

Observability

  • GearEquipEvent — player equipped/unequipped a gear item (playerId, gearId, slot, equipped, timestamp)
  • Subscribe via store.onEquipChanged(callback)