東方 STG に対戦プラットフォーム TH-Platform を作る
TH-Platform は東方弾幕 STG 向けのサードパーティ製デスクトップクライアントで、TH06、TH07、TH08、TH09 にロビー・マッチング・ルームといった対戦機能を被せるものだ。公式は対戦をやらないので、自分で埋めた穴になる。
対戦は二つに分かれる。片方は人をどう集めるか、もう片方はゲームプロセス内で両者の状態をどう同期するか。後者は汚れ仕事で、DLL を注入し、ゲームロジックを hook し、さらに原版 exe のメモリレイアウトと格闘する必要がある。これは伴走リポジトリ TH08-Platform に分けて地道に潰していく。このリポジトリは前者だけを扱う。クライアント本体、つまりロビー・ルーム・グループ・DM・プロフィール・設定という一式のページだ。UI と逆向を絡めるとしんどいので、切り分けてそれぞれ進める方がすっきりする。
フロントは Vite 6 + React 18 + TypeScript、スタイルは Tailwind、コンポーネントは Radix primitive、アイコンは lucide、外側は Tauri 2 のネイティブシェルで包む。狙いはボーダーレスで 1440x900 固定のデスクトップウィンドウであって、ブラウザのアレではない。ルーティングはライブラリを入れず、自前で hash router を書いた。#/lobby/th08、#/room/4912 みたいなので十分だし、ブラウザの進む・戻るもタダで使えて依存ゼロだ。バックエンドはまだないので、データ層はまず mock で作る。肝は types.ts という型の契約で、mock と本物のファサードが同じ型を共有する。本物のバックエンドを繋いだとき呼び出し側は一行も変えず、mock を差し替えるだけで済む。テーマはデフォルトでダークの三段階、localStorage の th-platform-theme に保存し、index.html にプリレンダースクリプトを仕込んで、入った瞬間に白く光ってから黒に変わるのを防いでいる。
一番硬いのは Windows 専用のゲームローダーで、Tauri 側の Rust で書き、launch_game / terminate_game として公開する。昔ながらの注入の流れだ。対象プロセスをサスペンド状態で起動し、伴走 DLL を注入し、CreateRemoteThread に LoadLibraryA を組み合わせ、それから実行を再開する。対戦パラメータはコマンドラインではなく、環境変数で子プロセスに渡す。
| 変数 | 役割 |
|---|---|
TH08_PLATFORM_PEER |
対向アドレス ip:port |
TH08_PLATFORM_HOST |
自分側がホストであることを示す |
TH08_PLATFORM_LISTEN |
待ち受けポート。ホストはデフォルト 7480、対向は 7481 |
TH08_PLATFORM_DISABLE_MULTIPLAYER |
対戦挙動の総合スイッチ |
TS 側では src/lib/tauri/loader.ts が launchGame を包み、ゲームパス・DLL パス・host モードを組み立てて Rust に投げる。これは Tauri シェルの中でしか生きない。素の pnpm dev で走らせると window.__TAURI__ が存在せず即座に例外を投げる。意図的で、開発時に誤って触ってしまわないようにするためだ。
いまの v0.1.0 はまだ進行中で、本質的には UI の足場に mock データを足したものだ。本物のバックエンドは繋いでおらず、Rust ローダーは組んであるが Windows しか認識しない。次はテーマプリセット、チャンネル、完全なプロフィールといったページを補い、Tauri のパッケージングをきれいに整え、それから mock を本物のバックエンドに繋いで、TH08-Platform 側の DLL インジェクターと本当に串刺しにしていく。