Crafting & Recipes
Managing Recipes in Code
Section titled “Managing Recipes in Code”Adding and Removing at Runtime
Section titled “Adding and Removing at Runtime”Recipes can be hot-reloaded through the asset store:
// add a recipe (triggers LoadedAssetsEvent, updates clients)CraftingRecipe.getAssetStore().loadAssets("mymod:mymod", List.of(recipe));
// remove by ID (triggers RemovedAssetsEvent, updates clients)CraftingRecipe.getAssetStore().removeAssets(List.of("mymod:custom_recipe"));This automatically updates all BenchRecipeRegistry instances and sends UpdateRecipes packets to connected clients.
Knowledge System
Section titled “Knowledge System”Recipes with KnowledgeRequired: true must be learned before a player can craft them. Only applies to Crafting and DiagramCrafting bench types.
// teach a recipeCraftingPlugin.learnRecipe(ref, "hytale:iron_pickaxe", componentAccessor);
// forget a recipeCraftingPlugin.forgetRecipe(ref, "hytale:iron_pickaxe", componentAccessor);
// sync known recipes to client (sends UpdateKnownRecipes packet)CraftingPlugin.sendKnownRecipes(ref, componentAccessor);learnRecipe and forgetRecipe both call sendKnownRecipes internally, so you don’t need to sync manually after calling them.
DiagramCrafting has an additional mechanic: when a player queues a craft, the recipe is auto-learned. Unknown recipes show as “Unknown” in the UI until learned.
The /recipe command provides admin control — see /recipe command reference.
Reacting to Crafting
Section titled “Reacting to Crafting”CraftRecipeEvent
Section titled “CraftRecipeEvent”CraftRecipeEvent fires as an ECS event with two phases:
- CraftRecipeEvent.Pre — fires before inputs are consumed. Cancel to prevent the craft entirely.
- CraftRecipeEvent.Post — fires after inputs are consumed but before outputs are given. Cancel to discard the outputs (inputs are already gone).
Both provide getCraftedRecipe() and getQuantity().
// prevent crafting certain recipesentityStoreRegistry.registerSystem( new EntityEventSystem<>(EntityStore.class, CraftRecipeEvent.Pre.class) { @Override protected void processEvent(ArchetypeChunk chunk, int entityIndex, CraftRecipeEvent.Pre event, CommandBuffer commandBuffer) { if (event.getCraftedRecipe().getId().equals("hytale:forbidden_item")) { event.setCancelled(true); } } });This event fires for the instant crafting path — all Fieldcraft (pocket crafting) and bench recipes with TimeSeconds: 0. If you need guaranteed event control over a recipe, making it Fieldcraft-compatible or keeping TimeSeconds at 0 ensures CraftRecipeEvent always fires.
Asset Events
Section titled “Asset Events”Listen for recipe additions and removals with asset events:
eventRegistry.register(LoadedAssetsEvent.class, CraftingRecipe.class, event -> { for (CraftingRecipe recipe : event.getLoadedAssets().values()) { // react to new/updated recipes }});