« ^ »

インターネットの片隅に秘密基地を作る

所要時間: 約 15分

TL;DR

  • 秘密基地と称してマイクラのようなゲームMinetestのサーバを構築した。
  • 知人数人を集めてプライベートな遊び場とし、毎日定時に集まって開発している。
  • Minetest楽しい。


https://res.cloudinary.com/symdon/image/upload/v1660175863/blog.symdon.info/1650178576/minetest-banner_nrhu0m.png

「秘密基地」それは、大なり小なり誰しもが幼少期や10代の頃に一度は構築を試みる、選ばれた人達だけの秘密の場所だ。いい大人となった今でも、僕はこの言葉に少しだけ心を動かされる。現実の中の生活は、厳しい事情や苦しい状況ばかりで嫌になる。だからこそ、それらを忘れさせてくれるような秘密の場所が必要だ。そんな環境を求めて、今回はインターネットの片隅に秘密基地を作ろうと思う。

秘密基地といっても要はただのお遊びだ。しかし「遊びに没頭して時間を無駄にしたな」とは思いたくない。貴重な時間を投じるのだから、気が付かないうちに実益を得たい。英語の勉強はしたくないが、世界中の人とは話ができるようになっていたい。そんな事をぼんやり考えていた。つまり勉強するのではなく、問題を解決していった結果、知らず知らずのうちに実力が付いていたという状況が欲しい。

そう考えると適度に遊べて適度に面倒をみないといけないものが丁度良いように思えた。例えばマイクラサーバーのような。マイクラはサーバーを自分でホスティングできる。だから、遊びつつも日々発生する問題を対処する事で実力をつける事ができるだろう。ただ、もう少し自由にいろいろいじれるものがないかと探してみたところ、minetestというOSSのマイクラクローンを見つけた。そこでminetestを使って秘密基地を構築していくことにした。

Minetestとは

Minetestはオープンソースのボクセルゲームである1。ボクセルゲームという言葉はあまり聞かないが、要はMinecraftみたいなゲームのことだ。ゲーム内では地面を掘って素材を採取し、素材を掛け合せて道具やアイテムを作る。ゴールというような概念は特になく、プレイヤーが思い思いの行動をして、世界を構築していく。そういった自由さにとても魅力を感じる。またModと呼ばれる拡張機能を実装したり、サーバープログラム、クライアントプログラムも改変できる。それはminetestのソースコードが公開されていて GNU LGPL でライセンスされているため、改変や再配布が許可されているからだ。ソースコード以外のリソースや、依存ライブラリなどは、また別のライセンスが適応されているが、全体的に自由に改変や再配布可能なライセンスが採用されている。ゲームのほぼ全てを自分で改造できるようになっている。これはとても魅力的だ。

https://github.com/minetest/minetest

インストール又はソースコードからビルドする

minetestのインストール方法はいくつかある。今回はmacOSに直接インストールする。macOSの場合、HomebrewのFormulaが用意されているので、それを使用するのが最も手っ取り早い。

brew install minetest
Homebrewでインストールする

ただ、私がインストールした時のものは、起動すると画面サイズがおかしな状態になることがわかった2。Github上のPull requestを確認すると、既に修正されmasterブランチにマージされていた。

https://github.com/minetest/minetest/issues/10654

そこでGithubからソースコードを取得し、直接ビルドする事にした。minetestのビルド方法については基本的にREADMEに記載がある。基本的には、その手順に従うことでビルドは可能だ。もし、ビルドに失敗しているなら、大抵の場合は次のいずれかをチェックしよう。

  • 必要なライブラリをインストールし、適切に環境変数を設定しているか?

    特に以下のパッケージがインストールされているか確認しよう。

    • cmake
    • curl
    • freetype
    • gettext
    • libjpeg
    • libogg
    • libpng
    • libvorbis
    • luajit
  • submoduleとなっているソースコードのバージョンは期待されているものと一致しているか? cmakeを実行する時に xxx x.x.x is required といった趣旨のエラーが表示される場合は、サブモジュールを確認したほうがよい。特に lib/irrlichtmt に展開されている Irrlicht のバージョンの食い違いでビルドに失敗する問題はしばしば遭遇した。

