Artisan Skills API Reference
Complete API reference for Hyperscape’s artisan skills systems.Table of Contents
- CraftingSystem
- FletchingSystem
- RunecraftingSystem
- TanningSystem
- ProcessingDataProvider
- Event Types
- Recipe Manifest Schemas
CraftingSystem
Tick-based crafting system for leather armor, dragonhide, jewelry, and gems. Location:packages/shared/src/systems/shared/interaction/CraftingSystem.ts
Public Methods
isPlayerCrafting(playerId: string): boolean
Check if a player is currently crafting.
Parameters:
playerId: Player entity ID
true if player has an active crafting session
Example:
Events
Subscribes To
CRAFTING_INTERACT: Trigger crafting interactionPROCESSING_CRAFTING_REQUEST: Start crafting with quantitySKILLS_UPDATED: Cache player skill levelsMOVEMENT_CLICK_TO_MOVE: Cancel crafting on movementCOMBAT_STARTED: Cancel crafting on combatPLAYER_UNREGISTERED: Cleanup on disconnect
Emits
CRAFTING_INTERFACE_OPEN: Send available recipes to clientCRAFTING_START: Crafting session startedCRAFTING_COMPLETE: Crafting session completedINVENTORY_ITEM_REMOVED: Consume materialsINVENTORY_ITEM_ADDED: Add crafted itemSKILLS_XP_GAINED: Grant crafting XPANIMATION_PLAY: Play crafting animationUI_MESSAGE: User feedback messages
Internal Types
Mechanics
Thread Consumption:- Thread has 5 uses per item
- Uses tracked in
consumableUsesMap - New thread consumed when uses depleted
- Crafting stops if no thread available
- Processes once per game tick (600ms)
- Uses
completionTickfor timing - Avoids duplicate processing with
lastProcessedTickguard
- Single inventory scan per tick
- Reusable arrays for completed sessions
- Pre-allocated inventory state buffer
FletchingSystem
Tick-based fletching system for bows and arrows with multi-output support. Location:packages/shared/src/systems/shared/interaction/FletchingSystem.ts
Public Methods
isPlayerFletching(playerId: string): boolean
Check if a player is currently fletching.
Parameters:
playerId: Player entity ID
true if player has an active fletching session
Example:
Events
Subscribes To
FLETCHING_INTERACT: Trigger fletching interactionPROCESSING_FLETCHING_REQUEST: Start fletching with quantitySKILLS_UPDATED: Cache player skill levelsMOVEMENT_CLICK_TO_MOVE: Cancel fletching on movementCOMBAT_STARTED: Cancel fletching on combatPLAYER_UNREGISTERED: Cleanup on disconnect
Emits
FLETCHING_INTERFACE_OPEN: Send available recipes to clientFLETCHING_START: Fletching session startedFLETCHING_COMPLETE: Fletching session completedINVENTORY_ITEM_REMOVED: Consume materialsINVENTORY_ITEM_ADDED: Add fletched itemsSKILLS_XP_GAINED: Grant fletching XPANIMATION_PLAY: Play fletching animationUI_MESSAGE: User feedback messages
Internal Types
Mechanics
Multi-Output Recipes:outputQuantityfield in recipe (default: 1)- Arrow shafts: 15 per log
- Headless arrows: 15 per action
- Arrows: 15 per action
- Bowstring + unstrung bow → strung bow
- Arrowtips + headless arrows → arrows
- Arrow shafts + feathers → headless arrows
getFletchingRecipesForInput(itemId): Single input (knife + logs)getFletchingRecipesForInputPair(itemA, itemB): Both inputs (item-on-item)
RunecraftingSystem
Instant essence-to-rune conversion system with multi-rune multipliers. Location:packages/shared/src/systems/shared/interaction/RunecraftingSystem.ts
Public Methods
None (instant conversion, no active sessions)Events
Subscribes To
RUNECRAFTING_INTERACT: Trigger runecrafting interactionSKILLS_UPDATED: Cache player skill levelsPLAYER_UNREGISTERED: Cleanup on disconnect
Emits
RUNECRAFTING_COMPLETE: Runecrafting completedINVENTORY_ITEM_REMOVED: Consume essenceINVENTORY_ITEM_ADDED: Add runesSKILLS_XP_GAINED: Grant runecrafting XPUI_MESSAGE: User feedback messages
Mechanics
Instant Conversion:- No tick delay (unlike other skills)
- All essence converted in one action
- XP granted per essence consumed
- Calculated from
multiRuneLevelsarray - Each threshold grants +1 rune per essence
- Example: Air runes at level 22 = 3 runes per essence
- Basic runes: rune_essence OR pure_essence
- Advanced runes: pure_essence only
- Invalid essence types ignored
TanningSystem
Instant hide-to-leather conversion system at tanner NPCs. Location:packages/shared/src/systems/shared/interaction/TanningSystem.ts
Public Methods
None (instant conversion, no active sessions)Events
Subscribes To
TANNING_INTERACT: Trigger tanning interactionTANNING_REQUEST: Request tanning with quantityPLAYER_UNREGISTERED: Cleanup on disconnect
Emits
TANNING_INTERFACE_OPEN: Send available recipes to clientTANNING_COMPLETE: Tanning completedINVENTORY_ITEM_REMOVED: Consume hidesINVENTORY_REMOVE_COINS: Deduct tanning costINVENTORY_ITEM_ADDED: Add leatherUI_MESSAGE: User feedback messages
Mechanics
Instant Conversion:- No tick delay
- Coins deducted first, then hides removed, then leather added
- No XP granted (tanning is a service, not a skill)
- Total cost = quantity × cost per hide
- If insufficient coins, tans only what player can afford
- Minimum 1 hide if player has any coins
ProcessingDataProvider
Central data provider for all artisan skill recipes. Location:packages/shared/src/data/ProcessingDataProvider.ts
Singleton Access
Crafting Methods
getCraftingRecipe(outputItemId: string): CraftingRecipeData | null
Get crafting recipe by output item ID.
Parameters:
outputItemId: Item ID of crafted item (e.g., “leather_gloves”)
getCraftingRecipesByStation(station: string): CraftingRecipeData[]
Get all crafting recipes for a specific station.
Parameters:
station: Station type (“none” or “furnace”)
getCraftingRecipesByCategory(category: string): CraftingRecipeData[]
Get all crafting recipes in a category.
Parameters:
category: Category name (leather, dragonhide, jewelry, gem_cutting)
isCraftableItem(itemId: string): boolean
Check if an item can be crafted.
Parameters:
itemId: Item ID to check
true if item has a crafting recipe
getCraftableItemIds(): Set<string>
Get all craftable item IDs.
Returns: Set of item IDs
getCraftingInputsForTool(toolId: string): Set<string>
Get valid input items for a crafting tool.
Parameters:
toolId: Tool item ID (e.g., “needle”, “chisel”)
isCraftingInput(itemId: string): boolean
Check if an item is used as input in any crafting recipe.
Parameters:
itemId: Item ID to check
true if item is a crafting input
getCraftingToolForInput(inputItemId: string): string | null
Get the tool required for a crafting input item.
Parameters:
inputItemId: Input item ID
Fletching Methods
getFletchingRecipe(recipeId: string): FletchingRecipeData | null
Get fletching recipe by unique recipe ID.
Parameters:
recipeId: Unique recipe ID (format: “output:primaryInput”)
getFletchingRecipesForInput(inputItemId: string): FletchingRecipeData[]
Get all fletching recipes using a specific input item.
Parameters:
inputItemId: Input item ID (e.g., “logs”)
getFletchingRecipesForInputPair(itemA: string, itemB: string): FletchingRecipeData[]
Get fletching recipes matching both input items (item-on-item).
Parameters:
itemA: First item IDitemB: Second item ID
getFletchingRecipesByCategory(category: string): FletchingRecipeData[]
Get all fletching recipes in a category.
Parameters:
category: Category name (arrow_shafts, headless_arrows, arrows, shortbows, longbows, stringing)
isFletchableItem(itemId: string): boolean
Check if an item can be fletched.
Parameters:
itemId: Item ID to check
true if item has a fletching recipe
getFletchableItemIds(): Set<string>
Get all fletchable item IDs.
Returns: Set of item IDs
getFletchingInputsForTool(toolId: string): Set<string>
Get valid input items for a fletching tool.
Parameters:
toolId: Tool item ID (e.g., “knife”)
isFletchingInput(itemId: string): boolean
Check if an item is used as input in any fletching recipe.
Parameters:
itemId: Item ID to check
true if item is a fletching input
getFletchingToolForInput(inputItemId: string): string | null
Get the tool required for a fletching input item.
Parameters:
inputItemId: Input item ID
Runecrafting Methods
getRunecraftingRecipe(runeType: string): RunecraftingRecipeData | null
Get runecrafting recipe by rune type.
Parameters:
runeType: Rune type identifier (e.g., “air”, “mind”, “water”)
getRunecraftingMultiplier(runeType: string, level: number): number
Calculate multi-rune multiplier for a given rune type and level.
Parameters:
runeType: Rune type identifierlevel: Player’s runecrafting level
getAllRunecraftingRecipes(): RunecraftingRecipeData[]
Get all runecrafting recipes.
Returns: Array of all recipes
isRunecraftingEssence(itemId: string): boolean
Check if an item is a valid runecrafting essence.
Parameters:
itemId: Item ID to check
true if item is rune_essence or pure_essence
Tanning Methods
getTanningRecipe(inputItemId: string): TanningRecipeData | null
Get tanning recipe by input hide item ID.
Parameters:
inputItemId: Hide item ID (e.g., “cowhide”)
getAllTanningRecipes(): TanningRecipeData[]
Get all tanning recipes.
Returns: Array of all recipes
isTannableItem(itemId: string): boolean
Check if an item can be tanned.
Parameters:
itemId: Item ID to check
true if item has a tanning recipe
Utility Methods
initialize(): void
Initialize the data provider by building lookup tables from manifests.
Must be called after DataManager loads manifests.
Example:
rebuild(): void
Rebuild all lookup tables (for hot-reload scenarios).
Example:
isReady(): boolean
Check if provider is initialized.
Returns: true if initialized
getSummary(): object
Get summary of loaded recipes for debugging.
Returns:
Event Types
Crafting Events
CRAFTING_INTERACT
Trigger crafting interaction (player used tool on item or clicked furnace).
Payload:
PROCESSING_CRAFTING_REQUEST
Request to start crafting with quantity.
Payload:
CRAFTING_INTERFACE_OPEN
Server sends available recipes to client.
Payload:
CRAFTING_START
Crafting session started.
Payload:
CRAFTING_COMPLETE
Crafting session completed.
Payload:
Fletching Events
FLETCHING_INTERACT
Trigger fletching interaction (player used knife on logs or item-on-item).
Payload:
PROCESSING_FLETCHING_REQUEST
Request to start fletching with quantity.
Payload:
FLETCHING_INTERFACE_OPEN
Server sends available recipes to client.
Payload:
FLETCHING_START
Fletching session started.
Payload:
FLETCHING_COMPLETE
Fletching session completed.
Payload:
Runecrafting Events
RUNECRAFTING_INTERACT
Trigger runecrafting interaction (player clicked altar).
Payload:
RUNECRAFTING_COMPLETE
Runecrafting completed.
Payload:
Tanning Events
TANNING_INTERACT
Trigger tanning interaction (player talked to tanner NPC).
Payload:
TANNING_REQUEST
Request tanning with quantity.
Payload:
TANNING_INTERFACE_OPEN
Server sends available recipes to client.
Payload:
TANNING_COMPLETE
Tanning completed.
Payload:
Recipe Manifest Schemas
Crafting Recipe Schema
File:packages/server/world/assets/manifests/recipes/crafting.json
output: Must exist in items manifestcategory: Non-empty stringinputs: Non-empty array, each item must exist in manifesttools: Array (can be empty), each item must exist in manifestconsumables: Array (can be empty), each item must exist in manifestlevel: Integer 1-99xp: Positive numberticks: Positive integerstation: Must be “none” or “furnace”
Fletching Recipe Schema
File:packages/server/world/assets/manifests/recipes/fletching.json
output: Must exist in items manifestoutputQuantity: Positive integer (default: 1)category: Non-empty stringinputs: Non-empty array, each item must exist in manifesttools: Array (can be empty for stringing), each item must exist in manifestlevel: Integer 1-99xp: Positive numberticks: Positive integerskill: Must be “fletching”
Runecrafting Recipe Schema
File:packages/server/world/assets/manifests/recipes/runecrafting.json
runeType: Non-empty string, uniqueruneItemId: Must exist in items manifestlevelRequired: Integer 1-99xpPerEssence: Positive numberessenceTypes: Non-empty array of item IDsmultiRuneLevels: Array of integers (can be empty), sorted ascending
Tanning Recipe Schema
File:packages/server/world/assets/manifests/recipes/tanning.json
input: Must exist in items manifestoutput: Must exist in items manifestcost: Non-negative integername: Non-empty string
Recipe Data Types
CraftingRecipeData
FletchingRecipeData
RunecraftingRecipeData
TanningRecipeData
Usage Examples
Starting a Crafting Session
Starting a Fletching Session
Runecrafting at Altar
Tanning Hides
Error Handling
Common Errors
Invalid Recipe:Performance Considerations
Memory Usage
Per Active Session:- CraftingSession: ~200 bytes (includes consumableUses Map)
- FletchingSession: ~150 bytes
- RunecraftingSystem: No active sessions (instant)
- Crafting: ~30 recipes × ~500 bytes = ~15KB
- Fletching: ~37 recipes × ~400 bytes = ~15KB
- Runecrafting: ~11 recipes × ~300 bytes = ~3KB
- Total: ~33KB for all recipe data
CPU Usage
Tick Processing:- CraftingSystem: O(n) where n = active sessions
- FletchingSystem: O(n) where n = active sessions
- RunecraftingSystem: No tick processing
- Single scan per tick per active session
- Pre-allocated buffers to avoid allocations
- Reusable arrays for completed sessions
Optimizations
Inventory State Caching:Security
Rate Limiting
All artisan skill interactions are rate-limited:Audit Logging
All completions are logged for economic tracking:Input Validation
Recipe ID Validation:- Must exist in recipe map
- Must match expected format
- Must be positive integer
- Clamped to available materials
- Checked before starting session
- Re-checked on each craft action
- Checked before starting session
- Re-checked on each craft action
- Prevents crafting with insufficient materials
Testing
Unit Tests
CraftingSystem:CraftingSystem.test.ts: 19 tests covering lifecycle, cancellation, edge cases
FletchingSystem.test.ts: 15 tests covering multi-output, item-on-item, cancellation
RunecraftingSystem.test.ts: 12 tests covering multipliers, essence validation, levels
ProcessingDataProvider.test.ts: 25 tests covering recipe loading, filtering, validation
Integration Tests
Crafting Flow:- Player uses needle on leather
- Server sends available recipes
- Player selects recipe and quantity
- Server starts crafting session
- Tick-by-tick processing
- Materials consumed, items added, XP granted
- Session completes
- Player uses knife on logs
- Server sends available recipes (arrow shafts, bows)
- Player selects arrow shafts and quantity 5
- Server starts fletching session
- Each action produces 15 arrow shafts
- Total: 75 arrow shafts after 5 actions
- Player clicks air altar with 100 rune essence
- Server calculates multiplier (e.g., 3x at level 22)
- Server converts all essence instantly
- Player receives 300 air runes
- Player gains 500 XP (100 essence × 5 XP)