Minecraft のセーブデータから地図を生成するやつを作った

VoxelMap というクライアント Mod を使っていて,この Mod は地図を PNG に書き出したり できるのだけれど,このところ書き出すところでクラッシュしていたので,セーブデータから 地図を生成するやつを自分で作ることにした。これを実現するためには Minecraft のセーブデータ をパーズする必要があるので,GitHub で適当に検索していたら良さげなのを発見。

matcool/anvil-parser

実際良いのかは分からないけど,なんかそこそこ動いてそうで,且つ最終コミットの日付が最近だったので これを使うことにしてみた。で,example っていうディレクトリがあって,一番上の非空気なブロック を画像に書き出すというものがあったので,それを参考にしながら作った。

作ってから分かったけどめちゃくちゃ遅い。生成にかかる時間はリージョンの中で生成されているチャンクの 数に依存するところはあるんだけど,だいたい 1 リージョン分の画像を生成するのに手元のラップトップだと 7 分くらいかかる。Python のオーバーヘッドだろうか。(知らんけど)

Python でやった理由は検索して出てきた実装の言語の中で割と楽に書けそうだったというもので, Python を使うということに関しては別にこだわりはなかったんだけど,C とか C++ で書き直したり するというはあまりにも辛いなあ。たぶん C とか C++ とかで書いたら速いんだろうけど。

まあ遅いのは VPS で常に走らせとけばいいやって感じで良いことにしました。

あと,このライブラリはブロックを文字列の ID で返してくれるんだけど,文字列ってのがなんかなあー。 ブロックの見た目に対応する整数とかのの ID があるのか知らんけど。

あと画像のクオリティなんだけど,VoxelMap はおそらく実際のレンダリング結果を使っていて (調べた訳じゃないので真偽は不明),これには勝てないな,という感じだった。具体的には透過ブロック のレンダリングで勝てない。透過ブロックをレンダリングするときは,真下のブロックとかあるいはもっと 下のブロックの色が最終的な色に関係してくるんだけど,その処理まではやってられないな,ってことで妥協した。 たぶんあまりこだわって処理すると7分が14分とか簡単になると思う。ただ,段差の処理だけはした。 高低差が分かった気になれないのはあまりにも残念なので。 でも分かった気になるだけで,隣のブロックの Y 座標を覚えておいてそれよりも低ければ暗くして それよりも高ければ明るくするみたいな感じなのでまあ結構適当に処理してます。

そういやこの実装だと,ブロックが追加されるたびにその色のコードを足さないといけない。 (というか現状でも完全じゃない)。 飽きたら死ぬ短命なソフトウェアですね。まあソフトウェアって得てしてそういうものっぽいけど。

ソースコード