# 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` ## 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. Validate asset loads in logs and in-game. 7. Move to the next pack group. ## 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` 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()` Recommended next pack groups: 1. remaining startup-adjacent patch packs 2. world and map content such as outdoor, terrain, tree, and zone 3. late-load gameplay content such as pc, npc, monster, and sound ## 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.