English
Retiring the Legacy Converter
Once you are done with it, delete the whole convert-legacy one-off migration tool in the fixed order below
convert-legacy is one-off migration scaffolding, not plugin behaviour. Treat the list below as its retirement contract: once every server has migrated, follow it to delete the converter without re-investigating the call sites
The decision-site convergence itself is documented in Item Matcher
Why this has its own page
The converter spans 6 packages (the shared CoreLib engine plus each module's own target definitions), and they have a deletion-order constraint. Get the order wrong and every other module's converter stops compiling, and that dependency is not visible from the code — LegacyMessageSink is still implemented by two classes that have nothing to do with migration
Deletion order
CoreLib's corelib.legacy is the shared engine and is depended upon by all 5 modules. Delete it on its own and every module's converter breaks, so it must be retired in the same change as the module-level legacy packages, never before
Full retirement list
Delete all of the following in one change:
EmakiCoreLib'scorelib.legacypackage;- each of the 5 modules'
legacypackages (Cooking / Forge / Gem / Level / Strengthen); - the single
case "convert-legacy" -> ...line in each module's command router, plus the"convert-legacy"string in its tab completion list; - the
command.convert_legacy.*keys in both language files of each module; Gem and Strengthen also havecommand.help.desc.convert_legacy; - each module's load-time
reportLegacyItemSources()call (Strengthen has none); - the
implements LegacyMessageSinkclauses onAbstractMessageServiceandLevelMessageService
Item 6 is the easy one to miss: LegacyMessageSink is the only member of the shared engine with a non-migration consumer, so those two implements clauses become dangling references when the package goes
Per-module layout
| Module | Migration target | Command entry | Other sites to edit after deletion |
|---|---|---|---|
| CoreLib | shared engine, no targets of its own | none | the implements on AbstractMessageService, LevelMessageService |
| Cooking | none left; the old flat station keys are handled by load-time fallback reads | /emakicooking convert-legacy | CookingCommandRouter, EmakiCookingPlugin |
| Forge | none left; the old and new key names coincide | /emakiforge convert-legacy | ForgeCommandRouter, EmakiForgePlugin |
| Gem | the legacy match block in items/*.yml; no key-rename targets left | /emakigem convert-legacy | GemCommandRouter, EmakiGemPlugin |
| Level | result_item_sources → item_sources in sources/*.yml | /emakilevel convert-legacy | LevelCommand, EmakiLevelPlugin |
| Strengthen | the legacy match block in recipes/*.yml | /emakistrengthen convert-legacy | StrengthenCommandRouter |
Cooking, Forge, Gem, Level, and Strengthen still expose migration targets or compatibility conversion paths. Cooking's targets cover flat matcher keys across station settings and recipe inputs, retaining the fermentation-barrel input key needed for persisted slot identity. Forge's targets cover legacy source entries in materials and blueprint requirements, retaining the material key. Level still renames result_item_sources to item_sources; Strengthen converts the legacy match block; Gem handles its legacy source fields
Shared safety properties
These properties are what make deletion safe:
- it is reached only from the command entry point and the load-time scanner warning; no runtime matching, loading, forging, cooking or inlay path calls into it;
- it reads no runtime state, writes no persistent data container entry, and touches no player data; it only reads and rewrites configuration files inside the plugin data folder;
- once the whole package is gone, the rest of the plugin still compiles apart from the sites listed in the table above
Module-specific boundaries
Cooking's four prefixed station keys are not converter targets. tool_matcher, spatula_matcher, container_matcher, and moisture_rules[].input_matcher are read at load time as a fallback for the nested tool / spatula / container / input nodes, so old configs keep working without the command. The fermentation-barrel item_sources key is retained because it shares a key space with persisted slot state
Gem's gems/*.yml construction base is now base_item_source. The parser still falls back to the old item_sources key for that value, and the sibling item_sources is the recognition condition, so no key rename is needed
Gem's match-block converter promotes item sources to the top level. The legacy match.item_sources becomes the top-level item_sources field rather than a type: item_source node inside matcher, so a converted items/*.yml needs no manual pass
Level's warning must not be removed ahead of the package. A rule carrying only result_item_sources has no recognised condition left and therefore matches every item, so the load-time warning is the operator's only signal until the converter runs
Strengthen has no item_sources rename to migrate. Its material tokens already use the sibling item_sources + matcher shape, and top-level recipe matching expresses item sources through source_patterns; only the legacy match block needs conversion here. Its converter turns match.source_ids into anchored, escaped regexes (^\Qemakiitem-xxx\E$) merged into the top-level source_patterns, so the output is directly usable
Telling when migration is done
You only need to watch the warnings: Cooking, Forge, Gem, and Level scan for leftover legacy syntax at startup and warn. Strengthen has no such call, so its leftovers only surface through an explicit /emakistrengthen convert-legacy preview. Once several consecutive releases pass without an operator reporting that warning, the migration period is over and the facility can be retired using the list above