feat: ground recipes on the server, translated via wiki langlinks

Crafting recipes come from Bukkit.recipeIterator(), which is authoritative
for this exact version. Player questions are Portuguese and Material names
are English, so the subject of the question is searched on the pt wiki and
prop=langlinks&lllang=en gives the English title, which uppercases onto the
enum constant.

Matching material names against the question directly does not work.
Measured over twenty realistic pt-BR questions it resolved 1 of 20, and that
one ("tridente" containing "trident") by coincidence rather than
translation. Through langlinks the same twenty resolve 17 of 20.

Brewing is not exposed by Bukkit at all: there is no brewing Recipe type,
PotionBrewer has no getter or iterator, and vanilla brewing is hardcoded in
PotionBrewing rather than registered as a recipe. Potions therefore come
from a hand-written pt-BR table. This is what actually answers the
fire-resistance question that motivated the feature; recipeIterator() alone
never could have.

Ingredients are read through getChoiceMap/getChoiceList. The deprecated
getIngredientMap/getIngredientList collapse a choice to one arbitrary stack,
printing "oak planks" where the recipe accepts any plank.

The design doc claimed recipeIterator() closed the potion case. It did not;
corrected to record what is true.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01F3jSvSTrG4qsniLSr6TpC6
This commit is contained in:
marcos
2026-08-05 15:40:36 +00:00
parent 0f3bdf209d
commit dba64df917
5 changed files with 755 additions and 6 deletions
@@ -78,9 +78,37 @@ invented "poeira de guncotton" as a creeper drop.
`explaintext` strips tables, and brewing and crafting recipes live in tables.
The fire-resistance article is only 1086 characters for this reason, and the
recipe question failed even fully grounded. Recipes therefore come from
`Bukkit.recipeIterator()` — the running server's own data, authoritative for
this exact version, free and instant.
recipe question failed even fully grounded.
Crafting and brewing close differently, and an earlier draft of this document
was wrong to treat them as one problem.
**Crafting comes from the running server.** `Bukkit.recipeIterator()` is
authoritative for this exact version, free and instant. It is read through
`getChoiceMap()` / `getChoiceList()`; the older `getIngredientMap()` /
`getIngredientList()` are deprecated and collapse a choice to one arbitrary
stack, which prints "oak planks" where the recipe really accepts any plank.
**Item names are translated through the wiki.** `Material` names are English
and players ask in Portuguese, and the two do not meet on their own: scanning
every material name for a substring of the question was measured over twenty
realistic pt-BR questions and resolved **1 of 20** — and that one, "tridente"
containing "trident", by coincidence rather than translation. So the question's
subject is searched on the pt wiki and the article's `prop=langlinks&lllang=en`
gives the English title, which uppercases onto the enum: "Espada de Diamante"
→ "Diamond Sword" → `DIAMOND_SWORD`. The same twenty questions now resolve
**17 of 20**. Articles without an English link (real case: "Mesa de
Encantamento") yield no grounding rather than a guess.
**Brewing is not exposed by Bukkit at all, so potions use a hardcoded table.**
Checked against the 26.2 API: there is no brewing `Recipe` implementation;
`PotionBrewer` has `addPotionMix` / `removePotionMix` / `resetPotionMixes` but
no getter and no iterator; and vanilla brewing is hardcoded in `PotionBrewing`
rather than registered as a recipe, so `recipeIterator()` never yields it. The
server genuinely cannot supply this. `RecipeBook.BREWING` therefore lists the
~17 base potions in pt-BR by hand. This is the part that actually answers the
fire-resistance question that motivated the feature — `recipeIterator()` alone
would never have fixed it.
## Constraints
@@ -103,7 +131,8 @@ this exact version, free and instant.
├─ context assembly
│ contexto.yml always server facts, hand written
│ correcoes.yml on keyword match operator corrections
│ recipe lookup recipe questions Bukkit.recipeIterator()
│ recipe lookup recipe questions server registry + wiki langlinks;
│ potions from a hardcoded table
│ wiki article PRECISO only forced tool call → pt.minecraft.wiki
│ last 3 exchanges same player, 10 min window