まず依存パッケージをインストールする。ここでは例としてHomebrewを用いてインストールする。

brew install cmake curl freetype gettext libjpeg libogg libpng libvorbis luajit
依存パッケージをインストールする

次にソースコードを取得する。Gitリポジトリにはサブモジュールが登録されている。そのため、サブモジュールも合せて取得するように --recurse-submodules を指定する。サブモジュールを取得できていない場合、ビルドに失敗する。

git clone --depth 1 --recurse-submodules https://github.com/minetest/minetet.git minetest
cd minetest
ソースコードを取得する

もしオリジナルではなく、私が使用している版を使いたい場合は https://github.com/TakesxiSximada/minetest-symdon-custom-source.git を使用する。ほとんど違いはないが、以下の修正が加えられている。

  • ゲーム画面内のメニューにホスト名を表示しない。
  • Debianでのビルドに対応。

ソースコードを取得できたらビルドの準備をする。Makefileを生成するために、cmakeを実行する。cmakeのオプションを指定する事で、何をビルドするかを切り替えることができる。サーバーをビルドしたい場合 -DBUILD_SERVER=TRUE を、クライアントをビルドしたい場合 -DBUILD_CLIENT=TRUE を指定する。また、その場で実行するものをビルドしたい場合は -DRUN_IN_PLACE=TRUE を指定する3

cmake -S . -B build -DBUILD_CLIENT=1 -DBUILD_SERVER=0 -DENABLE_FREETYPE=1 -DENABLE_GETTEXT=1 -DBUILD_UNITTESTS=0
ビルドの準備をする

build ディレクトリが作成され、そこに生成物が入るようなビルドの準備が行われる。

準備ができたら make コマンドでビルドを実行する。マシンスペックにもよるが、ビルドにはそこそこ時間がかかる。

cmake --build build
ビルドする

この時点で既にバイナリ等は生成されている。それを直接起動すれば、アプリケーションの実行もできるだろう。macOSはアプリケーションを .app という拡張子を持つディレクトリに所定のルールに従いファイルを配置することで、アプリケーションとして認識できるようになっている。そのためAPP形式のアプリケーションを生成する。

make package
APP形式のアプリケーションを生成する

完了すると minetest-5.7.0-dev-osx.zip といったファイルが生成される。このzipファイルの中に.app形式のフォルダとファイルが格納されている。

住人

この世界に自分一人だけというのはちょっと寂しい。そこで何人かを誘って住人として参加してもらい、週2回(水曜日と木曜日)集まる時間を設定した。今は主にプレイをしているメンバーは4人だが、もうすぐ更に1人増える予定だ(はやく元気になって退院してね。待ってる)。

時間になるとGoogle Meetでビデオチャットしながら、家を建築したり、海上道路を整備したりしている。ここまで熱中するとは思わなかったが、なかなか楽しく時間を忘れて遊んでしまう。作った海上道路がデコボコすぎると文句を言われたり笑われたりしながらも、世界の開発が進んでいくのは楽しいものだ。また人とのふれ合いという意味でも大きく意味があった。飽きられないように、活動したいと思えるような環境と仕組みを整備していきたいと思う。

早朝開発

サーバを運用しはじめた初期は、毎週水曜日と木曜日のだいたい午後19時30分頃に集まり開発をしていた。しかし作業が終わるのは深夜24時を過ぎてしまうこともあった。これはとても良くない。体に悪いことは排除するべきだし、この状況を習慣にしてしまうと、のちのちブラック企業な状態となり、苦しむことになるかもしれない。

もしやるのであればむしろ朝、早起きして開発するぐらいがよい。午前4時から午前6時ぐらいまでを、開発時間としてサーバーを開放すると、早起きも習慣化しそうだし、その日1日を有意義に使用できそうだ。これは運用ルールで可能だ。メンバーに提案たところ、結構好感触だった。そこで、もちろん今までの時間も開放するが、午前4時から午前6時30分までを活動推奨時間として、開放することにした。

2022年09月から実施しているが、だいたい数人は毎日ログインしてきている。こういった制約があると、その時間に作業をするモチベーションになる。また日常生活に影響を与えないような時間という所も良い。朝ログインは普通に早起きの習慣化にも一役買うことができる。だから今は早朝ログインボーナスのような仕組みができないか検討している4

