Skip to main content

API Reference - Skills and Processing Systems

This document provides detailed API reference for the skills and processing systems added in recent updates.

Table of Contents


SkillsSystem

Location: packages/shared/src/systems/shared/character/SkillsSystem.ts Purpose: Manages XP tracking, level calculation, and skill progression for all 17 skills.

Constants

Methods

grantXP(entityId: string, skill: keyof Skills, amount: number): void

Grant XP to a specific skill. Automatically handles level-ups and combat level updates. Parameters:
  • entityId - Entity ID (usually player ID)
  • skill - Skill name (use Skill constants)
  • amount - XP amount to grant
Example:

getLevelForXP(xp: number): number

Get the level for a given XP amount using OSRS XP table. Parameters:
  • xp - XP amount
Returns: Level (1-99) Example:

getXPForLevel(level: number): number

Get the XP required for a specific level. Parameters:
  • level - Target level (1-99)
Returns: XP required Example:

getXPToNextLevel(skill: SkillData): number

Get XP remaining to next level. Parameters:
  • skill - Skill data object { level: number, xp: number }
Returns: XP remaining

getXPProgress(skill: SkillData): number

Get XP progress percentage to next level. Parameters:
  • skill - Skill data object
Returns: Progress percentage (0-100)

meetsRequirements(entity: Entity, requirements: Partial<Record<keyof Skills, number>>): boolean

Check if entity meets skill level requirements. Parameters:
  • entity - Entity to check
  • requirements - Object mapping skills to required levels
Returns: true if all requirements met Example:

getCombatLevel(stats: StatsComponent): number

Calculate combat level from combat skills using OSRS formula. Parameters:
  • stats - Stats component with skill data
Returns: Combat level

getTotalLevel(stats: StatsComponent): number

Calculate total level (sum of all skill levels). Parameters:
  • stats - Stats component with skill data
Returns: Total level (max 1683)

getSkills(entityId: string): Skills | undefined

Get all skills for an entity. Parameters:
  • entityId - Entity ID
Returns: Skills object or undefined

ProcessingDataProvider

Location: packages/shared/src/data/ProcessingDataProvider.ts Purpose: Centralized recipe data provider for all processing skills. Loads recipes from JSON manifests.

Singleton Access

Initialization

Cooking Methods

isCookable(itemId: string): boolean

Check if an item can be cooked.

getCookingData(rawItemId: string): CookingItemData | null

Get cooking data for a raw food item. Returns:

getCookableItemIds(): Set<string>

Get all cookable item IDs.

getCookedItemId(rawItemId: string): string | null

Get cooked item ID for a raw food.

getBurntItemId(rawItemId: string): string | null

Get burnt item ID for a raw food.

getCookingLevel(rawItemId: string): number

Get cooking level requirement.

getCookingXP(rawItemId: string): number

Get cooking XP reward.

getStopBurnLevel(rawItemId: string, source: 'fire' | 'range'): number

Get stop-burn level for a cooking source.

Smithing Methods

isSmithableItem(itemId: string): boolean

Check if an item can be smithed.

getSmithingRecipe(itemId: string): SmithingRecipeData | null

Get smithing recipe for an output item. Returns:

getSmithingRecipesForBar(barType: string): SmithingRecipeData[]

Get all recipes that use a specific bar type.

getSmithingRecipesByCategory(barType: string): Map<SmithingCategory, SmithingRecipeData[]>

Get recipes grouped by category for a bar type.

getAvailableSmithingRecipes(smithingLevel: number): SmithingRecipeData[]

Get all recipes the player can make with their level.

getSmithableItemsWithAvailability(inventory: Array<{itemId: string, quantity?: number}>, smithingLevel: number): SmithingRecipeWithAvailability[]

Get all smithable items with availability flags for UI display. Returns:

Smelting Methods

isSmeltableBar(itemId: string): boolean

Check if an item is a smeltable bar.

isSmeltableOre(itemId: string): boolean

Check if an item is an ore that can be used for smelting.

getSmeltingData(barItemId: string): SmeltingItemData | null

Get smelting data for a bar. Returns:

getSmeltableBarsFromInventory(inventory: Array<{itemId: string, quantity?: number}>, smithingLevel: number): SmeltingItemData[]

