Files
m2dev-client-src/docs/runbook-windows-launch-test.md
2026-04-14 13:39:48 +02:00

20 KiB
Raw Permalink Blame History

Runbook: native Windows launch test

Audience: anyone on the team with a Windows 10/11 box and Visual Studio Build Tools 2022 installed. Primary target is Jakub or kolega 4.

Goal: end-to-end verification that Metin2Launcher.exe (from jann/metin-launcher) and Metin2.exe (from metin-server/m2dev-client-src) actually work on native Windows. So far the client is only confirmed working under Linux+Wine (m2dev-client/docs/linux-wine.md). A Windows native run closes that gap before anyone else wastes time tracking Wine-specific artefacts.

This runbook is Windows-first by design and aligns with this repo's AGENTS.md (Windows is the canonical target for m2dev-client-src). Nothing here modifies the C++ source — you only build and run.

Time budget: ~2 h from a clean Windows box to "character walking on the first map".


0. Scope and non-goals

Covered:

  • Installing the toolchain
  • Cloning both source repos + the runtime client assets
  • Building the C++ client (Metin2.exe) with MSVC
  • Building the launcher (Metin2Launcher.exe) with dotnet publish
  • First launch, login, character create, entering game
  • What to capture when anything breaks
  • Common Windows-specific pitfalls and their fixes
  • How to roll back to a clean client if you break the install
  • Where to file findings

Explicitly NOT covered:

  • Any source-level debugging. If something crashes in C++ land, capture the logs + dump and file an issue; don't patch.
  • Running the server. The live VPS mt2.jakubkadlec.dev is what you'll be connecting to. Do not try to start a local server as part of this test.
  • Packaging, signing or distribution. That's a separate flow.

1. Prerequisites

Install these on the Windows box in this order. Skip items you already have.

Tool Why Installer
Visual Studio Build Tools 2022 MSVC cl.exe, Windows SDK, CMake integration https://aka.ms/vs/17/release/vs_BuildTools.exe — during install tick Desktop development with C++ (brings MSVC v143, Windows 11 SDK, CMake).
Git for Windows git, bash, line-ending handling https://git-scm.com/download/win
.NET 8 SDK (x64) dotnet publish for the launcher https://dotnet.microsoft.com/en-us/download/dotnet/8.0
PowerShell 7.4+ better terminal, required for copy-paste blocks below https://github.com/PowerShell/PowerShell/releases/latest
(optional) Windows Terminal Multi-tab terminal, much nicer than conhost Microsoft Store

Do not install a separate CMake unless you already use one; the Build Tools ship a recent CMake and the Developer PowerShell for VS 2022 shortcut puts it on PATH.

Verify the toolchain

Open Developer PowerShell for VS 2022 (Start menu → "Developer PowerShell") and run:

cl          # expected: Microsoft (R) C/C++ Optimizing Compiler Version 19.4x
cmake --version  # expected: cmake version 3.28+
git --version
dotnet --list-sdks    # must show an 8.0.x entry

If any of these fail: the rest of the runbook won't work. Re-run the Build Tools installer and tick Desktop development with C++. Close and reopen Developer PowerShell afterwards.


2. Choose a working directory

Pick a path that is NOT under OneDrive, Documents, Desktop, or C:\Program Files. OneDrive sync mangles pack files and locks them mid-build; Program Files needs admin writes and triggers UAC prompts per-file.

Recommended:

$root = "C:\dev\metin"
New-Item -ItemType Directory -Force -Path $root | Out-Null
Set-Location $root

From here on, all path snippets assume C:\dev\metin as the root.


3. Clone the three repos

All three are on gitea.jakubkadlec.dev. You need an SSH key on that server (same one you use for the rest of the project). If you've never cloned from Gitea before, use HTTPS + a Gitea personal access token instead — both work.

Set-Location C:\dev\metin

# 1) C++ client source (this repo)
git clone ssh://git@gitea.jakubkadlec.dev:2222/metin-server/m2dev-client-src.git

# 2) C# launcher
git clone ssh://git@gitea.jakubkadlec.dev:2222/jann/metin-launcher.git

# 3) client runtime assets (packs, bgm, config, log dir, Metin2.exe prebuilt)
#    Skip this if you already have a populated client\ folder from an older
#    Windows install.
git clone ssh://git@gitea.jakubkadlec.dev:2222/metin-server/m2dev-client.git client

m2dev-client is ~4 GB because it contains the packed assets (pack\*.pck, bgm\, assets\). Expect the clone to take several minutes. Git LFS is not used — everything is vanilla git, large files included.

