Compare commits
23 Commits
e23f4e1e6e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6212559b41 | ||
|
|
e6b4060e5c | ||
|
|
73446a0a60 | ||
|
|
db1f2f435b | ||
|
|
3db306fbc7 | ||
|
|
db59f4963c | ||
|
|
ac0034fc51 | ||
|
|
8f6f378a23 | ||
|
|
027786a79d | ||
|
|
d2775bcfd8 | ||
|
|
9ffae5c7d9 | ||
|
|
1790502b58 | ||
|
|
0e95171e50 | ||
|
|
6ad8e8db19 | ||
|
|
3d98ac4470 | ||
|
|
ee7edfd990 | ||
|
|
dcc2b0fc42 | ||
|
|
5edd0c5aea | ||
|
|
3d3129032a | ||
|
|
0526ac2ef9 | ||
|
|
3f8acfc597 | ||
|
|
d9d45d0010 | ||
|
|
ad78f8f139 |
14
.gitignore
vendored
14
.gitignore
vendored
@@ -4,3 +4,17 @@ obj/
|
||||
*.suo
|
||||
.vs/
|
||||
publish/
|
||||
|
||||
# Runtime client data accidentally left when launcher is run from its bin dir
|
||||
# (CWD becomes the source tree). These should never be committed.
|
||||
src/Metin2Launcher/.updates/
|
||||
src/Metin2Launcher/bgm/
|
||||
src/Metin2Launcher/config/
|
||||
src/Metin2Launcher/mark/
|
||||
src/Metin2Launcher/pack/
|
||||
src/Metin2Launcher/log/
|
||||
src/Metin2Launcher/Metin2.exe
|
||||
src/Metin2Launcher/*.dll
|
||||
src/Metin2Launcher/*.pyd
|
||||
src/Metin2Launcher/python314*
|
||||
src/Metin2Launcher/runtime-key.json
|
||||
|
||||
49
CHANGELOG.md
Normal file
49
CHANGELOG.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to `metin-launcher` are tracked here. Format loosely
|
||||
follows Keep a Changelog; dates are Europe/Prague.
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- Release format dispatch. The manifest now carries an optional top-level
|
||||
`format` field (defaults to `legacy-json-blob`) and the orchestrator
|
||||
resolves an `IReleaseFormat` strategy via `ReleaseFormatFactory`.
|
||||
- `M2PackFormat`: new release format that lists `.m2p` pack archives plus a
|
||||
`runtime-key.json` sidecar. The launcher never opens or decrypts `.m2p`
|
||||
archives; it only places them next to the client root and loads the
|
||||
runtime key after apply.
|
||||
- `RuntimeKey` model + `IRuntimeKeyDelivery` strategy. `EnvVarKeyDelivery`
|
||||
is the MVP implementation and forwards `M2PACK_MASTER_KEY_HEX`,
|
||||
`M2PACK_SIGN_PUBKEY_HEX` and `M2PACK_KEY_ID` to the child process scoped
|
||||
to `ProcessStartInfo.Environment` only. `SharedMemoryKeyDelivery` is
|
||||
documented as a stub and throws until the Windows receiver lands.
|
||||
- `GameProcess.BuildStartInfo` now accepts an optional `RuntimeKey?` and
|
||||
forwards it through the env-var delivery.
|
||||
- `ClientAppliedReporter`: opt-in best-effort telemetry ping that fires
|
||||
once after a successful apply with a 5-second cap. Disabled by default
|
||||
(`LauncherConfig.TelemetryUrlTemplate == ""`). Failures are always
|
||||
swallowed and logged as warnings.
|
||||
- `docs/m2pack-integration.md` documenting the signature boundary, runtime
|
||||
key delivery, telemetry, backward compatibility and file layout.
|
||||
- ~60 new tests across `RuntimeKeyTests`, `EnvVarDeliveryTests`,
|
||||
`LegacyJsonBlobFormatTests`, `M2PackFormatTests`, `ReleaseFormatFactoryTests`,
|
||||
`ClientAppliedReporterTests`, `UpdateOrchestratorFormatDispatchTests` and
|
||||
extended `GameProcessTests`. Total suite is ~92 tests.
|
||||
|
||||
### Changed
|
||||
- `UpdateOrchestrator` dispatches through `ReleaseFormatFactory` after
|
||||
signature verification. The legacy flow is preserved byte-for-byte for
|
||||
manifests without a `format` field; the only visible difference is that
|
||||
the complete log line now reads `format=legacy-json-blob`.
|
||||
- `UpdateOrchestrator.Result` gained `Format` and `RuntimeKey` slots so the
|
||||
headless entry point can forward the runtime key into `GameProcess.Launch`.
|
||||
|
||||
### Security
|
||||
- A signed manifest carrying an unknown `format` value is refused outright
|
||||
rather than silently falling back to legacy, preventing a downgrade
|
||||
attack vector in the event of a signing key compromise.
|
||||
- Env vars produced by `EnvVarKeyDelivery` are scoped to the spawned
|
||||
child's environment only. The launcher never mutates its own process
|
||||
environment, so other processes on the machine and later code in the
|
||||
launcher itself cannot read the key.
|
||||
88
README.md
88
README.md
@@ -34,6 +34,67 @@ dotnet publish src/Metin2Launcher/Metin2Launcher.csproj \
|
||||
|
||||
The CI hasn't been wired yet; the MVP only requires the build to succeed.
|
||||
|
||||
## Build (Wine bundle)
|
||||
|
||||
For Linux users who run the Windows launcher through Wine, the safe layout is
|
||||
not a single `Metin2Launcher.exe`. The Wine-compatible launcher currently needs
|
||||
the non-single-file `win-x64` publish output, and it must live separately from
|
||||
the mutable client install dir so the updater does not patch over its own
|
||||
runtime files.
|
||||
|
||||
Use:
|
||||
|
||||
```
|
||||
scripts/build-wine-bundle.sh
|
||||
```
|
||||
|
||||
This produces:
|
||||
|
||||
```
|
||||
release-wine/
|
||||
Metin2Launcher-wine/
|
||||
start-launcher.sh
|
||||
README.txt
|
||||
launcher/
|
||||
Metin2Launcher.exe
|
||||
*.dll
|
||||
client/
|
||||
Metin2Launcher-wine.tar.gz
|
||||
```
|
||||
|
||||
`start-launcher.sh` exports `METIN2_INSTALL_DIR=./client` and then runs
|
||||
`wine ./launcher/Metin2Launcher.exe`, so the launcher runtime stays isolated
|
||||
from the actual game files.
|
||||
|
||||
## Publishing a release
|
||||
|
||||
`scripts/publish-launcher.sh` is the single entry point for cutting a Velopack
|
||||
release of the launcher and pushing it to the
|
||||
`https://updates.jakubkadlec.dev/launcher/` feed that
|
||||
`LauncherConfig.VelopackFeedUrl` points at. It runs `dotnet publish` for
|
||||
`win-x64` self-contained single-file, then drives `vpk pack` (Velopack CLI
|
||||
global tool, auto-installed on first run) with `--packId Metin2Launcher
|
||||
--channel win-x64 --mainExe Metin2Launcher.exe`, and finally rsyncs the
|
||||
resulting `RELEASES-win-x64` + `*.nupkg` (full + delta) to the VPS.
|
||||
|
||||
```
|
||||
scripts/publish-launcher.sh --version 0.1.0 --dry-run
|
||||
scripts/publish-launcher.sh --version 0.1.0 --yes
|
||||
```
|
||||
|
||||
Flags: `--version` (required), `--dry-run` (build + pack but skip rsync),
|
||||
`--yes` (skip the interactive rsync confirmation), `--rsync-target` (override
|
||||
the default VPS path).
|
||||
|
||||
**Known limitation (2026-04-14):** Velopack's `vpk pack` is platform-routed.
|
||||
On a Linux host it only builds Linux `.AppImage` bundles and refuses to pack
|
||||
the win-x64 publish output (it tries to ELF-parse `Metin2Launcher.exe` and
|
||||
crashes with `Given stream is not a proper ELF file`). Building the win-x64
|
||||
Velopack release therefore needs a Windows host. The script is correct —
|
||||
it's the toolchain that's gated. Once we have a Windows CI runner this can
|
||||
be wired into Gitea Actions; until then run the script on a Windows dev box.
|
||||
The `dotnet publish` step on Linux still works and is a useful sanity check.
|
||||
|
||||
## Run
|
||||
|
||||
By default the launcher opens an Avalonia GUI window (900x560, fixed size)
|
||||
@@ -63,6 +124,9 @@ and run it. On first launch it will:
|
||||
dev builds)
|
||||
5. start `Metin2.exe`
|
||||
|
||||
For the Wine bundle layout, do not run the launcher from the mutable client
|
||||
directory. Run `./start-launcher.sh` from the bundle root instead.
|
||||
|
||||
A log is written to both stdout and `<client>/.updates/launcher.log`. On a plain
|
||||
`dotnet run` (no client root yet), the log falls back to
|
||||
`%LOCALAPPDATA%/Metin2Launcher/launcher.log` on Windows or
|
||||
@@ -96,6 +160,30 @@ tests/Metin2Launcher.Tests/
|
||||
game assets (~4 GB) are handled by our own patcher code.
|
||||
- **xunit / xunit.runner.visualstudio** — tests.
|
||||
|
||||
## Release formats
|
||||
|
||||
The launcher dispatches on a top-level `format` field in the signed manifest.
|
||||
Two strategies exist today:
|
||||
|
||||
- `legacy-json-blob` (default when `format` is absent) — individual files
|
||||
listed in `files[]`, downloaded by sha256 and atomically replaced inside
|
||||
the client root.
|
||||
- `m2pack` — the `files[]` entries are `.m2p` pack archives plus a
|
||||
`runtime-key.json` sidecar. The launcher **never** opens or decrypts
|
||||
`.m2p` archives; it just places them next to the client root and forwards
|
||||
the runtime key to `Metin2.exe` via environment variables
|
||||
(`M2PACK_MASTER_KEY_HEX`, `M2PACK_SIGN_PUBKEY_HEX`, `M2PACK_KEY_ID`).
|
||||
|
||||
A manifest whose `format` value is signed but unknown is refused outright —
|
||||
the orchestrator falls back to offline mode rather than silently downgrading.
|
||||
See `docs/m2pack-integration.md` for the full threat model and file layout.
|
||||
|
||||
An opt-in "client applied this release" telemetry ping is available via
|
||||
`LauncherConfig.TelemetryUrlTemplate`. It is empty by default, which short-
|
||||
circuits the reporter so no network call is made. When set, the reporter
|
||||
fires a single bounded (5s) best-effort POST after a successful apply and
|
||||
swallows any failure.
|
||||
|
||||
## Signing key
|
||||
|
||||
`LauncherConfig.PublicKeyHex` is the Ed25519 public key that every manifest
|
||||
|
||||
114
docs/m2pack-integration.md
Normal file
114
docs/m2pack-integration.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# m2pack integration
|
||||
|
||||
Notes on how `metin-launcher` handles the m2pack release format. Written when the
|
||||
launcher-side support landed on `claude/m2pack-launcher`; the client-side receiver
|
||||
for the runtime key is tracked separately.
|
||||
|
||||
## Scope
|
||||
|
||||
The launcher's job in an m2pack release is narrowly defined:
|
||||
|
||||
1. Fetch the signed `manifest.json` and its `.sig` exactly as before.
|
||||
2. Verify Ed25519 signature against the compiled-in public key, exactly as before.
|
||||
3. Read the new top-level `format` field (falling back to `legacy-json-blob`).
|
||||
4. Dispatch through `ReleaseFormatFactory.Resolve(...)` to an `IReleaseFormat`.
|
||||
5. Diff, download and atomically apply the file entries listed in the manifest.
|
||||
For m2pack these are `.m2p` pack archives plus a `runtime-key.json` sidecar.
|
||||
6. **Never** open, decrypt or decompress a `.m2p` archive. Integrity of the
|
||||
archive contents is the client's problem, gated on the runtime key.
|
||||
7. Load `runtime-key.json` from the client root and forward it to `Metin2.exe`
|
||||
via environment variables (`M2PACK_MASTER_KEY_HEX`, `M2PACK_SIGN_PUBKEY_HEX`,
|
||||
`M2PACK_KEY_ID`), scoped to the child process only.
|
||||
|
||||
Anything beyond step 7 — parsing the archive, selecting pack files, decrypting
|
||||
blocks, validating per-file signatures — lives in the client. The launcher is
|
||||
deliberately dumb about `.m2p`.
|
||||
|
||||
## Signature boundary
|
||||
|
||||
The Ed25519 signature stays on the top-level `manifest.json`. `.m2p` files are
|
||||
each a single `files[]` entry with a `sha256`, exactly like any other blob —
|
||||
that's enough to detect tampering or incomplete downloads, and tamper-resistance
|
||||
of the content-addressed URL is inherited from the signed manifest.
|
||||
|
||||
The `runtime-key.json` sidecar is listed in the manifest in the same way, so
|
||||
its integrity is also covered by the manifest signature. We do **not** sign the
|
||||
runtime key independently.
|
||||
|
||||
## Runtime key delivery
|
||||
|
||||
Two delivery strategies are defined behind `IRuntimeKeyDelivery`:
|
||||
|
||||
- `EnvVarKeyDelivery` — MVP, used on every platform. Sets
|
||||
`M2PACK_MASTER_KEY_HEX`, `M2PACK_SIGN_PUBKEY_HEX` and `M2PACK_KEY_ID` on the
|
||||
child `ProcessStartInfo.Environment`. The launcher never sets these on its
|
||||
own process environment, so unrelated processes can't snoop them and the
|
||||
values don't leak via `Environment.GetEnvironmentVariable` calls elsewhere
|
||||
in the launcher.
|
||||
- `SharedMemoryKeyDelivery` — Windows stub. Not implemented. See the class
|
||||
docs for the planned approach (named `MemoryMappedFile` with a random
|
||||
suffix, write-then-zero lifecycle, child reads via mapping name passed in
|
||||
env). Left as a stub because the client-side receiver hasn't landed.
|
||||
|
||||
Threat model note: env vars are readable by any process that shares the
|
||||
parent's user on Linux (`/proc/$pid/environ`, gated by `ptrace_scope` and by
|
||||
file mode). That's identical to the current legacy flow in terms of secret
|
||||
handling — the legacy release also trusts the local user — and the shared
|
||||
memory strategy is planned for a future hardening pass, not as an MVP
|
||||
requirement.
|
||||
|
||||
## Telemetry
|
||||
|
||||
`ClientAppliedReporter` is wired but disabled by default: `LauncherConfig.TelemetryUrlTemplate`
|
||||
is empty. When set to a non-empty URL template (supporting `{format}` and
|
||||
`{version}` placeholders) the reporter fires a single bounded POST after a
|
||||
successful apply, with a hard 5-second timeout and warning-level logging on
|
||||
failure. Failures never block the launch flow and are never retried.
|
||||
|
||||
The payload is intentionally small: `format`, `version`, `timestamp`. Nothing
|
||||
personally identifying.
|
||||
|
||||
## Backward compatibility
|
||||
|
||||
Existing installs pointing at a manifest without a `format` field continue to
|
||||
parse exactly as before: `Manifest.EffectiveFormat` defaults to
|
||||
`legacy-json-blob` and `LegacyJsonBlobFormat` is a near-verbatim lift of the
|
||||
old inline behaviour. The only visible difference is that the orchestrator's
|
||||
log line now reads `format=legacy-json-blob`.
|
||||
|
||||
Signed manifests that ship an unknown `format` value are refused outright —
|
||||
`ReleaseFormatFactory.Resolve` throws and the orchestrator reports
|
||||
`OfflineFallback`. This prevents a future attacker who compromises the signing
|
||||
key from downgrading clients via a fabricated `format: "no-verify"` field.
|
||||
|
||||
## File layout on disk
|
||||
|
||||
```
|
||||
client/
|
||||
├── Metin2.exe
|
||||
├── runtime-key.json ← written from the manifest, loaded by M2PackFormat
|
||||
├── pack/
|
||||
│ ├── item.m2p ← staged/placed by the launcher, never opened
|
||||
│ ├── mob.m2p
|
||||
│ └── ...
|
||||
└── .updates/
|
||||
├── launcher.log
|
||||
├── current-manifest.json
|
||||
└── staging/ ← per-file resume, same as legacy
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Run `dotnet test -c Release` — the relevant suites are:
|
||||
|
||||
- `RuntimeKeyTests` — happy path, validation, load-from-disk
|
||||
- `EnvVarDeliveryTests` — scoped env mutation, no current-process leak
|
||||
- `LegacyJsonBlobFormatTests` / `M2PackFormatTests` / `ReleaseFormatFactoryTests`
|
||||
- `ClientAppliedReporterTests` — disabled-by-default, success, 500, timeout,
|
||||
connection refused
|
||||
- `UpdateOrchestratorFormatDispatchTests` — signature failure path, offline
|
||||
fallback when manifest fetch fails, result carries `Format` + `RuntimeKey`
|
||||
- Extended `GameProcessTests` asserting the runtime key gets forwarded through
|
||||
`BuildStartInfo` and does NOT leak into the launcher's own environment.
|
||||
|
||||
Total suite after this change is ~92 tests.
|
||||
466
docs/metin-release-cli-plan.md
Normal file
466
docs/metin-release-cli-plan.md
Normal file
@@ -0,0 +1,466 @@
|
||||
# metin-release-cli plan
|
||||
|
||||
Plan for a release orchestration toolchain that stays outside NewERP and lets
|
||||
the ERP module act only as the control plane.
|
||||
|
||||
## Goal
|
||||
|
||||
Build two components:
|
||||
|
||||
- `metin-release-cli` as the real operator and automation entry point
|
||||
- `metin-release-mcp` as a thin MCP wrapper over the CLI
|
||||
|
||||
The ERP module should not own manifest generation, signing, blob publishing, or
|
||||
launcher packaging logic. It should call the CLI through a stable contract and
|
||||
store release metadata, status, logs, and audit trail.
|
||||
|
||||
## Why this split
|
||||
|
||||
Current release concerns already live across multiple repos and runtimes:
|
||||
|
||||
- `metin-launcher` consumes signed `manifest.json` + blob storage
|
||||
- `m2dev-client` already has `make-manifest.py` and `sign-manifest.py`
|
||||
- `m2pack-secure` owns `.m2p` build, verify, diff, and runtime-key export
|
||||
- launcher self-update currently depends on Velopack packaging, which is still
|
||||
Windows-host constrained
|
||||
|
||||
Putting that logic into NewERP would duplicate the release path and make the ERP
|
||||
module too heavy. The CLI should own the workflow. ERP should orchestrate it.
|
||||
|
||||
## Design principles
|
||||
|
||||
- CLI first. Every real operation must be runnable without MCP.
|
||||
- JSON first. Every non-interactive CLI command must support machine-readable
|
||||
output.
|
||||
- Thin wrapper. MCP must call CLI commands, parse JSON, and return it. No
|
||||
duplicated business logic.
|
||||
- Explicit state. Releases move through named stages and emit durable logs.
|
||||
- Secret isolation. Signing keys and content keys stay on the release machine or
|
||||
in a secret store, never in ERP DB.
|
||||
- Linux-first. Manifest build, signing, blob publish, and `.m2p` validation must
|
||||
run on Linux. Windows-only launcher packaging remains a separate step.
|
||||
|
||||
## Scope
|
||||
|
||||
`metin-release-cli` should cover:
|
||||
|
||||
- create and validate a release workspace
|
||||
- build or import a release manifest
|
||||
- sign the manifest
|
||||
- diff against the currently published release
|
||||
- upload missing blobs to the update storage
|
||||
- archive historical manifests
|
||||
- promote a release to current
|
||||
- verify the public endpoint after publish
|
||||
- optionally record release metadata in ERP through HTTP API
|
||||
- optionally manage `.m2p` release artifacts and runtime-key export
|
||||
- optionally run launcher publish as a separate command
|
||||
|
||||
`metin-release-mcp` should cover:
|
||||
|
||||
- expose the same operations as MCP tools
|
||||
- map tool input to CLI flags
|
||||
- read CLI JSON output
|
||||
- pass through logs, status, and errors in structured form
|
||||
|
||||
## Non-goals
|
||||
|
||||
- No manifest generation inside ERP PHP code
|
||||
- No signing inside ERP
|
||||
- No heavy artifact proxying through ERP uploads for multi-GB releases
|
||||
- No duplicated publish logic in MCP
|
||||
- No attempt to hide Windows constraints for Velopack launcher packaging
|
||||
|
||||
## Canonical release path
|
||||
|
||||
For the current launcher contract, the canonical asset release path is:
|
||||
|
||||
1. obtain a prepared client root on Linux
|
||||
2. generate `manifest.json`
|
||||
3. sign `manifest.json`
|
||||
4. compute which content-addressed blobs are missing remotely
|
||||
5. upload missing blobs
|
||||
6. upload archived manifest under `manifests/<version>.json`
|
||||
7. upload archived signature under `manifests/<version>.json.sig`
|
||||
8. switch top-level `manifest.json` and `manifest.json.sig`
|
||||
9. verify the public endpoint
|
||||
10. report final release metadata to ERP
|
||||
|
||||
For launcher self-update, the path is separate:
|
||||
|
||||
1. build win-x64 launcher package on Windows-capable host
|
||||
2. publish Velopack feed into `/launcher/`
|
||||
3. optionally annotate the same release in ERP
|
||||
|
||||
## Proposed architecture
|
||||
|
||||
### 1. metin-release-cli
|
||||
|
||||
Suggested implementation language:
|
||||
|
||||
- Python is the pragmatic default because the current manifest tooling already
|
||||
exists in Python
|
||||
- shell scripts may wrap platform-specific steps, but the primary interface
|
||||
should be one CLI executable with stable subcommands
|
||||
|
||||
Suggested internal modules:
|
||||
|
||||
- `workspace`
|
||||
- resolve source roots, temp dirs, release output dirs
|
||||
- `manifest`
|
||||
- call or absorb `make-manifest.py`
|
||||
- `signing`
|
||||
- call or absorb `sign-manifest.py`
|
||||
- `storage`
|
||||
- remote existence checks
|
||||
- blob upload
|
||||
- manifest archive upload
|
||||
- current manifest promotion
|
||||
- `verify`
|
||||
- verify local artifacts
|
||||
- verify public HTTP endpoint
|
||||
- `erp`
|
||||
- create/update release records in ERP
|
||||
- `m2pack`
|
||||
- optional integration with `m2pack-secure`
|
||||
- `launcher`
|
||||
- optional launcher publish integration
|
||||
|
||||
### 2. metin-release-mcp
|
||||
|
||||
Suggested shape:
|
||||
|
||||
- one MCP server process
|
||||
- each tool maps 1:1 to one CLI subcommand
|
||||
- wrapper only:
|
||||
- validates tool input
|
||||
- spawns CLI
|
||||
- parses JSON stdout
|
||||
- returns structured result
|
||||
- forwards stderr as diagnostic text
|
||||
|
||||
No release decision logic should live here.
|
||||
|
||||
## Release state model
|
||||
|
||||
The CLI should emit explicit states the ERP module can mirror:
|
||||
|
||||
- `draft`
|
||||
- `scanning`
|
||||
- `manifest_built`
|
||||
- `signed`
|
||||
- `uploading_blobs`
|
||||
- `uploaded`
|
||||
- `promoting`
|
||||
- `published`
|
||||
- `verifying`
|
||||
- `verified`
|
||||
- `failed`
|
||||
- `rolled_back`
|
||||
|
||||
Each state transition should include:
|
||||
|
||||
- `release_id` if known in ERP
|
||||
- `version`
|
||||
- `started_at`
|
||||
- `finished_at`
|
||||
- `duration_ms`
|
||||
- `step`
|
||||
- `status`
|
||||
- `message`
|
||||
- `log_path` if available
|
||||
|
||||
## CLI command set
|
||||
|
||||
Suggested commands:
|
||||
|
||||
### Release lifecycle
|
||||
|
||||
- `metin-release release init`
|
||||
- create local workspace metadata for a new version
|
||||
- `metin-release release inspect`
|
||||
- inspect source root, file counts, launcher presence, total bytes
|
||||
- `metin-release release build-manifest`
|
||||
- generate canonical `manifest.json`
|
||||
- `metin-release release sign`
|
||||
- sign `manifest.json`
|
||||
- `metin-release release diff-remote`
|
||||
- compare manifest blobs against remote storage
|
||||
- `metin-release release upload-blobs`
|
||||
- upload only missing blobs
|
||||
- `metin-release release upload-manifest-archive`
|
||||
- upload `manifests/<version>.json` and `.sig`
|
||||
- `metin-release release promote`
|
||||
- switch current `manifest.json` and `.sig`
|
||||
- `metin-release release verify-public`
|
||||
- fetch public manifest, signature, and optional blob samples
|
||||
- `metin-release release publish`
|
||||
- composite command executing the full asset publish flow
|
||||
- `metin-release release rollback`
|
||||
- promote a historical manifest back to current
|
||||
|
||||
### ERP sync
|
||||
|
||||
- `metin-release erp create-release`
|
||||
- `metin-release erp update-release`
|
||||
- `metin-release erp append-log`
|
||||
- `metin-release erp mark-status`
|
||||
|
||||
### m2pack integration
|
||||
|
||||
- `metin-release m2pack build`
|
||||
- `metin-release m2pack verify`
|
||||
- `metin-release m2pack diff`
|
||||
- `metin-release m2pack export-runtime-key`
|
||||
|
||||
### Launcher integration
|
||||
|
||||
- `metin-release launcher publish`
|
||||
- separate path because of Windows packaging constraints
|
||||
|
||||
## JSON contract
|
||||
|
||||
Every automation-facing command should support:
|
||||
|
||||
```text
|
||||
--json
|
||||
```
|
||||
|
||||
Success output shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": true,
|
||||
"command": "release publish",
|
||||
"version": "2026.04.14-1",
|
||||
"status": "published",
|
||||
"artifacts": {
|
||||
"manifest_path": "/abs/path/manifest.json",
|
||||
"signature_path": "/abs/path/manifest.json.sig"
|
||||
},
|
||||
"stats": {
|
||||
"file_count": 123,
|
||||
"blob_count": 9,
|
||||
"uploaded_blob_count": 3,
|
||||
"uploaded_bytes": 1048576
|
||||
},
|
||||
"remote": {
|
||||
"manifest_url": "https://updates.jakubkadlec.dev/manifest.json"
|
||||
},
|
||||
"erp": {
|
||||
"release_id": 42
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Failure output shape:
|
||||
|
||||
```json
|
||||
{
|
||||
"ok": false,
|
||||
"command": "release publish",
|
||||
"version": "2026.04.14-1",
|
||||
"status": "failed",
|
||||
"error": {
|
||||
"code": "blob_upload_failed",
|
||||
"message": "Failed to upload one or more blobs"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Exit code rules:
|
||||
|
||||
- `0` success
|
||||
- `1` operator or validation error
|
||||
- `2` remote or network error
|
||||
- `3` signing or integrity error
|
||||
- `4` ERP sync error
|
||||
|
||||
## ERP integration contract
|
||||
|
||||
The ERP module should integrate with the CLI at the orchestration layer only.
|
||||
|
||||
Recommended boundary:
|
||||
|
||||
- ERP creates a draft release record
|
||||
- ERP stores operator intent, notes, target channel, and visibility
|
||||
- ERP triggers the CLI through a worker, SSH command, queue job, or agent
|
||||
- CLI performs release operations
|
||||
- CLI pushes structured status updates back to ERP
|
||||
- ERP renders the timeline, logs, artifacts, and rollback actions
|
||||
|
||||
Recommended ERP-owned data:
|
||||
|
||||
- release version
|
||||
- notes
|
||||
- previous release reference
|
||||
- publish status
|
||||
- operator identity
|
||||
- started/finished timestamps
|
||||
- manifest metadata
|
||||
- remote verification status
|
||||
- launcher publish status
|
||||
- pointers to logs and artifacts
|
||||
|
||||
CLI-owned data:
|
||||
|
||||
- actual manifest generation
|
||||
- signing
|
||||
- file hashing
|
||||
- blob deduplication
|
||||
- upload semantics
|
||||
- runtime-key export
|
||||
- launcher packaging invocation
|
||||
|
||||
## Remote storage contract
|
||||
|
||||
For the current launcher path, the CLI should treat this as canonical:
|
||||
|
||||
- `/var/www/updates.jakubkadlec.dev/files/<hash-prefix>/<sha256>`
|
||||
- `/var/www/updates.jakubkadlec.dev/manifests/<version>.json`
|
||||
- `/var/www/updates.jakubkadlec.dev/manifests/<version>.json.sig`
|
||||
- `/var/www/updates.jakubkadlec.dev/manifest.json`
|
||||
- `/var/www/updates.jakubkadlec.dev/manifest.json.sig`
|
||||
- `/var/www/updates.jakubkadlec.dev/launcher/*`
|
||||
|
||||
Promotion safety rule:
|
||||
|
||||
- upload immutable blobs first
|
||||
- upload archived versioned manifest second
|
||||
- replace current manifest last
|
||||
|
||||
## Secrets and security
|
||||
|
||||
- launcher manifest signing key remains outside ERP
|
||||
- `.m2p` master keys remain outside ERP
|
||||
- CLI reads secrets from:
|
||||
- fixed secure file paths
|
||||
- environment variables
|
||||
- secret manager integration later
|
||||
- CLI must redact secrets from logs and JSON output
|
||||
|
||||
Never return:
|
||||
|
||||
- raw private keys
|
||||
- runtime master keys
|
||||
- decrypted secret material
|
||||
|
||||
## Linux and Wine posture
|
||||
|
||||
Supported on Linux now:
|
||||
|
||||
- client tree scan
|
||||
- manifest build
|
||||
- manifest signing
|
||||
- blob upload and promotion
|
||||
- `.m2p` build and verification
|
||||
- Wine-based smoke validation if needed
|
||||
|
||||
Not fully Linux-native yet:
|
||||
|
||||
- Velopack packaging for win-x64 launcher release
|
||||
|
||||
Implication:
|
||||
|
||||
- asset release commands should be Linux-first
|
||||
- launcher publish should remain an explicit separate command and may require a
|
||||
Windows runner or Windows host until the toolchain changes
|
||||
|
||||
## MCP tool set
|
||||
|
||||
Suggested MCP tools:
|
||||
|
||||
- `release_init`
|
||||
- `release_inspect`
|
||||
- `release_build_manifest`
|
||||
- `release_sign`
|
||||
- `release_diff_remote`
|
||||
- `release_upload_blobs`
|
||||
- `release_promote`
|
||||
- `release_verify_public`
|
||||
- `release_publish`
|
||||
- `release_rollback`
|
||||
- `erp_create_release`
|
||||
- `erp_update_release`
|
||||
- `m2pack_build`
|
||||
- `m2pack_verify`
|
||||
- `m2pack_diff`
|
||||
- `m2pack_export_runtime_key`
|
||||
- `launcher_publish`
|
||||
|
||||
Each tool should document the exact CLI command it runs.
|
||||
|
||||
## Recommended implementation phases
|
||||
|
||||
### Phase 1. Asset release CLI
|
||||
|
||||
Build first:
|
||||
|
||||
- `release inspect`
|
||||
- `release build-manifest`
|
||||
- `release sign`
|
||||
- `release diff-remote`
|
||||
- `release upload-blobs`
|
||||
- `release promote`
|
||||
- `release verify-public`
|
||||
- `release publish`
|
||||
|
||||
This is the minimum path ERP needs for the current launcher contract.
|
||||
|
||||
### Phase 2. ERP sync
|
||||
|
||||
Build second:
|
||||
|
||||
- `erp create-release`
|
||||
- `erp update-release`
|
||||
- CLI status callbacks or polling contract
|
||||
|
||||
This lets the ERP module focus on UI, permissions, and audit trail.
|
||||
|
||||
### Phase 3. MCP wrapper
|
||||
|
||||
Build third:
|
||||
|
||||
- expose the Phase 1 and 2 CLI commands as MCP tools
|
||||
- no new logic
|
||||
|
||||
### Phase 4. m2pack path
|
||||
|
||||
Build fourth:
|
||||
|
||||
- `m2pack build`
|
||||
- `m2pack verify`
|
||||
- `m2pack diff`
|
||||
- `m2pack export-runtime-key`
|
||||
|
||||
Only after the signed-manifest release path is stable.
|
||||
|
||||
### Phase 5. Launcher release path
|
||||
|
||||
Build fifth:
|
||||
|
||||
- `launcher publish`
|
||||
- Windows-capable execution environment
|
||||
- optional ERP annotation
|
||||
|
||||
## Open decisions
|
||||
|
||||
- Whether the CLI should directly push status to ERP or ERP should poll CLI job
|
||||
results
|
||||
- Whether release workspaces are local-only or persisted on a shared release
|
||||
host
|
||||
- Whether `.m2p` artifacts become part of the same release object now or later
|
||||
- Whether launcher release should be represented as:
|
||||
- separate release type
|
||||
- or a child job under the same release
|
||||
|
||||
## Recommendation
|
||||
|
||||
Start with:
|
||||
|
||||
- one Linux-first `metin-release-cli`
|
||||
- one thin `metin-release-mcp`
|
||||
- ERP module consuming only CLI results and statuses
|
||||
|
||||
Do not start by embedding release logic in ERP. That will create a second
|
||||
source of truth and make later `.m2p` and launcher evolution harder.
|
||||
BIN
release-wine/Metin2Launcher-wine.tar.gz
Normal file
BIN
release-wine/Metin2Launcher-wine.tar.gz
Normal file
Binary file not shown.
10
release-wine/Metin2Launcher-wine/README.txt
Normal file
10
release-wine/Metin2Launcher-wine/README.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Metin2Launcher Wine bundle
|
||||
|
||||
Layout:
|
||||
- launcher/ launcher runtime (.exe + DLLs)
|
||||
- client/ final game install dir and .updates/ state
|
||||
|
||||
Run:
|
||||
./start-launcher.sh
|
||||
|
||||
The launcher installs into client/, not into launcher/.
|
||||
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Base.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Base.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Controls.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Controls.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.DesignerSupport.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.DesignerSupport.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Desktop.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Desktop.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Dialogs.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Dialogs.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Fonts.Inter.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Fonts.Inter.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.FreeDesktop.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.FreeDesktop.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Markup.Xaml.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Markup.Xaml.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Markup.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Markup.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Metal.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Metal.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.MicroCom.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.MicroCom.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Native.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Native.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.OpenGL.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.OpenGL.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Remote.Protocol.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Remote.Protocol.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Skia.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Skia.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Themes.Fluent.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Themes.Fluent.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Vulkan.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Vulkan.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Win32.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.Win32.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.X11.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.X11.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Avalonia.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/CommunityToolkit.Mvvm.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/CommunityToolkit.Mvvm.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/HarfBuzzSharp.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/HarfBuzzSharp.dll
Executable file
Binary file not shown.
1305
release-wine/Metin2Launcher-wine/launcher/Metin2Launcher.deps.json
Normal file
1305
release-wine/Metin2Launcher-wine/launcher/Metin2Launcher.deps.json
Normal file
File diff suppressed because it is too large
Load Diff
BIN
release-wine/Metin2Launcher-wine/launcher/Metin2Launcher.dll
Normal file
BIN
release-wine/Metin2Launcher-wine/launcher/Metin2Launcher.dll
Normal file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Metin2Launcher.exe
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Metin2Launcher.exe
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Metin2Launcher.pdb
Normal file
BIN
release-wine/Metin2Launcher-wine/launcher/Metin2Launcher.pdb
Normal file
Binary file not shown.
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"runtimeOptions": {
|
||||
"tfm": "net8.0",
|
||||
"includedFrameworks": [
|
||||
{
|
||||
"name": "Microsoft.NETCore.App",
|
||||
"version": "8.0.22"
|
||||
}
|
||||
],
|
||||
"configProperties": {
|
||||
"MVVMTOOLKIT_ENABLE_INOTIFYPROPERTYCHANGING_SUPPORT": true,
|
||||
"System.Reflection.Metadata.MetadataUpdater.IsSupported": false,
|
||||
"System.Runtime.InteropServices.BuiltInComInterop.IsSupported": true,
|
||||
"System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
release-wine/Metin2Launcher-wine/launcher/MicroCom.Runtime.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/MicroCom.Runtime.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Microsoft.CSharp.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Microsoft.CSharp.dll
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Microsoft.VisualBasic.Core.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Microsoft.VisualBasic.Core.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Microsoft.VisualBasic.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Microsoft.VisualBasic.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Microsoft.Win32.Primitives.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Microsoft.Win32.Primitives.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/Microsoft.Win32.Registry.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/Microsoft.Win32.Registry.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/NSec.Cryptography.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/NSec.Cryptography.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/NuGet.Versioning.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/NuGet.Versioning.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/SkiaSharp.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/SkiaSharp.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.AppContext.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.AppContext.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Buffers.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Buffers.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Collections.Concurrent.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Collections.Concurrent.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Collections.Immutable.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Collections.Immutable.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Collections.NonGeneric.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Collections.NonGeneric.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Collections.Specialized.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Collections.Specialized.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Collections.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Collections.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.ComponentModel.Annotations.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.ComponentModel.Annotations.dll
Executable file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.ComponentModel.Primitives.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.ComponentModel.Primitives.dll
Executable file
Binary file not shown.
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.ComponentModel.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.ComponentModel.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Configuration.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Configuration.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Console.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Console.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Core.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Core.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Data.Common.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Data.Common.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Data.DataSetExtensions.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Data.DataSetExtensions.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Data.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Data.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.Contracts.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.Contracts.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.Debug.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.Debug.dll
Executable file
Binary file not shown.
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.FileVersionInfo.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.FileVersionInfo.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.Process.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.Process.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.StackTrace.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.StackTrace.dll
Executable file
Binary file not shown.
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.Tools.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.Tools.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.TraceSource.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.TraceSource.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.Tracing.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Diagnostics.Tracing.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Drawing.Primitives.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Drawing.Primitives.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Drawing.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Drawing.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Dynamic.Runtime.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Dynamic.Runtime.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Formats.Asn1.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Formats.Asn1.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Formats.Tar.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Formats.Tar.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Globalization.Calendars.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Globalization.Calendars.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Globalization.Extensions.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Globalization.Extensions.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.Globalization.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.Globalization.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Compression.Brotli.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Compression.Brotli.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Compression.FileSystem.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Compression.FileSystem.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Compression.Native.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Compression.Native.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Compression.ZipFile.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Compression.ZipFile.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Compression.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Compression.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.FileSystem.AccessControl.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.FileSystem.AccessControl.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.FileSystem.DriveInfo.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.FileSystem.DriveInfo.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.FileSystem.Primitives.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.FileSystem.Primitives.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.FileSystem.Watcher.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.FileSystem.Watcher.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.FileSystem.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.FileSystem.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.IsolatedStorage.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.IsolatedStorage.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.MemoryMappedFiles.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.MemoryMappedFiles.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Pipelines.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Pipelines.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Pipes.AccessControl.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Pipes.AccessControl.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Pipes.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.Pipes.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.UnmanagedMemoryStream.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.UnmanagedMemoryStream.dll
Executable file
Binary file not shown.
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.dll
Executable file
BIN
release-wine/Metin2Launcher-wine/launcher/System.IO.dll
Executable file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user