LinuxでGameServerQueryする

GameDigでdebugするよ

具体的にgame serverにqueryするための準備です。gslistでもQuery可能ですが、gamedigのデバッグモードでより詳細で具体的なプロトコルが分かりますので、その手順と情報を示します。game serverのプロトコルはほぼonline gameの数に匹敵するくらいありますので、制作中のBattlefield2142関連に限定した話です。

普通gamer serverへのqueryはUDPパケットで始めますが、Battlefield2142の場合、

というのがすぐに見つかりますが、正確さは50%です。(100%でなければ0%と一緒という説がありますね。が、手順は基本的に正しいです。)

そこで適切なプログラムを探していましたが、

これが使えそうです。うたい文句は上記githubに記載があるように、

node-GameDig is a game server query Node.js module (as well as a command line executable), capable of querying for the status of nearly any game or voice server.

であり、Node.jsモジュールなので、npm経由でインストールして使うものですが、今回はチラッと書いてあるコマンドラインプログラムの方をデバッグモードで使います。まずはinstallですが、

apt install nodejs npm

の後、

npm install gamedig -g

使い方は、exampleにあるように

gamedig --type minecraft mc.example.com:11234

等として使います。今回は、bf2142のプロトコルですから、IPアドレスが54.36.176.221のサーバのポート29900へQueryするのであれば、

gamedig --debug --type battlefield2142 54.36.176.221:29900

と起動します。結果は、

nao@debian-g:~$ gamedig --debug --type battlefield2142 54.36.176.221:29900
Q#0 Starting
Q#0 Protocol: gamespy3
Q#0 Options: {
  socketTimeout: 2000,
  attemptTimeout: 10000,
  maxRetries: 1,
  stripColors: true,
  portCache: true,
  noBreadthOrder: false,
  ipFamily: 0,
  requestPlayers: true,
  port: 29900,
  protocol: 'gamespy3',
  pretty: false,
  debug: true,
  givenPortOnly: false,
  requestRules: false,
  requestRulesRequired: false,
  requestPlayersRequired: false,
  checkOldIDs: false,
  rejectUnauthorized: false,
  type: 'battlefield2142',
  host: '54.36.176.221'
}
Q#0 DNS Lookup: 54.36.176.221
Q#0 Raw IP Address: 54.36.176.221
54.36.176.221:29900 UDP(55070)-->
Buffer length: 11 bytes
fe fd 09 00 00 00 01 00 00 00 00


54.36.176.221:29900 <--UDP(55070)
Buffer length: 7 bytes
09 00 00 00 01 30 00
               0

Q#0 Registered RTT: 324ms
Q#0 UDP send finished by callback
Q#0 Received challenge key: 0
54.36.176.221:29900 UDP(55070)-->
Buffer length: 11 bytes
fe fd 00 00 00 00 01 ff ff ff 01


54.36.176.221:29900 <--UDP(55070)
Buffer length: 1218 bytes
00 00 00 00 01 73 70 6c 69 74 6e 75 6d 00 80 00 68 6f 73 74 6e
               s  p  l  i  t  n  u  m           h  o  s  t  n
61 6d 65 00 42 46 32 31 34 32 20 52 65 63 6c 61 6d 61 74 69 6f
a  m  e     B  F  2  1  4  2     R  e  c  l  a  m  a  t  i  o
6e 20 4e 4c 20 28 4b 6e 69 66 65 20 53 65 72 76 65 72 29 00 67
n     N  L     (  K  n  i  f  e     S  e  r  v  e  r  )     g
61 6d 65 6e 61 6d 65 00 73 74 65 6c 6c 61 00 67 61 6d 65 76 65
a  m  e  n  a  m  e     s  t  e  l  l  a     g  a  m  e  v  e
72 00 31 2e 31 30 2e 31 31 32 2e 30 00 6d 61 70 6e 61 6d 65 00
r     1  .  1  0  .  1  1  2  .  0     m  a  p  n  a  m  e
43 61 6d 70 5f 47 69 62 72 61 6c 74 61 72 00 67 61 6d 65 74 79
C  a  m  p  _  G  i  b  r  a  l  t  a  r     g  a  m  e  t  y
70 65 00 67 70 6d 5f 6e 76 00 67 61 6d 65 76 61 72 69 61 6e 74
p  e     g  p  m  _  n  v     g  a  m  e  v  a  r  i  a  n  t
00 62 66 32 31 34 32 00 6e 75 6d 70 6c 61 79 65 72 73 00 30 00
   b  f  2  1  4  2     n  u  m  p  l  a  y  e  r  s     0
6d 61 78 70 6c 61 79 65 72 73 00 36 34 00 67 61 6d 65 6d 6f 64
m  a  x  p  l  a  y  e  r  s     6  4     g  a  m  e  m  o  d
65 00 6f 70 65 6e 70 6c 61 79 69 6e 67 00 70 61 73 73 77 6f 72

途中を省略して、最後はご丁寧にgamedigがJSONで返してきます。

