230 lines
6.4 KiB
Markdown
230 lines
6.4 KiB
Markdown
# 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`
|
|
|
|
The current actor validator now resolves real `MotionFileName` targets from
|
|
`.msa` files instead of assuming every motion uses a same-name local `.gr2`.
|
|
That removed the old false positives from redirected actor motions, and the
|
|
remaining `orc_lord` mismatch was fixed in the runtime assets by correcting
|
|
`30_1.msa` to point to `30_1.GR2`.
|
|
|
|
On the current real client runtime, the actor validator now passes cleanly.
|
|
|
|
It still verifies:
|
|
|
|
- `.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 now reports 10 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/turtle_statue_tree_roof_light01.mse` missing `turtle_statue_tree_roof_light01.mde`
|
|
|
|
Two earlier effect-path issues were cleaned up in the runtime assets by adding
|
|
safe aliases for already existing textures:
|
|
|
|
- `effect/background/smh_gatetower01.mse` now resolves `effect/monster2/smoke_dust.dds`
|
|
- `effect/etc/compete/ready.mse` now resolves `effect/etc/compete/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 no longer reports any missing audio references. The
|
|
previous cross-pack and wrong-path sound references were cleaned up in the
|
|
runtime assets, and the last remaining `combo7.wav` issue was resolved by
|
|
aligning `combo_07.mss` with the byte-identical `combo_08` motion variant.
|
|
|
|
The current effect findings are recorded in:
|
|
|
|
- `known_issues/runtime_known_issues.json`
|
|
|
|
Actor and audio are currently clean in that baseline.
|
|
|
|
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.
|