スキン改善

始めは初期スキンを使用していた。マインクラフトのスキンは初期の状態ですでにかなり良い感じだ。自分でビルドしたMinetest serverを使用している場合はそうではない。ペラペラで緑色の人っぽい何かがプレイヤーとして投影されている。可愛くない。もっと可愛いキャラクターが投影されて欲しい。おそらく設定とかmod導入でかなり改善されるものなので、早めに調査し対応したい。

あとから確認したことだが、これは開発者用のテストモードだとこのような見た目になるようだった。通常モードで行うと所謂マイクラのようなスキンが適応された。

更にスキン用のModをインストールして何種類かのスキン変更ができるようになった。

https://blog.symdon.info/posts/1665104416/

その他やったこと

以下にその他に関連してやったことのログを記載する。

構想

環境を構築し世界の開発を進めていくと、いろいろとやりたいことが増えてくる。全てを実現はできないが、できることからひとつずつ実現していければと思う。

ナイトリービルド

実行しているバイナリはしばらく前にビルドしたものを使用している。気が向いた時にバイナリをビルドしなおしているが、毎日最新の状態をビルドしそのバイナリを使用するようにしたい。今はまだ誰もソースを改変するようなことはしていないが、Githubのリポジトリをフォークし、プルリクを作成することであらゆる機能拡張を住人が行えるように環境を整備したい。現状はバニラの状態で使用しているが、ソースを改変した場合はソースコードの公開もすべきだ。その対応もかねて、上記の機構を準備しよう。

ログインボーナス

毎朝、早朝開発推奨時間を設定し、開発という名のゲームをしている。前述もしたが、毎日数名はログインしていて、早朝に開発し、そして通勤や通学の時間になると去っていく。これはとても良い習慣だ。だからこの習慣を促進するための取り組みを行いたい。

今の所考えているのは、夏休みのラジオ体操の参加スタンプのようなものを提供しようと考えている。今の子供達の状況は分からないけれど、私が小学生の頃、夏休み中は近所の広場に集まってラジオ体操をするという風習があった。それが学校のイベントだったのか地域のイベントだったのかは覚えていないが、6時30分に広場に行くと、誰かが持ってきたラジオ受信機からラジオ体操の音楽が流れ出す。そして参加スタンプなるものが存在し、参加すると台紙に参加したことを証明するスタンプを押してもらえるというものだった。よく考えるとそれのどこが嬉しかったのか理解できないけれど、当時はそのスタンプを押してもらうために参加していた記憶がある。なんでもそうかもしれないが、そろっていったり、集まっていったりすることは、嬉しいものなのかもしれない。

このような体験を、模倣できるような機構を提供することを計画している。

第2世代のインフラのシステム構成

第2世代のインフラはとてもシンプルな構成にした。理由は単純で、面倒を見る時間的な余裕があまりないからだ。Google Cloudの無料の範囲枠内で構成するため、GCEの無料用のインスタンスを利用する。必然的にリージョンはオレゴンとなる。日本からの距離はそこそこあるが、この地理的な距離が問題になるほど通信は発生しないと思われる。現時点で特段問題は発生していない。ちなみに第1世代のアーキテクチャは記述することさえはばかられるようなあまりにお粗末なアーキテクチャであったため、闇に葬ることにした。

+---------------------------------------------+
|                                             |
| Google Cloud                                |
|                                             |
|                                             |
|   +-----------------------------------+     |
|   |                                   |     |
|   | game server 1                     |     |
|   |                                   |     |
|   | - Instance: e2-micro              |     |
|   |   - CPU: Intel Broadwell(x86/64)  |     |
|   |   - vCPU: 2                       |     |
|   |   - RAM: 1GB                      |     |
|   | - Disk: SCSI 30GB                 |     |
|   |                                   |     |
|   +-----------+-----------------------+     |
|               |                             |
|          +----+----+-----+                  |
|          |         |     |                  |
|          |         |     |                  |
+----------|---------|-----|------------------+
           |         |     |
           |         |     |
