Files
m2pack-secure/docs/migration.md

5.8 KiB

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
  • 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:

python3 scripts/validate_runtime_gate.py \
  --runtime-root /tmp/m2dev-client-runtime-http

For release tightening:

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

Those current actor and effect findings are also recorded in:

  • known_issues/runtime_known_issues.json

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.