Get all bars that can be smelted from inventory items.

Crafting Methods

isCraftableItem(itemId: string): boolean

Check if an item can be crafted.

getCraftingRecipe(outputItemId: string): CraftingRecipeData | null

Get crafting recipe for an output item. Returns:

getCraftingRecipesByCategory(category: string): CraftingRecipeData[]

Get all recipes in a category. Categories: leather, studded, dragonhide, jewelry, gem_cutting

getCraftingRecipesByStation(station: string): CraftingRecipeData[]

Get all recipes that require a specific station. Stations: “none”, “furnace”

getCraftingInputsForTool(toolId: string): Set<string>

Get valid input item IDs for a tool. Example:

isCraftingInput(itemId: string): boolean

Check if an item is used as input in any crafting recipe.

getCraftingToolForInput(inputItemId: string): string | null

Get the tool required for a crafting input item.

Fletching Methods

isFletchableItem(itemId: string): boolean

Check if an item can be fletched.

getFletchingRecipe(recipeId: string): FletchingRecipeData | null

Get fletching recipe by unique recipe ID (format: output:primaryInput). Returns:
Categories: arrow_shafts, headless_arrows, shortbows, longbows, stringing, arrows

getFletchingRecipesForInput(inputItemId: string): FletchingRecipeData[]

Get all recipes that use a specific input item. Example:

getFletchingRecipesForInputPair(itemA: string, itemB: string): FletchingRecipeData[]

Get recipes that require BOTH input items (for item-on-item interactions). Example:

getFletchingInputsForTool(toolId: string): Set<string>

Get valid input item IDs for a tool. Example:

isFletchingInput(itemId: string): boolean

Check if an item is used as input in any fletching recipe.

getFletchingToolForInput(inputItemId: string): string | null

Get the tool required for a fletching input item.

Runecrafting Methods

getRunecraftingRecipe(runeType: string): RunecraftingRecipeData | null

Get runecrafting recipe by rune type. Parameters:
  • runeType - Rune type identifier (e.g., “air”, “water”, “chaos”)
Returns:

isRunecraftingEssence(itemId: string): boolean

Check if an item is runecrafting essence.

getRunecraftingMultiplier(runeType: string, level: number): number

Calculate multi-rune multiplier for a rune type and level. Returns: Number of runes produced per essence (1-10) Example:
Multi-Rune Thresholds (OSRS-accurate):
  • Air: 11, 22, 33, 44, 55, 66, 77, 88, 99
  • Water: 19, 38, 57, 76, 95
  • Earth: 26, 52, 78
  • Fire: 35, 70
  • Mind: 14, 28, 42, 56, 70, 84, 98
  • Body: 46, 92
  • Cosmic: 59
  • Chaos: 74
  • Nature: 91
  • Law: None (always 1)
  • Death: None (always 1)
  • Blood: None (always 1)

Tanning Methods

getTanningRecipe(inputItemId: string): TanningRecipeData | null

Get tanning recipe by input hide item ID. Returns:

isTannableItem(itemId: string): boolean

Check if an item can be tanned.

getAllTanningRecipes(): TanningRecipeData[]

Get all tanning recipes.

Utility Methods

getSummary(): object

Get summary of loaded recipes for debugging. Returns:

CraftingSystem

Location: packages/shared/src/systems/shared/interaction/CraftingSystem.ts Purpose: Handles crafting skill (leather armor, jewelry, gem cutting).

Features

  • Tick-based processing (3 ticks default)
  • Thread consumable with 5 uses
  • Station support (none, furnace)
  • Category grouping (leather, studded, dragonhide, jewelry, gem_cutting)
  • Movement/combat cancellation
  • Server-authoritative validation

Events Listened

  • CRAFTING_INTERACT - Player used needle/chisel/gold bar
  • PROCESSING_CRAFTING_REQUEST - Player selected recipe and quantity
  • SKILLS_UPDATED - Cache player skill levels
  • MOVEMENT_CLICK_TO_MOVE - Cancel crafting on movement
  • COMBAT_STARTED - Cancel crafting on combat
  • PLAYER_UNREGISTERED - Clean up on disconnect

