Retiring the Legacy Converter
convert-legacy is one-off migration scaffolding, not plugin behaviour. This page records its retirement contract: once every server has migrated, follow this list to delete it without re-investigating the call sites.
The decision-site convergence itself is documented in Item Matcher. This page covers only how to remove the converter entirely.
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. Getting the order wrong breaks every other module's converter, 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. Deleting it alone breaks every module's converter, 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
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.