Skip to content

feat(script): fire playerCraftRecipe when a grid recipe is crafted - #387

Merged
NaySurGithub merged 1 commit into
devfrom
feat/script-player-craft-recipe
Nov 13, 2026
Merged

NaySurGithub merged 1 commit into
devfrom
feat/script-player-craft-recipe

Conversation

@NaySurGithub

Copy link
Copy Markdown
Contributor

What

world.afterEvents.playerCraftRecipe was bound but never fired. It now fires after a player crafts a recipe on the crafting grid (the 2x2 inventory grid or a crafting table), with the documented fields:

  • player — the crafter
  • itemStack — the crafted item (the recipe's output stack)
  • block — the crafting table when one is open, left undefined for the 2x2 inventory grid

PlayerCraftRecipeEventOptions filtering is honored: playerFilter (EntityFilter), itemFilter (ItemFilter.includeTypes against the crafted item), and blockFilter (BlockFilter include/exclude types, tags and permutations) applied when the event carries a block.

How it was done / checked

  • ItemStackRequestHandler::execute already runs the request on a working copy and commits only on success. It now reports the crafted recipe output through a new out-param, set in the grid-recipe path (craftRecipe) once the request validates — so the event only fires for a real, committed craft, after the request holds, like the other after-events.
  • The crafting-table block comes from InventoryManager, which already tracks the open table's position.
  • Fields verified against the @minecraft/server 2.12.0-beta.1.26.60 .d.ts: PlayerCraftRecipeAfterEvent = { block?, itemStack?, player }, and PlayerCraftRecipeEventOptions = { blockFilter, itemFilter, playerFilter }. In the 26.60 client the event is raised from the vanilla crafting-container completion through the player event coordinator.
  • Scope: only the crafting grid fires it. The stonecutter, anvil and cartography table go through their own request paths and are not reported here — I could not confirm in the client whether vanilla raises playerCraftRecipe for the stonecutter, so I did not fire it there rather than guess.
  • itemStack is the recipe's declared output stack (not multiplied by the requested craft count): the count the game reports for a bulk/shift craft is the one value I could not pin down in the binary, so the reported stack is the recipe output as loaded, which is a known value rather than a guess.

Test: player-craft-recipe drives a real one-ingredient shapeless recipe through execute and checks the crafted item reported to scripts is the recipe output with its count, and that a request crafting nothing reports no item.

Not built locally (syntax-checked with clang++ -fsyntax-only); CI runs on the branch.

In-game test plan: subscribe to world.afterEvents.playerCraftRecipe; craft in the 2x2 grid (expect the event with block undefined) and at a crafting table (expect block = the table); check itemStack.typeId and that playerFilter/itemFilter/blockFilter narrow the callbacks.

AI disclosure

Code, research in the game binary and this description: Claude Opus 4.8 (claude-opus-4-8).

@NaySurGithub
NaySurGithub merged commit 917e9a8 into dev Nov 13, 2026
8 checks passed
@NaySurGithub
NaySurGithub deleted the feat/script-player-craft-recipe branch November 13, 2026 22:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant