Skip to content

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:

  1. EmakiCoreLib's corelib.legacy package;
  2. each of the 5 modules' legacy packages (Cooking / Forge / Gem / Level / Strengthen);
  3. the single case "convert-legacy" -> ... line in each module's command router, plus the "convert-legacy" string in its tab completion list;
  4. the command.convert_legacy.* keys in both language files of each module; Gem and Strengthen also have command.help.desc.convert_legacy;
  5. each module's load-time reportLegacyItemSources() call (Strengthen has none);
  6. the implements LegacyMessageSink clauses on AbstractMessageService and LevelMessageService.

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

ModuleMigration targetCommand entryOther sites to edit after deletion
CoreLibshared engine, no targets of its ownnonethe implements on AbstractMessageService, LevelMessageService
Cookingnone left; the old flat station keys are handled by load-time fallback reads/emakicooking convert-legacyCookingCommandRouter, EmakiCookingPlugin
Forgenone left; the old and new key names coincide/emakiforge convert-legacyForgeCommandRouter, EmakiForgePlugin
Gemthe legacy match block in items/*.yml; no key-rename targets left/emakigem convert-legacyGemCommandRouter, EmakiGemPlugin
Levelresult_item_sourcesitem_sources in sources/*.yml/emakilevel convert-legacyLevelCommand, EmakiLevelPlugin
Strengthenthe legacy match block in recipes/*.yml/emakistrengthen convert-legacyStrengthenCommandRouter

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.