Q#0 Query was successful
{
  "name": "BF2142 Reclamation NL (Knife Server)",
  "map": "Camp_Gibraltar",
  "password": false,
  "raw": {
    "playerTeamInfo": {
      "": [],
      "t": [
        {
          "team": "Pac",
          "score": "0"
        },
        {
          "team": "EU",
          "score": "0"
        }
      ]
    },
    "hostname": "BF2142 Reclamation NL (Knife Server)",
    "gamename": "stella",
    "gamever": "1.10.112.0",
    "mapname": "Camp_Gibraltar",
    "gametype": "gpm_nv",
    "gamevariant": "bf2142",
    "numplayers": "0",
    "maxplayers": "64",
    "gamemode": "openplaying",
    "password": "0",
    "timelimit": "0",
    "roundtime": "1",
    "hostport": "17567",
    "bf2142_ranked": "0",
    "bf2142_anticheat": "0",
    "bf2142_autorec": "0",
    "bf2142_d_idx": "http://",
    "bf2142_d_dl": "http://",
    "bf2142_voip": "1",
    "bf2142_autobalanced": "1",
    "bf2142_friendlyfire": "1",
    "bf2142_tkmode": "Punish",
    "bf2142_startdelay": "15",
    "bf2142_spawntime": "15.000000",
    "bf2142_sponsortext": "http://battlefield2142.co",
    "bf2142_sponsorlogo_url": "http://bf2142.ddns.net/BF2142banners/Reclamation_EU_Banner_2025.png",
    "bf2142_communitylogo_url": "http://bf2142.ddns.net/BF2142banners/Reclamation_EU_Banner_2025.png",
    "bf2142_scorelimit": "0",
    "bf2142_ticketratio": "100",
    "bf2142_teamratio": "100.000000",
    "bf2142_team1": "Pac",
    "bf2142_team2": "EU",
    "bf2142_pure": "1",
    "bf2142_mapsize": "16",
    "bf2142_globalunlocks": "1",
    "bf2142_reservedslots": "0",
    "bf2142_maxrank": "0",
    "bf2142_provider": "",
    "bf2142_region": "",
    "bf2142_type": "0",
    "bf2142_averageping": "0",
    "bf2142_ranked_tournament": "0",
    "bf2142_allow_spectators": "0",
    "bf2142_custom_map_url": "1http://bfeditor.org/index.php?lang=English&sec=maps&act=vmap&game=bf2142&map="
  },
  "version": "1.10.112.0",
  "maxplayers": 64,
  "numplayers": 0,
  "players": [],
  "bots": [],
  "queryPort": 29900,
  "connect": "54.36.176.221:17567",
  "ping": 324
}

プロトコルは、まずUDPパケットでgame server 54.36.176.221のポート29900へ11バイト、

fe fd 09 00 00 00 01 00 00 00 00

を送ります。返されてきた7バイト、

09 00 00 00 01 30 00

を受け取ります。ここまでがchallenge/responseフェーズで、本当はresponseに対してなんらかの計算をした結果を次に使うのですが、どうも手抜きでコンスタントです。が、手順は守らなくてはいけないわけです。最後にQueryのパケット11バイト、

fe fd 00 00 00 00 01 ff ff ff 01

を送ると、サーバの今の情報が得られるというわけです。マスターサーバーが把握しているサーバ群は、gslistで得ておきます。(既報)

./gslist -n stella

でしたね。

54.36.176.221:29900 <--UDP(55070)
Buffer length: 1218 bytes
00 00 00 00 01 73 70 6c 69 74 6e 75 6d 00 80 00 68 6f 73 74 6e
               s  p  l  i  t  n  u  m           h  o  s  t  n
61 6d 65 00 42 46 32 31 34 32 20 52 65 63 6c 61 6d 61 74 69 6f
a  m  e     B  F  2  1  4  2     R  e  c  l  a  m  a  t  i  o
6e 20 4e 4c 20 28 4b 6e 69 66 65 20 53 65 72 76 65 72 29 00 67
n     N  L     (  K  n  i  f  e     S  e  r  v  e  r  )     g
61 6d 65 6e 61 6d 65 00 73 74 65 6c 6c 61 00 67 61 6d 65 76 65
a  m  e  n  a  m  e     s  t  e  l  l  a     g  a  m  e  v  e
72 00 31 2e 31 30 2e 31 31 32 2e 30 00 6d 61 70 6e 61 6d 65 00
r     1  .  1  0  .  1  1  2  .  0     m  a  p  n  a  m  e
43 61 6d 70 5f 47 69 62 72 61 6c 74 61 72 00 67 61 6d 65 74 79
C  a  m  p  _  G  i  b  r  a  l  t  a  r     g  a  m  e  t  y
70 65 00 67 70 6d 5f 6e 76 00 67 61 6d 65 76 61 72 69 61 6e 74
p  e     g  p  m  _  n  v     g  a  m  e  v  a  r  i  a  n  t
00 62 66 32 31 34 32 00 6e 75 6d 70 6c 61 79 65 72 73 00 30 00
   b  f  2  1  4  2     n  u  m  p  l  a  y  e  r  s     0
6d 61 78 70 6c 61 79 65 72 73 00 36 34 00 67 61 6d 65 6d 6f 64
m  a  x  p  l  a  y  e  r  s     6  4     g  a  m  e  m  o  d
65 00 6f 70 65 6e 70 6c 61 79 69 6e 67 00 70 61 73 73 77 6f 72
以下略

等々から必要な情報を取り出すのは自分でやらないといけないわけですが、それは”次号”で。

コメント