開国2日目、DebtCraftのDiscordに「入国審査で登録できない」と連絡が来た。統合版(スマホ)の参加者で、ゲーマータグに空白が入っている人だった。
DebtCraftのサバイバルはホワイトリスト制で、登録はDiscordのボットがやっている(前の記事)。統合版の人は、ボットがRCONで Floodgate の fwhitelist add 名前 を送って登録する。
1つ目の思い込み:空白のせい?
ボットは、ゲーマータグの空白を _ に変えて fwhitelist add Abc_def1234 のように送っていた。ゲーム内では統合版の名前の空白が _ になるので、それに合わせていた。
これだと Xbox の本当の名前と違うから見つからないのでは、と考えて、"Abc def1234" のように " で囲んで送るように直した。でも、通らなかった。
本当の原因:Floodgate がその人を知らない
サバイバルのログを見ると、こう出ていた。
[floodgate] Got an error from requesting the xuid of a Bedrock player:
Unable to find user in our cache. Please try specifying their Floodgate UUID instead
fwhitelist add 名前 は、名前から Xbox の ID(XUID)を GeyserMC の共有キャッシュで探す。このキャッシュには、どこかの Geyser サーバーに最近入ったことがある人しか載っていない。一度もサーバーに入っていない人は、名前では登録できない。
エラーにあるとおり、Floodgate の UUID を指定すれば登録できる。統合版の人の UUID は 00000000-0000-0000-0009-xxxxxxxxxxxx の形で、XUID から決まる。
2つ目の問題:ロビーに入るとキックされる
なので「一度ロビーに入ってもらえば UUID が分かる」と思ったら、本人から「ロビーからキックされた」と言われた。
.Abc_def1234 was kicked for floating too long!
lost connection: Flying is not enabled on this server
ロビーのスポーン地点が空中にあって、統合版は地形の読み込みが遅いので、着地する前に「8秒浮いている=飛行」と判定されてキックされていた。Java版の人は普通に落ちて着地できるので、気づいていなかった。
ロビーはアドベンチャーモードで飛べないので、ALLOW_FLIGHT: "TRUE" にして飛行キックを止め、スポーン地点も床の上に直した。
3つ目の問題:UUIDがどこにも書かれていない
ロビーに入ってもらえば、UUID はロビーの usercache.json に残るはず……と思ったら、残っていなかった。Paper はこのファイルをすぐには書き込まないらしい。
ただ、ログにははっきり出ている。
UUID of player .Abc_def1234 is 00000000-0000-0000-0009-01fd8c51c619
ボットにロビーのフォルダを読み取り専用で渡して、logs/latest.log と過去のログ(.log.gz)からこの行を探すようにした。
ちなみに、ロビーのコンテナを作り直すと docker logs の中身は消える。最初に手動で探したときは docker logs を grep していて見つからず、ファイルの方から探して見つかった。
4つ目の問題:登録できているのに「失敗」
UUID で fwhitelist add すると登録はできた。それなのに、ボットは「登録できませんでした」と返していた。
whitelist list を見て分かった。
There are 12 whitelisted player(s): ch1w4, ..., unknown, unknown, ...
UUID で登録すると、名前が unknown で載る。ボットは「ホワイトリストに .名前 があるか」で成功を確かめていたので、見つけられずに失敗と判断していた。
サバイバルの whitelist.json も読み取り専用で渡して、UUID があるかで確かめるように直した。名前が unknown でも、ホワイトリストの判定は UUID でされるので、入るのには問題ない。
今の流れ
統合版の人は、次の手順で登録できるようになった。
- 一度ロビーに入る(登録しなくても入れる)
- Discord の入国審査で「統合版で登録」を押して、ゲーマータグを入力
- ボットがロビーのログから UUID を見つけて
fwhitelist add <UUID>し、whitelist.jsonで確認して、Discord と結びつける
それでもだめなとき用に、ロビーのログから UUID を探して登録するシェルスクリプトも置いてある。
学んだこと
- 統合版は「名前」より「UUID」で扱った方が確実
- 成功したかは、コマンドの返事ではなく、結果のファイルで確かめる(Floodgate の返事は非同期で RCON には返ってこない)
- Java版だけでテストしていると、統合版の問題に気づけない
参加してくれた人には何度も試してもらって、申し訳なかった。でも、おかげで次からの統合版の人はスムーズに入れるはず。