# Migration from legacy packs This project is meant to replace legacy `.pck` or EterPack-style content delivery gradually, not through a single risky cutover. ## Target state - Linux builds produce `.m2p` - the client loads `.m2p` first - runtime master key delivery is required - silent fallback to legacy packs is disabled in production ## Suggested migration phases ### Phase 1: parallel loader - keep the legacy loader in the client - add `.m2p` support beside it - verify the new loader against real content sets - keep fallback only in development if needed ### Phase 2: pipeline validation - build `.m2p` from the same source tree as legacy packs - run `verify` for every archive - run `diff` between the source tree and `.m2p` - compare in-game behavior between legacy and `.m2p` ### Phase 3: runtime delivery - stop embedding a real content key in the client - deliver the runtime key through launcher, environment, or mapping - verify startup failure behavior when the runtime key is missing ### Phase 4: production cutover - package only `.m2p` for release clients - disable silent fallback to legacy packs - remove stale pack generation from release CI - keep extract/debug tools only for internal use ## Recommended checks - duplicate normalized paths - invalid relative paths - case-collision problems on Windows - decompression failures - manifest signature failures - key mismatch by `key_id` - runtime smoke against the real client - scenario gate with known-issues baseline ## Practical migration loop 1. Pick one legacy pack group. 2. Rebuild it as `.m2p`. 3. Verify it. 4. Diff it against the source tree. 5. Boot the client with runtime keys. 6. Run the runtime scenario gate. 7. Validate asset loads in logs and in-game. 8. Move to the next pack group. Recommended gate command: ```bash python3 scripts/validate_runtime_gate.py \ --runtime-root /tmp/m2dev-client-runtime-http ``` For release tightening: ```bash python3 scripts/validate_runtime_gate.py \ --runtime-root /tmp/m2dev-client-runtime-http \ --strict-known-issues ``` The shared baseline lives in: - `known_issues/runtime_known_issues.json` This lets the migration fail only on new regressions while still tracking historical client data problems explicitly. ## Confirmed startup-safe pack group The following startup pack set has already been validated against the real client runtime on the Linux VPS: - `root` - `patch1` - `patch2` - `season3_eu` - `metin2_patch_snow` - `metin2_patch_snow_dungeon` - `metin2_patch_etc_costume1` - `metin2_patch_pet1` - `metin2_patch_pet2` - `metin2_patch_ramadan_costume` - `metin2_patch_flame` - `metin2_patch_flame_dungeon` - `locale` - `uiscript` - `uiloading` - `ETC` - `item` - `effect` - `icon` - `property` - `terrain` - `tree` - `zone` - `outdoora1` - `outdoora2` - `outdoorb1` - `outdoorc1` - `outdoorsnow1` - `pc` - `pc2` - `guild` - `npc` - `monster2` - `sound` - `sound_m` - `sound2` - `monster` - `npc2` - `textureset` - `outdoora3` - `outdoorb3` - `outdoorc3` - `outdoordesert1` - `outdoorflame1` - `outdoorfielddungeon1` Validation method: 1. build each pack as `.m2p` 2. remove the matching legacy `.pck` 3. provide the runtime master key through: - `M2PACK_MASTER_KEY_HEX` - `M2PACK_KEY_ID=1` 4. start the Linux-built Windows client with `xvfb-run + wine` Observed result: - `PackInitialize` succeeded - Python startup succeeded - `app.Create(...)` succeeded - client reached `MainStream.SetLoginPhase()` For the world, audio, actor, and gameplay-adjacent packs in this list, the current validation level is startup regression smoke only. Full confidence for those packs still requires map-load or in-game coverage. The repository now also includes a scenario validator for common world packs: - `scripts/validate_runtime_scenarios.py` It verifies that selected `Outdoor*` maps reference valid `textureset` and environment assets across pack boundaries. It also now includes an actor/content validator: - `scripts/validate_actor_scenarios.py` On the current real client runtime, the full actor validator reports five data issues that look like pre-existing content inconsistencies rather than `.m2p` loader regressions: - `Monster/misterious_diseased_host` missing `25.gr2` - `Monster/skeleton_king` missing `24.gr2` - `Monster/thief2` missing `03_1.gr2` - `NPC/christmas_tree` missing `wait.gr2` - `NPC/guild_war_flag` missing `wait.gr2` The expanded validator did not find additional breakage in: - `.msm` base model references - `.msm` effect script references - `.msm` default hit effect references - `.msm` default hit sound references It also now includes an effect graph validator: - `scripts/validate_effect_scenarios.py` On the current real client runtime, the effect validator checks 458 text-based effect files and reports 12 concrete missing references: - `effect/background/moonlight_eff_bat*.mse` missing three `effect/pet/halloween_2022_coffin_bat_0{1,2,3}.dds` textures - `effect/background/mushrooma_{01,03,04}.mse` missing matching `.mde` mesh files - `effect/background/smh_gatetower01.mse` missing `effect/monster2/smoke_dust.dds` - `effect/background/turtle_statue_tree_roof_light01.mse` missing `turtle_statue_tree_roof_light01.mde` - `effect/etc/compete/ready.mse` missing `ready.DDS` It also now includes an audio scenario validator: - `scripts/validate_audio_scenarios.py` On the current real client runtime, the audio validator checks the full `*.mss` runtime script layer and now reports a single concrete missing audio reference: `sound2/sound/pc2/assassin/dualhand_sword/combo7.wav`. The previous cross-pack and wrong-path sound references were cleaned up in the runtime assets and are no longer part of the shared baseline. Those current actor and effect findings are also recorded in: - `known_issues/runtime_known_issues.json` The current audio findings are recorded there as well. That file is now the shared runtime baseline used by the validators and the aggregated release gate. Recommended next pack groups: 1. remaining startup-adjacent patch packs 2. remaining late-load gameplay content not covered yet 3. broader scenario-based validation for actor, effect, and sound content ## Risk notes - Do not mix silent fallback with production security claims. - Do not ship a client that accepts `.m2p` without runtime key enforcement. - Do not keep real secret keys inside the repository.