Events Emitted

  • CRAFTING_INTERFACE_OPEN - Show available recipes to player
  • CRAFTING_START - Crafting session started
  • CRAFTING_COMPLETE - Crafting session completed
  • INVENTORY_ITEM_REMOVED - Materials consumed
  • INVENTORY_ITEM_ADDED - Crafted item added
  • SKILLS_XP_GAINED - XP granted
  • ANIMATION_PLAY - Crafting animation
  • UI_MESSAGE - Feedback messages

Methods

isPlayerCrafting(playerId: string): boolean

Check if a player is currently crafting.

Session Flow


FletchingSystem

Location: packages/shared/src/systems/shared/interaction/FletchingSystem.ts Purpose: Handles fletching skill (bows, arrows, arrow shafts).

Features

  • Tick-based processing (2-3 ticks)
  • Multi-output support (15 arrow shafts per log, 15 arrows per set)
  • Item-on-item interactions (bowstring + unstrung bow, arrowtips + headless arrows)
  • Category grouping (arrow_shafts, headless_arrows, shortbows, longbows, stringing, arrows)
  • Movement/combat cancellation
  • Server-authoritative validation

Events Listened

  • FLETCHING_INTERACT - Player used knife on logs or item-on-item
  • PROCESSING_FLETCHING_REQUEST - Player selected recipe and quantity
  • SKILLS_UPDATED - Cache player skill levels
  • MOVEMENT_CLICK_TO_MOVE - Cancel fletching on movement
  • COMBAT_STARTED - Cancel fletching on combat
  • PLAYER_UNREGISTERED - Clean up on disconnect

Events Emitted

  • FLETCHING_INTERFACE_OPEN - Show available recipes to player
  • FLETCHING_START - Fletching session started
  • FLETCHING_COMPLETE - Fletching session completed
  • INVENTORY_ITEM_REMOVED - Materials consumed
  • INVENTORY_ITEM_ADDED - Fletched items added (with outputQuantity)
  • SKILLS_XP_GAINED - XP granted
  • ANIMATION_PLAY - Crafting animation
  • UI_MESSAGE - Feedback messages

Methods

isPlayerFletching(playerId: string): boolean

Check if a player is currently fletching.

Multi-Output Handling

Fletching supports multi-output recipes where one action produces multiple items: Example: Arrow Shafts
  • Input: 1 log
  • Output: 15 arrow shafts
  • XP: 5 (total for all 15 shafts)
  • Ticks: 2
Implementation:

RunecraftingSystem

Location: packages/shared/src/systems/shared/interaction/RunecraftingSystem.ts Purpose: Handles runecrafting skill (essence → runes at altars).

Features

  • Instant processing (no tick delay)
  • Multi-rune multiplier at higher levels
  • Converts ALL essence in inventory at once
  • Two essence types: rune_essence (basic runes), pure_essence (all runes)
  • Server-authoritative validation

Events Listened

  • RUNECRAFTING_INTERACT - Player clicked altar
  • SKILLS_UPDATED - Cache player skill levels
  • PLAYER_UNREGISTERED - Clean up on disconnect

Events Emitted

  • RUNECRAFTING_COMPLETE - Runes crafted
  • INVENTORY_ITEM_REMOVED - Essence consumed
  • INVENTORY_ITEM_ADDED - Runes added
  • SKILLS_XP_GAINED - XP granted
  • UI_MESSAGE - Feedback messages

Processing Flow

Example:

RunecraftingAltarEntity

Location: packages/shared/src/entities/world/RunecraftingAltarEntity.ts Purpose: Interactable altar entity for runecrafting.

Constructor

Config:

Properties

  • entityType: “runecrafting_altar”
  • isInteractable: true
  • isPermanent: true
  • displayName: Display name (e.g., “Air Altar”)
  • runeType: Rune type this altar produces

Methods

handleInteraction(data: EntityInteractionData): Promise<void>

Handle altar interaction. Emits RUNECRAFTING_INTERACT event.

getContextMenuActions(playerId: string): Array<{id, label, priority, handler}>

Get context menu actions. Returns:

Visual Effects

