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
- ProcessingDataProvider
- CraftingSystem
- FletchingSystem
- RunecraftingSystem
- RunecraftingAltarEntity
- Event Types
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 (useSkillconstants)amount- XP amount to grant
getLevelForXP(xp: number): number
Get the level for a given XP amount using OSRS XP table.
Parameters:
xp- XP amount
getXPForLevel(level: number): number
Get the XP required for a specific level.
Parameters:
level- Target level (1-99)
getXPToNextLevel(skill: SkillData): number
Get XP remaining to next level.
Parameters:
skill- Skill data object{ level: number, xp: number }
getXPProgress(skill: SkillData): number
Get XP progress percentage to next level.
Parameters:
skill- Skill data object
meetsRequirements(entity: Entity, requirements: Partial<Record<keyof Skills, number>>): boolean
Check if entity meets skill level requirements.
Parameters:
entity- Entity to checkrequirements- Object mapping skills to required levels
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
getTotalLevel(stats: StatsComponent): number
Calculate total level (sum of all skill levels).
Parameters:
stats- Stats component with skill data
getSkills(entityId: string): Skills | undefined
Get all skills for an entity.
Parameters:
entityId- Entity ID
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:
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”)
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:
- 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 barPROCESSING_CRAFTING_REQUEST- Player selected recipe and quantitySKILLS_UPDATED- Cache player skill levelsMOVEMENT_CLICK_TO_MOVE- Cancel crafting on movementCOMBAT_STARTED- Cancel crafting on combatPLAYER_UNREGISTERED- Clean up on disconnect
Events Emitted
CRAFTING_INTERFACE_OPEN- Show available recipes to playerCRAFTING_START- Crafting session startedCRAFTING_COMPLETE- Crafting session completedINVENTORY_ITEM_REMOVED- Materials consumedINVENTORY_ITEM_ADDED- Crafted item addedSKILLS_XP_GAINED- XP grantedANIMATION_PLAY- Crafting animationUI_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-itemPROCESSING_FLETCHING_REQUEST- Player selected recipe and quantitySKILLS_UPDATED- Cache player skill levelsMOVEMENT_CLICK_TO_MOVE- Cancel fletching on movementCOMBAT_STARTED- Cancel fletching on combatPLAYER_UNREGISTERED- Clean up on disconnect
Events Emitted
FLETCHING_INTERFACE_OPEN- Show available recipes to playerFLETCHING_START- Fletching session startedFLETCHING_COMPLETE- Fletching session completedINVENTORY_ITEM_REMOVED- Materials consumedINVENTORY_ITEM_ADDED- Fletched items added (with outputQuantity)SKILLS_XP_GAINED- XP grantedANIMATION_PLAY- Crafting animationUI_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
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 altarSKILLS_UPDATED- Cache player skill levelsPLAYER_UNREGISTERED- Clean up on disconnect
Events Emitted
RUNECRAFTING_COMPLETE- Runes craftedINVENTORY_ITEM_REMOVED- Essence consumedINVENTORY_ITEM_ADDED- Runes addedSKILLS_XP_GAINED- XP grantedUI_MESSAGE- Feedback messages
Processing Flow
RunecraftingAltarEntity
Location:packages/shared/src/entities/world/RunecraftingAltarEntity.ts
Purpose: Interactable altar entity for runecrafting.
Constructor
Properties
entityType: “runecrafting_altar”isInteractable: trueisPermanent: truedisplayName: 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
- Pillar: Large soft glows above altar peak (slow vertical bob)
- Wisps: Medium orbs orbiting altar silhouette (helical motion)
- Sparks: Small bright particles rising from surface vertices
- Base: Low ambient glows at altar footprint
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:Tick Processing Optimization
Once-Per-Tick Guard:Skill Level Caching
Migration Notes
Breaking Changes
None. All new skills are additive.Database Migrations
Required: Run migrations to add new skill columns:- 0029: Crafting skill (craftingLevel, craftingXp)
- 0030: Fletching skill (fletchingLevel, fletchingXp)
- 0031: Runecrafting skill (runecraftingLevel, runecraftingXp)
- 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.jsonpackages/server/world/assets/manifests/recipes/fletching.jsonpackages/server/world/assets/manifests/recipes/runecrafting.json
Troubleshooting
Recipes Not Loading
Symptom: Crafting/fletching/runecrafting panels show no recipes. Cause: Recipe manifests not loaded or validation errors. Fix:- Check console for validation errors
- Verify recipe JSON files exist in
packages/server/world/assets/manifests/recipes/ - Check DataManager initialization logs
- 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: VerifyconsumableUses 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
- SKILLS.md - Skills system overview
- CLAUDE.md - Development guidelines
- README.md - Project documentation
- OSRS Wiki: https://oldschool.runescape.wiki