20 KiB
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) withdotnet 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.devis 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 Win32is 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
RelWithDebInfoso we get a.pdbnext to the exe for crash dumps. - If the build fails, the full log is in
cmake-build.lognext 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\andvendor\subdirs and make sure your checkout is clean (git statusshould be empty). - Build succeeds but no
Metin2.exe: checkcmake-build.logfor 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 ~80–120 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_PROXYor equivalent. dotnet testfails (if you chose to run it): the tests run on Linux in CI. On Windows they should still pass; if they don't, capturepublish.logplus the failing test output and file an issue.
6. First run — launcher GUI
Set-Location C:\dev\metin\client
.\Metin2Launcher.exe
Expected behaviour:
- Avalonia window appears, 900×560 fixed size, with a banner, a status / progress panel on the left, and a news panel on the right.
- 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". - The Play button becomes enabled.
C:\dev\metin\client\.updates\launcher.logis 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 iswin-x64but must be run on 64-bit Windows (it is; Win32 apps work fine on x64). If you copied aMetin2.exebuild 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
- Click Play.
Metin2.exeshould start in a separate process within a couple of seconds. The launcher window should remain visible (or minimise, depending on the configured behaviour). - Language bar appears along the top of the Metin2 window.
- The Metin2 logo screen animates.
- A server picker shows one row:
01. Metin2/CH1 NORM.- Select it and click OK.
- 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.
- Create a fresh character of any class, any empire. Confirm.
- You should land on the first map (Yongbi / Seoungmahn depending on
empire). Move with
WASD, open the menu withESC, try the chat by pressingEnterand 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 workingdialog, 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 ownserverinfofile. CheckC:\dev\metin\client\serverinfo.pyor whatever config points at the live server's IP. The audit branch has the current public IP ofmt2.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.ttfis still inC:\Windows\Fontsand hasn't been replaced by a custom font manager. - SmartScreen / Defender quarantine.
Metin2Launcher.exeandMetin2.exeare 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 tolog\,config\,.updates\, and into its own install dir; UAC will silently redirect writes to%LOCALAPPDATA%\VirtualStoreand 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.exesilently 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.exetries 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 inlauncher.log. Use a plain-ASCII user or setC:\dev\metinfrom 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 tojann/metin-launcherwith 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:
- Clone
m2dev-client→C:\dev\metin\client. - Download the latest CI artifact of
Metin2Launcher.exefromjann/metin-launcherreleases (once CI is wired; until then, build it yourself per step 5). - Drop the launcher next to
client\Metin2.exe. - Run
Metin2Launcher.exe. Click Play. Done.
No MSVC needed. If this path fails but the full build path in steps 4–7 works, the bug is in the prebuilt binary, not in the source tree.