+----------|------+  |     |  +--------------------+
|          |      |  |     |  |                    |
| Area 1   |      |  |     |  | Area 2             |
|          |      |  |     |  |                    |
| +--------+---+  |  |     |  | +---------------+  |
| |            |  |  |     |  | |               |  |
| | Client 1   |  |  |     +----+ Client 2      |  |
| |            |  |  |     |  | |               |  |
| |            |  |  |     |  | |               |  |
| +------------+  |  |     |  | +---------------+  |
|                 |  |     |  |                    |
+-----------------+  |     |  |                    |
                     |     |  | +---------------+  |
                     |     |  | |               |  |
                     |     +----+ Client 3      |  |
+-----------------+  |     |  | |               |  |
|                 |  |     |  | |               |  |
| Area 3          |  |     |  | +---------------+  |
|                 |  |     |  |                    |
| +------------+  |  |     |  |                    |
| |            |  |  |     |  | +---------------+  |
| | Client 5   +-----+     |  | |               |  |
| |            |  |        +----+ Client 4      |  |
| |            |  |           | |               |  |
| +------------+  |           | |               |  |
|                 |           | +---------------+  |
+-----------------+           |                    |
                              +--------------------+

作業ログ

以降はおおむねシステム構築時の作業ログだ。何かの参考になればよいと思う。

インストール

インストール方法はいくつかある。今回はmacOSに直接インストールする。Dockerを用いるほうが簡単だが、設定を何度も変更するなどして再起動を繰り返したかったため直接インストールすることにした。

brew install minetest

起動

/usr/local/opt/minetest/minetest.app/Contents/MacOS/minetest

設定

/usr/local/opt/minetest/minetest.app/Contents/MacOS/minetest

画面サイズがおかしい問題

Homebrewでインストールしたバイナリで起動すると画面サイズがおかしな状態になることがわかった。Github上のPull requestを確認すると、既に修正されmasterブランチにマージされていた。

https://github.com/minetest/minetest/issues/10654

Docker Imageのビルド

前述の不具合は既に修正されているが、Homebrewでインストールしたバイナリは、まだそれに追い付いていないようだった。そのため、最新のソースからビルドすることにした。macOS上でビルドすることもできたが、ビルド環境を整備することが面倒であったため、Docker ImageとしてDocker上でビルドすることにした。

git clone https://github.com/minetest/minetest.git --depth 1
cd minetest
docker build --ssh=default --tag minetest -f Dockerfile .

macOS上でのソースからのビルド

macOS上でビルドする手順も記録しておく。これを実行すると minetest-5.6.0-dev-osx.zip のような名前のZIPファイルが生成される。このZIPファイルの中に、macOS用のアプリケーション形式のディレクトリが作成されている。それをダブルクリックするか、openコマンドで起動すれば良い(はず)。

brew install cmake curl freetype gettext libjpeg libogg libpng libvorbis luajit
git clone https://github.com/minetest/minetest
cd minetest
git clone https://github.com/minetest/irrlicht lib/irrlichtmt
cmake .
make -j$(nproc)
make package

ただ確認したところ以下のエラーを出力し起動に失敗した。

The application cannot be opened for an unexpected reason, error=Error Domain=NSOSStatusErrorDomain Code=-10827 "kLSNoExecutableErr: The executable is missing" UserInfo={_LSLine=3863, _LSFunction=_LSOpenStuffCallLocal}

OSはmacOS 12.5 Monterey、CPUはIntel Core i5を使用している。環境に起因する問題だとは思うが、調査できていないため原因はわかっていない。

Minetest Organizationが所有する主なリポジトリ

Minetest Organizationが所有する主なリポジトリとその用途をまとめた。ただしドキュメントなどのリポジトリは省略した。

リポジトリ主な言語内容
minetestC++Minetest本体。
minetest/irrlichtC++オープンソースの3DエンジンであるIrrlichtのfork。MinetestではそれをMinetest用に拡張して利用している。
contentdbPythonデータベース。SQLAlchemy, Flask, Celeryを利用している。
minetest_gameLuaゲームエンジン。
minetestmapperC++MinetestのMapから概要の画像を生成する。
minetest_android_depsShellAndroidの依存関係を解決するためのスクリプト。
serverlist-公開されているMinetestのサーバーの一覧。
io_scene_xPythonBlender2.8以降用のExporter。
B3DExportPythonBlender2.7以前用のExporter。