Expected layout after this step:

C:\dev\metin\
├── m2dev-client-src\        ← C++ source, CMakeLists.txt at root
├── metin-launcher\          ← C# source, Launcher.sln at root
└── client\                  ← runtime: assets\, pack\, bgm\, config\, log\, Metin2.exe (prebuilt)

If client\Metin2.exe already works for you you can skip the C++ build in step 4 and only replace Metin2.exe if step 4 produces a newer one.


4. Build the C++ client (Metin2.exe)

From Developer PowerShell for VS 2022 (important — regular PowerShell won't see cl.exe):

Set-Location C:\dev\metin\m2dev-client-src
New-Item -ItemType Directory -Force -Path build | Out-Null
Set-Location build

cmake .. -G "Visual Studio 17 2022" -A Win32 2>&1 | Tee-Object ..\cmake-configure.log
cmake --build . --config RelWithDebInfo 2>&1 | Tee-Object ..\cmake-build.log

Notes:

  • -A Win32 is intentional. The client is 32-bit because of FMOD, Granny 2, the embedded Python, and decades of assumptions in EterLib. A 64-bit build will not produce a runnable exe today.
  • Use RelWithDebInfo so we get a .pdb next to the exe for crash dumps.
  • If the build fails, the full log is in cmake-build.log next to the build dir. Attach that file verbatim when filing the issue — do not paraphrase.

Expected output:

C:\dev\metin\m2dev-client-src\build\...\RelWithDebInfo\Metin2.exe
C:\dev\metin\m2dev-client-src\build\...\RelWithDebInfo\Metin2.pdb

Copy the exe into the runtime client directory, overwriting the prebuilt one (keep a backup):

$client = "C:\dev\metin\client"
Copy-Item $client\Metin2.exe $client\Metin2.exe.backup -ErrorAction SilentlyContinue

$built = Get-ChildItem -Recurse -Filter Metin2.exe C:\dev\metin\m2dev-client-src\build |
         Where-Object { $_.FullName -like "*RelWithDebInfo*" } | Select-Object -First 1
Copy-Item $built.FullName $client\Metin2.exe -Force
Copy-Item ($built.FullName -replace '\.exe$','.pdb') $client\ -Force

If it fails:

  • Missing cl.exe / link.exe: you're in the wrong shell. Use the Developer PowerShell shortcut.
  • "Cannot open include file: 'd3d9.h'": Windows SDK is missing. Re-run Build Tools installer and tick the Windows 11 SDK.
  • "LNK2019 unresolved external" against FMOD / Granny / Python: the build tree is picking up the wrong vendored lib. Check extern\ and vendor\ subdirs and make sure your checkout is clean (git status should be empty).
  • Build succeeds but no Metin2.exe: check cmake-build.log for the actual target name — upstream may have it under a slightly different casing.

5. Build the launcher (Metin2Launcher.exe)

From a regular PowerShell 7 window (Developer PowerShell also works, but dotnet doesn't need the MSVC env):

Set-Location C:\dev\metin\metin-launcher

dotnet publish src\Metin2Launcher\Metin2Launcher.csproj `
  -c Release `
  -r win-x64 `
  --self-contained `
  -p:PublishSingleFile=true `
  -p:IncludeNativeLibrariesForSelfExtract=true `
  2>&1 | Tee-Object publish.log

Expected output:

C:\dev\metin\metin-launcher\src\Metin2Launcher\bin\Release\net8.0\win-x64\publish\Metin2Launcher.exe

The single-file exe is ~80120 MB because Avalonia + .NET runtime are bundled. That's normal.

Copy it next to Metin2.exe:

Copy-Item `
  C:\dev\metin\metin-launcher\src\Metin2Launcher\bin\Release\net8.0\win-x64\publish\Metin2Launcher.exe `
  C:\dev\metin\client\Metin2Launcher.exe -Force

If it fails:

  • "SDK 8.0.x not found": install .NET 8 SDK, then reopen the shell.
  • Avalonia / Velopack restore errors: check internet connectivity, the build pulls packages from nuget.org. Corporate proxies will need NUGET_HTTP_PROXY or equivalent.
  • dotnet test fails (if you chose to run it): the tests run on Linux in CI. On Windows they should still pass; if they don't, capture publish.log plus the failing test output and file an issue.

6. First run — launcher GUI

Set-Location C:\dev\metin\client
.\Metin2Launcher.exe

Expected behaviour:

  1. Avalonia window appears, 900×560 fixed size, with a banner, a status / progress panel on the left, and a news panel on the right.
  2. Launcher attempts to fetch https://updates.jakubkadlec.dev/manifest.json. DNS for that host is currently broken on purpose; the launcher should time out and fall back to "Server unreachable — using local client".
  3. The Play button becomes enabled.
  4. C:\dev\metin\client\.updates\launcher.log is created and starts getting lines written to it.

If the launcher window never shows up:

  • Run from a terminal and watch stdout — Velopack bootstrapping errors land on stderr only. Redirect with .\Metin2Launcher.exe 2>&1 | Tee-Object launcher-stdout.log.
  • SmartScreen may have quarantined the exe because it's unsigned. Windows Defender → Protection history → Allow. Or right-click the exe → Properties → Unblock.
  • If you see This app can't run on your PC, you built for the wrong arch. The launcher is win-x64 but must be run on 64-bit Windows (it is; Win32 apps work fine on x64). If you copied a Metin2.exe build instead, you'll see this; re-check step 5.

If the status panel stays at "Checking for updates..." forever:

  • Expected to time out within ~15 s and flip to "Server unreachable". If it never does, the launcher is stuck in a DNS retry loop. Close it, grab .updates\launcher.log, and file the log — this is a launcher bug, not a client bug.

7. Play — reach the game

  1. Click Play. Metin2.exe should start in a separate process within a couple of seconds. The launcher window should remain visible (or minimise, depending on the configured behaviour).
  2. Language bar appears along the top of the Metin2 window.
  3. The Metin2 logo screen animates.
  4. A server picker shows one row: 01. Metin2 / CH1 NORM.
    • Select it and click OK.
  5. Login screen:
    • Register a new account (the server allows on-the-fly registration — use a throwaway ID and password). Or use an existing account if you have one.
    • Proceed to character selection.
  6. Create a fresh character of any class, any empire. Confirm.
  7. You should land on the first map (Yongbi / Seoungmahn depending on empire). Move with WASD, open the menu with ESC, try the chat by pressing Enter and typing a line.

Acceptance bar for this runbook: you reached the first map, you can move, chat works. Anything beyond that is a nice-to-have.

If Metin2.exe crashes on click-Play:

  • Look in C:\dev\metin\client\log\syserr.txt. That file is how the client's legacy error reporter logs crashes. The last dozen lines are usually enough to classify the failure.
  • If Windows shows a .exe has stopped working dialog, check Event Viewer → Windows Logs → Application for the Faulting Module entry.
  • If it silently exits, the problem is usually missing DirectX runtime (d3dx9). Install the legacy DirectX End-User Runtimes (June 2010) from Microsoft.

If login fails with "Connection closed":

  • This is the DNS breakage again. The launcher's fallback path does not help Metin2.exe, which reads its own serverinfo file. Check C:\dev\metin\client\serverinfo.py or whatever config points at the live server's IP. The audit branch has the current public IP of mt2.jakubkadlec.dev.

8. What to capture and send back

Regardless of whether it worked or not, collect and attach these to a Gitea issue in metin-server/m2dev-client-src with label windows-test:

File Why
client\.updates\launcher.log Launcher side — manifest fetch, update decisions, Play-button flow.
client\log\syserr.txt C++ client crashes and asserts.
client\log\packetdump.txt (if present) Last packets before disconnect/crash; rare but invaluable for login breaks.
m2dev-client-src\cmake-configure.log Build: CMake configuration output.
m2dev-client-src\cmake-build.log Build: MSVC compile output. Verbatim, not paraphrased.
metin-launcher\publish.log Launcher publish output.
Screenshots Any visual glitch, stuck screen, or error dialog.
Windows version (winver) + MSVC version (cl) Paste at top of issue.
GPU + driver version dxdiag → Save All Information → attach DxDiag.txt.

Zip the whole set:

$stamp = Get-Date -Format "yyyyMMdd-HHmmss"
Compress-Archive -Path `
  C:\dev\metin\client\.updates\launcher.log, `
  C:\dev\metin\client\log\syserr.txt, `
  C:\dev\metin\client\log\packetdump.txt, `
  C:\dev\metin\m2dev-client-src\cmake-configure.log, `
  C:\dev\metin\m2dev-client-src\cmake-build.log, `
  C:\dev\metin\metin-launcher\publish.log `
  -DestinationPath "$env:USERPROFILE\Desktop\windows-test-$stamp.zip" `
  -ErrorAction SilentlyContinue

Missing files are fine — the -ErrorAction SilentlyContinue keeps the command going if one of them doesn't exist (e.g. packetdump.txt on a successful run).


9. Windows-specific gotchas

Distilled from m2dev-client/docs/linux-wine.md (Wine oddities that also apply on Windows in different forms) and from general Windows experience with legacy 32-bit game clients:

  • Tahoma font. On fresh Wine prefixes you have to install it; on Windows it's always present, so this should be a non-issue. If text is missing on the login screen, check fonts\Tahoma.ttf is still in C:\Windows\Fonts and hasn't been replaced by a custom font manager.
  • SmartScreen / Defender quarantine. Metin2Launcher.exe and Metin2.exe are unsigned. On first run Windows will warn and may move them to quarantine. Either sign them (out of scope for this runbook), or Allow + Unblock per-file in Properties.
  • UAC + C:\Program Files. Don't install there. The client writes to log\, config\, .updates\, and into its own install dir; UAC will silently redirect writes to %LOCALAPPDATA%\VirtualStore and you'll chase phantom bugs.
  • OneDrive / Documents / Desktop. Same reason. OneDrive can lock files during sync, which corrupts pack reads. Use C:\dev\metin.
  • Antivirus with heuristic scanning. The 32-bit client, the embedded Python, the unsigned exe, plus FMOD unpacking into temp, together look like a toy virus to aggressive AVs. If the process is killed mid-load check the AV quarantine first.
  • DirectX End-User Runtimes. Modern Windows still doesn't install the d3dx9 helper DLLs by default. If the launcher works but Metin2.exe silently exits, install the DirectX End-User Runtimes (June 2010) package from Microsoft.
  • Display scaling. The client is DPI-unaware. On a 4K laptop with 150% scaling the window can render as a tiny 900×600 rectangle. Right- click Metin2.exe → Properties → Compatibility → Change high DPI settings → tick "Override high DPI scaling behavior" = System.
  • Windows Firewall prompt on first connect. The first time Metin2.exe tries to reach port 11000, Defender Firewall will ask. Allow on private networks at minimum.
  • 32-bit vs 64-bit confusion. The client is strictly 32-bit. If a Python extension or native DLL is built x64 you'll get a load error on startup. Check the build arch on every custom DLL.
  • Non-English locale. The client's Python side assumes certain code pages. If you run on a system with a non-ASCII username (C:\Users\ Jánek), watch for path encoding issues in launcher.log. Use a plain-ASCII user or set C:\dev\metin from the root of the drive.

10. Rollback / reset to a known state

If you've made a mess and want to start over without re-cloning 4 GB of assets:

Set-Location C:\dev\metin\client

# Restore original Metin2.exe if you kept the backup
if (Test-Path Metin2.exe.backup) { Copy-Item Metin2.exe.backup Metin2.exe -Force }

# Wipe launcher + updater state
Remove-Item -Recurse -Force .\.updates -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force .\log     -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Path .\log | Out-Null

# Remove the launcher exe; it'll be re-copied from the publish dir next time
Remove-Item .\Metin2Launcher.exe -ErrorAction SilentlyContinue

The runtime asset tree (pack\, assets\, bgm\) is read-only during a normal run, so you almost never have to re-pull it. If you do need to reset everything to HEAD:

Set-Location C:\dev\metin\client
git reset --hard origin/main
git clean -fdx

Do NOT git clean -fdx inside m2dev-client-src\ unless you're ready to re-download vendored third-party trees that may not be on disk elsewhere.


11. Where to report findings

File a new issue in metin-server/m2dev-client-src on gitea.jakubkadlec.dev:

  • Title: windows-test: <one-line summary>, e.g. windows-test: launcher OK, Metin2.exe crashes in EterLib on first map.
  • Label: windows-test. Create the label if it doesn't exist.
  • Body: a short timeline of what you did, which step in this runbook failed (e.g. "Step 7, after clicking OK in server picker"), and the zipfile from step 8 attached.
  • Assign Jan (jann) for triage. For launcher-only issues, cross-link to jann/metin-launcher with the same label.

If everything worked end-to-end, still file an issue titled windows-test: full run PASS <date> with the zip attached — we want a reproducible baseline of a good Windows run on record.


Appendix A — the absolute-minimum fast path

For when you just want to verify "does it start at all" and don't care about building from source:

  1. Clone m2dev-clientC:\dev\metin\client.
  2. Download the latest CI artifact of Metin2Launcher.exe from jann/metin-launcher releases (once CI is wired; until then, build it yourself per step 5).
  3. Drop the launcher next to client\Metin2.exe.
  4. Run Metin2Launcher.exe. Click Play. Done.

No MSVC needed. If this path fails but the full build path in steps 47 works, the bug is in the prebuilt binary, not in the source tree.