はじめに
初めまして、初投稿です。
日本語がおかしなところや読みにくい箇所があるかと思いますがご了承ください。
仕事でPythonを書く日々なのですが、半年ほど前にこのアイデアを思いつきまして。
「PythonでMinecraftサーバーを動かしたい!」
そこでマイクラのサーバーを1からPythonで書き直すプロジェクト、「Project Pyncraft」の開発を始めたのですが、やはりつまずくのは技術的なアーキテクチャがわからない事でしょう。
この記事ではマイクラというゲームの技術的かつ基礎的なコンセプトをまとめておくので、例えばMod/プラグイン開発をしているけどすぐクラッシュしてしまう、といった方向けにピッタリの内容になっていると思います。
一方でかなり技術的かつ抽象的な話になってしまっているので、サーバーを建てたいだけの人や具体的な実装方法を探している人にとってはあまり収穫はないかもしれません。
またここに書いていることはマイクラの根本的な技術的基礎なので、これさえ理解していれば基本的にマイクラに関わる開発で困る事はなくなるはずです。(APIの使い方は各自ドキュメントを読んでもらうとして...)
マイクラは遊んだことだけはあるという方にも、エンジニアとして興味深い内容のはずなので、これを機にMod/プラグイン開発にも興味を持っていただければ幸いです。
技術的な側面から見た「マインクラフト」
マイクラは早期の開発段階で既にマルチプレイが考案されており、その実態はクライアント、サーバーという二つのサイドがお互いにやりとりする「クライアント・サーバーモデル」を土台としています。その為、この二つのサイドの理解が曖昧なままでの開発はいずれ問題を引き起こします。
ここで、Mod開発とプラグイン開発の違いを書いておきます。Modとは基本的にクライアント側(とサーバー側)の改造を指しており、プラグインはサーバー側のみの改造を指しています。
- クライアント側の改造(Forge、Fabric等)はサーバー側とクライアント側両方である
- サーバー側の改造(Spigot、Paper等)はサーバー側のみである
これが基本的な違いです。
クライアントとサーバー二つのサイドに関してはこちらの説明の理解で問題ありません(英語ですが...)。
https://docs.minecraftforge.net/en/latest/concepts/sides/
要約すると、
- 物理クライアント(Physical Client): グラフィカルコンポーネント、つまりプレイヤーが画面で見る直接的な物の描写やサウンドエンジンを担当。マイクラのゲームウィンドウに描写されるものや聞こえるものその物こそがこの物理クライアントです
- 論理クライアント(Logical Client): PCからのキーボードやマウス入力から、その動きをワールドに干渉させるためのパケットを論理サーバーとやりとりします。また、論理サーバーから受け取ったワールド情報を物理クライアントに送りそれらを描写させます
- 物理サーバー(Physical Server): マルチプレイでサーバーjarを開くと現れるGUIがこの物理サーバーです。シングルプレイではほぼ関係ありません。この記事では物理サーバーの事を「専用サーバー(Dedicated Server)」(マルチプレイ専用の物理サーバーの意)と呼ぶことにします
- 論理サーバー(Logical Server): ゲームロジックの全て(Mob AI, 天候, 地形情報のアップデート, ワールド生成等々)を担当します。論理クライアントと、プレイヤーやワールド情報をやりとりします
論理クライアントと論理サーバーは別々に処理が実行されており、シングル、マルチプレイ問わずパケットを用いてやり取りが行われています。パケットはマイクラで起こっている全ての情報をやりとり可能ですが、Forge API等のMod開発ではこれらのパケットI/Oによるローレベルのイベントハンドルではなく、イベントバスとして分かりやすく定義されているので、直感的に使えるようになっています。
Mod開発では、サーバーとクライアント両方を改造できるので、自由度は上がります。しかし、サイドの概念を理解していないと、ある時点でこの二つのサイドを混合させてしまう事が起こるでしょう。Forge APIはそれぞれのサイドでのみ動くことを想定したメソッドがいくつもあります。なので、無作為にクライアント側でサーバー側専用のメソッドを使ってしまっている、若しくはイベントバスやパケットを経由せずにサーバー側の情報を読み書きした場合、スレッド同士で非同期が起こり、バグやクラッシュを引き起こします。
一方、Spigot等を使ったプラグインの開発ではコードはサーバー側のみで動いているのでこれらに気を使う事はありませんが、クライアント側の改造が必要になる内容は追加することができません。
このようにマイクラのMod/プラグイン開発はこの二つのサイドを知る事は必須になります。
マルチプレイとシングルプレイの違いとは
マルチプレイとはハイレベル視点から説明すると、クライアント側が「物理+論理クライアント」のみを動かしており、マイクラのワールドで起こるあらゆる干渉は全て専用の物理サーバー(Dedicated Server)に委ねている状態です。
一方シングルプレイの場合、クライアントは「物理、論理クライアント」に加えて「論理サーバー」を動かしています。マイクラにおけるシングル、マルチプレイの違いとは、この論理サーバーをクライアントで動かしているか、専用サーバーで動かしているかの違いなのです。
この「専用サーバー」とは具体的には"net.minecraft.server"、通称NMSと呼ばれているサーバー側のコードを独立して動かすための.jarの事です。
サーバーを建てたことのある方ならわかると思いますが、いわゆる"server.jar"がこのNSM単体の事で、コンセプト上ではサーバー・クライアントモデルからサーバーのみを独立して動かすことで一つのサーバーに多数のクライアントが接続できるようになっています。また、シングルプレイでもこのモデルの恩恵を受けており、「LANに公開」の機能はクライアント内で論理サーバーを外部に公開することによって物理的なサーバーを建てずともワールドがホストできる仕組みなのです。
具体的にそれぞれのサイドで何ができるのか
基本的に、バニラマイクラ(Mod等何も入れていない状態のマイクラ)に既にある何かを何れかの形で改造することは、サーバー側のみで可能です。
ゾンビのAIをエンダーマンのAIと取り替える、マイクラにある「木の棒」の内部データ(NBT)を改変して魔法の杖を作る、この杖を使って村を吹き飛ばすようなワールド干渉をする等。
一方で、新しいエモートを追加する、銃Modや線路等カスタムモデルを持ったアイテムやブロック、エンティティを追加する、新しいディメンション(ネザーやエンドに変わる新しい世界)を追加するといったバニラに存在しない物を追加するならクライアント側の改造(つまりMod開発)が必要になります。
例えば、新しいMobを追加したいとします。
このMobは専用の3Dモデルとテクスチャを持っており、その動きやAIもまるで異なるものとします。
先述した通り、これはバニラに存在しないテクスチャとモデルを追加しようとしているので、サーバー側だけでは不可能です。
カスタム3Dモデルとテクスチャ、具体的なモデルの動き方とその専用パケットを登録するためのレジストリはクライアント側の管轄であるため、仮にバニラの専用サーバーがこれらのパケットを受け取ったとしてもサーバーは理解することができません。(クラッシュまではしないと思いますがコードの書き方によってはバグやクラッシュにつながるかも)なので、これをマルチに持って行くなら、これらのパケットが登録された専用サーバー、Forge ModであればForgeサーバーを建てる必要があります。この場合、サーバーとクライアント両方がModを入れている必要があります。
一方で、Mobのスポーン方法やAIはサーバー側なので、バニラのmob(ゾンビ等)のモデルとテクスチャを使い回して全く新しいMobを作ることは可能です。例えば、日光に晒されても燃えないゾンビや、友好的なゾンビ等。
さらにこれを応用すると、プレイヤーをAI Mobとしてスポーンさせることができます。この場合は、プレイヤーがカスタムスキンを使って見た目を変えるのと同じようにカスタムテクスチャを用いてのMob作成が技術上は可能です。
プラグインはサーバー側のみで動くので、クライアントは何らかのModを入れる必要はありません。
ところで、プロジェクトPyncraftとはなんですか?
Pyncraft(読み:パインクラフト)はマイクラの「物理+論理サーバー」の開発。つまり、"server.jar"の一からの開発になります。具体的には、
- 多数接続を受け付ける玄関口、「サーバーソケット」と、独立した接続を管理する為のマルチスレッディングの確立
- TCP経由でのパケットプロトコルの定義
- コンソールからのコマンド入力を受け付ける
- マイクラのワールドそのものの維持とプレイヤー同士の干渉を司る「tick loop」の確立
- Tickで起こるあらゆる現象(Mobの移動、天候、レッドストーン、地形情報の処理、ゲーム内時間等)をPythonで書き直す
- ワールド生成アルゴリズムを書き直す
といったところでしょうか。
プロジェクト自体のゴールとしては:
- マイクラ(NMS)のコードをより簡潔に理解できるプロジェクトにする
- サーバー側のMod開発、また論理サーバーそのものの改造ができるようなコードベースを構築する
- カスタムワールド生成や全く新しい動きをするMob AIなどサーバー側が提供できる範囲での試行ができるようなAPIを提供する
この三つが主旨になります。
まとめ
- マイクラは「クライアント・サーバーモデル」が基礎である
- Mod/プラグイン開発をする上で、そのアイデアが果たして技術的に可能なのか、具体的にどのようにして実装するかはこの基礎モデルに帰する
- バニラマイクラで存在するものだけを用いた粘土遊びはサーバー側(プラグイン開発)、全く新しいアイテムやブロック等の追加はクライアント側(Mod開発)で行う
- Pyncraftは専用サーバー(NMS)を1からPythonで書き直そうとするプロジェクトである