Steam のゲームの中には Windows 用の専用サーバーしか用意されていないものがあります。depot に Linux バイナリがないので、いつものアドバイスは「Windows マシンで動かせ」です。その必要はありません。Wine を使えば、Windows サーバーを普通の Linux マシンで動かすことができ、Steam に接続して実際のプレイヤーを受け入れます。これは、例として Alien Swarm: Reactive Drop(無料の co-op Source ゲーム)を使って私たちが実際にうまくいったレシピそのものです。同じアプローチは Windows 専用の他の Source 専用サーバーでも通用するはずです。
まず、本当に Linux サーバーが存在しないかを確認する
決めつけないでください。Wine に頼る前に Steam に直接尋ねましょう。steamcmd をそのアプリに向けて、プラットフォームの一覧を読みます:
steamcmd +login anonymous +app_info_print <appid> +quit \
| grep -iE "oslist|name"サーバーの専用サーバーアプリが「oslist windows」だけなら、頼れるネイティブ Linux ビルドはありません。Linux インストールを強制してみることもできます。本当に Linux depot がないときは、その場で失敗します:
steamcmd +@sSteamCmdForcePlatformType linux \
+login anonymous +app_update <appid> validate +quit
# ERROR! Failed to install app '<appid>' (Missing configuration)このエラーと、ELF ファイルが 1 つもダウンロードされないことが、それを裏付けます。ここからは Wine が道です。サーバーと app 1007(Steamworks Common Redistributables)を同じフォルダに、プラットフォームタイプ windows でインストールします。app 1007 はサーバーが必要とする Steam の DLL をもたらします。その理由はステップ 2 でわかります:
steamcmd +@sSteamCmdForcePlatformType windows +login anonymous \
+force_install_dir /path/to/server \
+app_update <appid> validate \
+app_update 1007 validate \
+quitWine での素朴な試みが失敗する理由
サーバーを Wine から直接動かすと、続けざまに 2 つの壁にぶつかります:
- コンソールがない: サーバーは本物の端末を期待します。/dev/null からリダイレクトすると CTextConsoleWin32::GetLine: !GetNumberOfConsoleInputEvents が出て、起動しません。
- Steam ライブラリを読み込めませんでした: 起動したあとでも「Unable to load Steam support library」と表示され、Steam に登録されないので、誰も見つけられず入れません。
どちらにも直し方があります。ここに完全なレシピを示します。
ステップ 1: 本物の端末(PTY)を与える
ヘッドレスのマシンには端末がなく、Windows のコンソールサーバーは端末なしでは動くのを拒否します。起動をスクリプトで包んで疑似端末を割り当て、偽のディスプレイ用に Xvfb を使います:
Xvfb :99 -screen 0 1024x768x24 &
export DISPLAY=:99 WINEPREFIX=/wine
script -qfc "wine srcds_console.exe -console -condebug \
-game <gamedir> +map <map> -port 27015" /tmp/server.logこれだけでサーバーはマップを読み込んでゲームポートをバインドします。ですが、まだ Steam と話すことができません。
ステップ 2: 2 つの Steam DLL、2 つの異なる入手元
Source エンジンは steamclient.dll と steam.dll の両方をサーバーの exe の隣に必要とします。そしてここに、デバッグを丸 1 周分よけいに費やす羽目になった罠があります: それらは異なる場所から来ていて、app 1007 はそのうち片方しか渡してくれません。
- steamclient.dll: はステップ 1 でインストールした app 1007(Steamworks Common Redistributables)から来ます。正規で、互換性のあるバージョンで、Valve がメンテナンスしています。
- steam.dll: は app 1007 に含まれていません。これは Steam クライアントの一部で、それをきれいに入手する唯一の方法は、Windows 版の steamcmd.exe を Wine の下で一度実行することです。すると自動更新され、steam.dll(と steamclient.dll)を自身のフォルダに置きます。
そこで steamcmd.exe を Wine の下で実行して steam.dll をブートストラップし、そのあと 2 つの DLL をサーバーの exe の隣にコピーします:
# steam.dll: run Windows steamcmd once under Wine (needs Xvfb for a display)
cd "$WINEPREFIX/drive_c/steamcmd"
curl -fsSLO https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip
unzip -o steamcmd.zip
DISPLAY=:99 wine steamcmd.exe +quit # lays down steam.dll + steamclient.dll
# place both next to the server exe
cd /path/to/server
cp "$WINEPREFIX/drive_c/steamcmd/steam.dll" .
[ -f steamclient.dll ] || cp "$WINEPREFIX/drive_c/steamcmd/steamclient.dll" .ステップ 3: なぜ steam.dll が肝心の部品なのか
これはほとんど誰も書き留めていない部分です。エラーには「Unable to load Steam support library」と出ますが、そこで言及されているサポートライブラリは steamclient.dll ではなく steam.dll です。Source エンジンは Steam のチェーン全体をブートストラップするために、実行ファイルの隣に steam.dll を探します。steamclient.dll だけがある状態(app 1007 が渡してくれるのはそれだけ)ではまだ失敗します。steam.dll が .exe の隣に置かれた瞬間、ログは失敗から成功へと変わります:
Connection to Steam servers successful.
VAC secure mode is activated.VAC はサーバーが正しくログインしたゲームサーバーでない限り有効になりません。なので、この行はサーバーが登録されたことの証拠です。ほとんどの Source サーバーはここで匿名でログインし、Game Server Login Token(GSLT)は必要ありません。一部のゲーム(CS2 など)だけが必要とします。
罠: A2S が沈黙するがサーバーは正常
ここで私たちが最も時間を取られ、あやうく諦めかけた理由となる部分です。Wine の下ではサーバーは A2S_INFO に応答しません。これはツールがサーバーの名前、マップ、プレイヤー数を読むために使う UDP クエリです。問い合わせると、どのポートも、同じマシンからでもタイムアウトします。A2S をヘルスチェックに使っていると、サーバーは完全に死んでいるように見えます。
死んではいません。Wine の下で A2S が沈黙しても、実際のプレイヤーが入るのを妨げることはありません。ゲーム内のサーバーブラウザは Steam のマスターリスト(サーバー自身が送信します)からサーバーを一覧表示し、ダイレクト接続は A2S ではなくゲームのプロトコルを使います。だから本当のテストはクエリが応答することではなく、クライアントが接続することです。実際に試してみたところ、本物のプレイヤーが一発で接続してプレイできました:
Client "player" connected (10.0.0.5:27005).
1/ 8 on map <mapname>実践的な教訓: Wine でホストしたサーバーでは、A2S でヘルスチェックをしないこと。ログの「VAC secure mode is activated」の行、プレイヤー数の行、あるいはゲームの UDP ポートがバインドされているかどうかの単純な確認など、実際に生きているかどうかを反映するものをチェックしましょう。
これはすべての Windows ゲームで通用する?
スコープには正直になりましょう。私たちはこれを Source エンジンのサーバーで実証しましたが、同じレシピ(PTY、steamcmd でビルドしたランタイム、exe の隣の steam.dll)は Windows 専用の他の Source 専用サーバーでも通用するはずです。他のエンジンのゲームは Steam の統合の仕方が異なるので、別々の実験として扱ってください。どのみち予想すべきことが 2 つあります。ブートはネイティブ Linux より遅くなること(Wine に steamcmd のステップと Steam ログインが加わるため)、そして上記の A2S 沈黙の挙動はおそらくすべてに当てはまること。
あるいは全部すっ飛ばす
これは午後をまるごと食いつぶすたぐいの面倒ごとです。サーバーさえあればいいなら、Linux フリートと Wine まわりの配管は私たちが引き受けます。時間単位で、最初の 1 分からパブリック IP 付きです。私たちが2hours.gg でホストしているものをご覧ください。