Mystical Particle System (client-only):
  • 4 particle layers: pillar, wisps, sparks, base
  • Color-coded by rune type (air=white, water=blue, fire=red, etc.)
  • Mesh-aware placement (particles spawn from actual model geometry)
  • Billboard rendering (always faces camera)
  • Additive blending for glow effect
Particle Layers:
  1. Pillar: Large soft glows above altar peak (slow vertical bob)
  2. Wisps: Medium orbs orbiting altar silhouette (helical motion)
  3. Sparks: Small bright particles rising from surface vertices
  4. Base: Low ambient glows at altar footprint
Color Palettes (per rune type):

Collision

Altars register collision tiles based on footprint:
  • Default footprint: 2x2 tiles (from station manifest)
  • Can be overridden per-instance
  • Blocks player movement (OSRS-accurate)

Event Types

New Events (Added in Recent PRs)

CRAFTING_INTERACT

Player used crafting tool (needle/chisel) or clicked furnace. Payload:

CRAFTING_INTERFACE_OPEN

Show crafting panel with available recipes. Payload:

PROCESSING_CRAFTING_REQUEST

Player selected crafting recipe and quantity. Payload:

CRAFTING_START

Crafting session started. Payload:

CRAFTING_COMPLETE

Crafting session completed. Payload:

FLETCHING_INTERACT

Player used knife on logs or item-on-item. Payload:

FLETCHING_INTERFACE_OPEN

Show fletching panel with available recipes. Payload:

PROCESSING_FLETCHING_REQUEST

Player selected fletching recipe and quantity. Payload:

FLETCHING_START

Fletching session started. Payload:

FLETCHING_COMPLETE

Fletching session completed. Payload:

RUNECRAFTING_INTERACT

Player clicked runecrafting altar. Payload:

RUNECRAFTING_COMPLETE

Runes crafted from essence. Payload:

Type Definitions

SkillData

Skills

SmithingCategory

FootprintSpec


Usage Examples

Example 1: Check if Player Can Craft Item

Example 2: Calculate Runecrafting Output

Example 3: Get Available Fletching Recipes for Logs

Example 4: Display Smithing Panel with Availability


Performance Considerations

Memory Optimization

Pre-allocated Buffers:
Reusable Arrays:

Tick Processing Optimization

Once-Per-Tick Guard:
Batch Processing:

Skill Level Caching


Migration Notes

Breaking Changes

None. All new skills are additive.

Database Migrations

Required: Run migrations to add new skill columns:
Migrations:
  • 0029: Crafting skill (craftingLevel, craftingXp)
  • 0030: Fletching skill (fletchingLevel, fletchingXp)
  • 0031: Runecrafting skill (runecraftingLevel, runecraftingXp)
Default Values:
  • All new skills default to level 1, XP 0
  • Existing characters automatically get default values

Manifest Updates

New Recipe Files (must be present):
  • packages/server/world/assets/manifests/recipes/crafting.json
  • packages/server/world/assets/manifests/recipes/fletching.json
  • packages/server/world/assets/manifests/recipes/runecrafting.json
Fallback Behavior: If recipe manifests are missing, ProcessingDataProvider falls back to embedded item data (backwards compatibility).

Troubleshooting

Recipes Not Loading

Symptom: Crafting/fletching/runecrafting panels show no recipes. Cause: Recipe manifests not loaded or validation errors. Fix:
  1. Check console for validation errors
  2. Verify recipe JSON files exist in packages/server/world/assets/manifests/recipes/
  3. Check DataManager initialization logs
  4. Call processingDataProvider.getSummary() to see loaded recipe counts

Thread Not Being Consumed

Symptom: Thread never runs out when crafting leather armor. Cause: Consumable uses not being decremented. Fix: Verify consumableUses Map is being updated in completeCraft():

Multi-Rune Multiplier Not Working

Symptom: Always getting 1 rune per essence regardless of level. Cause: multiRuneLevels array not sorted or multiplier calculation incorrect. Fix: Verify multiRuneLevels is sorted ascending in manifest:

Fletching Producing Wrong Quantity

Symptom: Arrow shafts produce 1 instead of 15. Cause: outputQuantity not being used when adding items. Fix: Verify INVENTORY_ITEM_ADDED event uses recipe.outputQuantity:

See Also