Skip to content

Crafting & Recipes

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.

Recipes with KnowledgeRequired: true must be learned before a player can craft them. Only applies to Crafting and DiagramCrafting bench types.

// teach a recipe
CraftingPlugin.learnRecipe(ref, "hytale:iron_pickaxe", componentAccessor);
// forget a recipe
CraftingPlugin.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.


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 recipes
entityStoreRegistry.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.

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
}
});