bedrock-vizで統合版Minecraftの地図を作る

表題の通り。地図を作る際Java版だとMapcrafterとか、かなりfancyなツールが有志によって開発されているのですが、
統合版にもbedrock-vizというツールがあります。
今回はオンプレ鯖にbedrock-vizを導入して、月一で自動的に地図を生成する設定を行います。
また過去のマップに関してもアーカイブ形式で閲覧できるようにスクリプトを書いていきます。

## bedrock-vizの導入
bedrock-vizは [こちら](https://github.com/bedrock-viz/bedrock-viz) 入手できます。

https://github.com/bedrock-viz/bedrock-viz

以前Windows機に導入したことはあったのですが、Ubuntuへの導入は初めてでした。
`README.md`と`BUILD.md`を見ればだいたい書いてあるんですが、ちょっと躓いたポイントもあったのでそこも説明します。

まずはgitからクローン。

```bash
# dirがhard-codeされているようでこのディレクトリに置かないと動きません
cd /usr/local/share

# リポジトリクローン
git clone --recursive https://github.com/bedrock-viz/bedrock-viz.git

# patchの適用
cd bedrock-viz
git apply -p0 patches/leveldb-1.22.patch
git apply -p0 patches/pugixml-disable-install.patch
```

さてmakeする前に必要なパッケージの導入と、一部`CMakeLists.txt`の修正を行います。
必要なパッケージを以下でインストールします。

```bash
sudo apt install cmake
sudo apt install libpng++-dev zlib1g-dev
sudo apt install libboost-program-options-dev
sudo apt install -y build-essential

# C++17が使われているので、古いg++を使っているならg++ 8以降をインストール
# Ubuntu 20.04 or laterなら大丈夫だと思います
sudo apt install g++-8
```

次に`CMakeLists.txt`の修正です。
大きなワールドのマップを構築しようとするとバッファ・オーバーフローが起こるので、
CMakeのオプションを変更します。
[gitのissue(#194)](https://github.com/bedrock-viz/bedrock-viz/issues/194) を参考にしました。感謝。

```diff:bedrock-viz/CMakeLists.txt
+ set(CMAKE_BUILD_TYPE Debug)
```

また本来C++17でコンパイルしたいのにC++11でコンパイルするようにオプションを設定しているやつがいるので、
C++17でコンパイルしてもらいます。
このバグ報告と対処法の説明は [gitのissues(#196)](https://github.com/bedrock-viz/bedrock-viz/issues/196) で取り上げられていました。感謝。

```diff:bedrock-viz/third_party/libnbtplusplus/CMakeLists.txt
- target_compile_options(nbt++ PUBLIC -std=c++11)
+ target_compile_options(nbt++ PUBLIC -std=c++17)
```

最後にmakeします。

```bash
mkdir build && cd build
cmake ..
make
```

### マップ作成テスト
一旦正しくマップが作成されるか確認します。
先ほどのディレクトリで以下を実行します。
そこそこ時間がかかります。

```bash:/usr/local/share/bedrock-viz/build/
# ワールドデータをコピー、環境によって適宜調整してください
cp -r {ワールドデータのパス} .

# マップ作成開始
./bedrock-viz --db myWorld/ --out test_map1 --html-most    # myWorld/ は適宜書き換え
```

作成が終わると `test_map1/index.html` が生成されるのでブラウザ等で確認してみましょう。

## bedrock-vizの自動実行スクリプト
bedrock-vizの自動実行には以下の処理を行います。
bedrock-vizで生成されたHTMLは `/var/www/html/` に配置して外部から閲覧できるようにします。

```
1. ワールドデータをコピー
2. bedrock-vizを実行してHTMLを /var/www/html/map に生成
3. /var/www/html/map 内のマップディレクトリをリスト化してHTML作成
```

まずはbedrock-vizを実行するスクリプトを作成します。

```bash:map_composer.sh
#!/bin/bash
# Automatically composes a bedrock-viz map

VIZ_DIR=/usr/local/share/bedrock-viz/build
WORLD_DIR={ワールドデータのディレクトリ}
MAP_DIR=/var/www/html/map/`date +%Y-%m`    # 2024-10/ のようなdirにマップを生成します

cd $VIZ_DIR

# Clone the world data
cp -r $WORLD_DIR .

# Make a map directory
eval "mkdir ${MAP_DIR}"

# Start composing a map
eval "./bedrock-viz --db ./OurCity --outdir ${MAP_DIR} --html-most"

# Delete the copy of the world
rm -r OurCity
```

最後に `/var/www/html/map/` 内のマップを一覧化してリンクを生成するスクリプトを作成します。

```bash:map_list.sh
#!/bin/bash
# Automatically constructs a list of maps

VER_PATH=$'${サーバのバージョンを記録しているtxtファイルのパス}'    # 任意です
HTML0=$'<!-- HTML -->'
HTML1=$'\n<p>Current server version: '`cat ${VER_PATH}`$'</p>'
HTML2=$'\n<ul>'
HTML3=$'\n</ul>'

BODY=$HTML0$HTML1    # サーババージョンを表示させない場合は $HTML0 を消してください

# マップのディレクトリ
cd /var/www/html/map/

# ディレクトリ内のフォルダを列挙してHTMLのul形式で記録します
for file in `ls -1d */`
do
    BODY=${BODY}$'\n<li><a href=\"map/'$file$'\">'${file}$'</li>'
done

BODY=${BODY}${HTML3}

# HTMLに書き込み
echo $BODY > /var/www/html/index.html
```

あとはこれらを `crontab` などで定期的に実行することで、自動的にマップの生成を行うことが出来ます。

以上によりこのようなHTMLを表示させることができました。
自動で更新を行うスクリプトも走っていますので、サーババージョンを確認することもできます。
本当はNode.jsなどでスクリプトを書いたほうがスマートなんだろうなと思いますが、Node.jsは門外漢なのでシェルスクリプトかつクソダサデザインでヨシとしました。
もしもっといい方法があるよ!っていう方はぜひ教えていただきたいです!

![スクリーンショット 2024-10-25 221018.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626368/65ad0c0e-02ad-cecb-9c96-529b6c769924.png)

https://ourcity-map.localto.net/