サーバーとして起動可能なバイナリをコンパイルする

BUILD_CLIENTとBUILD_SERVERを制御することで、サーバー用のバイナリやクライアント用のバイナリをビルドできる。今回はサーバー用のバイナリが必要になるのでそれをビルドする。

cmake . -DRUN_IN_PLACE=0 -DBUILD_SERVER=TRUE -DBUILD_CLIENT=FALSE
make -j$(nproc)
make package

ビルドしたバイナリはプロジェクト直下に配置しないと、init.luaのPATHの辻褄が合わなくて起動に失敗する。おそらく回避する方法はあるが、調査しきれなかった。仕方がないので、バイナリをリポジトリの上部にコピーして使用する。

cp bin/minetestserver .
cp bin/minetest .

初期マップの作成

minetestをプレイするためにはworldを作成する必要がある。

minetest_gamesを取り込む

どのようなモードのゲームをプレイするかは、gamesディレクトリに格納されているゲームから選択できる。初期状態ではdevtestのみが入っている。これは開発者用のゲームで初期状態から最強の装備をしており、見たこともないようなブロックがあったりする。また木などはなく、クラフトもできない。これは開発したものの動作を確認するためのゲームだ。サバイバルモードのような状態でプレイすることはできない。

通常のゲームとしてプレイするためにはminetest_game5を取り込む必要がある。これはminetest本体とは別のリポジトリで管理されており、別途取得する必要がある。今回は手動でGithubから取得することにした。

cd games
git clone [email protected]:minetest/minetest_game.git minetest_game

これを用いるとdevtestではない通常のゲームとしてminetestを楽しめる。

マップの作成

CLIからマップを作成する方法を調べたがわからなかった。マップが作成できさえすればよいので、ビルドしておいたクライアントを起動し、そこから手動でマップを作成した。

./minetest

ビルドしたクライアントがキーボードの入力を受け付けない問題

マップを作成するためにクライアントを起動したが、キーボードの入力を受け付けてくれなくて困った。なぜかは不明だが、不便すぎるので調査する。実際にプレイする際は、Homebrewでインストールしたクライアントを使用した。

サーバーの起動

コピーしたバイナリを指定してサーバーを起動する。

./minetest

起動に成功すると以下のような出力が表示され、30000ポートを開く。

bash-5.1$ ./minetestserver  --config ./minetest.conf --worldname world1
2022-07-18 18:34:33: [Main]: Using world specified by --worldname on the command line
2022-07-18 18:34:33: WARNING[Main]: Game Minetest Game at /opt/ng/minetest/games/minetest_game:
2022-07-18 18:34:33: WARNING[Main]:     "name" setting in game.conf is deprecated, please use "title" instead
         __.               __.                 __.
  _____ |__| ____   _____ /  |_  _____  _____ /  |_
 /     \|  |/    \ /  __ \    _\/  __ \/   __>    _\
|  Y Y  \  |   |  \   ___/|  | |   ___/\___  \|  |
|__|_|  /  |___|  /\______>  |  \______>_____/|  |
      \/ \/     \/         \/                  \/
2022-07-18 18:34:33: ACTION[Main]: World at [/Users/sximada/Library/Application Support/minetest/worlds/world1]
2022-07-18 18:34:33: ACTION[Main]: Server for gameid="minetest" listening on 0.0.0.0:30000.
2022-07-18 18:34:51: ACTION[Server]: test [127.0.0.1] joins game. List of players: test

サーバーを起動したら、クライアントを起動にオープニングの画面から接続情報を入力する。

https://res.cloudinary.com/symdon/image/upload/v1658137398/blog.symdon.info/1650178576/minetest-opening.png

脚注


1

正しくはボクセルゲーム用のゲームエンジンと言う方が正しい。ゲーム自体を構成しているものは mintest_gamesVoxelLibre という名前で、Modの集合として配布されている。ベースの部分がminetestとして実装されていて、ゲームを構成する部分はModで実装する事を想定している。CとEmacs Lispで実装されたEmacsと少し近さを感じる。

2

これは既に修正されている。

4

ログインボーナスの機能は実装した。 https://blog.symdon.info/posts/1678364398