1.13でワールドのフォーマット変わったんだよな~~w

標記通りです。
具体的に言うと、Section[:list]部はblocks[:bytearray]の配列が廃止され、パレット方式となりました。
Pallets[:list]にパレットデータが格納され、BlockStates[:compound]にステートIDが書かれています。ちなみにBlockStates[:longArray]はlong配列です。1long値につき16blockが格納されていると思われます。longは64bitなので、おそらく16bitでしょう。メタデータも書かれていませんすべてプロパティーに変更されています。
パレットの要素がName[:string]とPropertis[:compound]です。

HeightMapが増えたため、HeightMaps[:compound]に格納されています。ライトマップや水のしみこみ??みたいなマップが格納されています。これ、あれですねもし別のライブラリでやるとしたら計算がしんどいめんどい。

IsTerrainPopulated[:byte]が見つからない。なんかStatus[:string]に変わったかな???ていうか文字列で管理するのなんなの……(文字列管理嫌悪派

なんかよくわからんListがいっぱいありますね。真相は自分の目で……

たいへんそうです。

.NETのLevelDBのライブラリについて考える

OrangeNBTの実装に向けての検証とテスト等

LevelDBはgoogleが開発したSQLiteみたいなデータベースです。MinecraftのBedrock版でワールドの保存に使われてます。C#で実装しなおすのは極めて車輪の再発明です。ライブラリがどれがいいのか考えるだけの記事です。

LevelDBはCでの実装が公式に公開されてます。https://github.com/google/leveldb
.NETでは動きません。DLLImport等使えば動くと思いますけど……。

理想のライブラリの条件を上げましょう
・追加のDLLいらない。NativeDLLもできればいらない。
・ソースコードのまま導入できる。いわばオープンソース
・.NET Standardで動いてほしい。動かなくても改造可なら改造する。
・ライセンスにソースコードの開示を求める条項がないこと。このライブラリの利用者もおそらく継承されるため
・別に高機能は求めてない。低レベルでもいい。うごけばそれでいい。

ざっとググってみた限り以下のライブラリを見つけたので検証していきます。
LevelDB.NET
https://github.com/neo-project/leveldb
ライセンス:BSD-3。(可)
githubを見る限りcppファイル等しかない。下記のReactiveExtensionのことでしょうか?

LevelDB sharp
https://github.com/meebey/leveldb-sharp
ライセンス:BSD-3。(可)
ネイティブDLLの使用:あり(unix等で動かないっぽい?)

ReactiveExtension LevelDB
https://github.com/Reactive-Extensions/LevelDB
ライセンス:Apache License, Version 2.0(可)
ネイティブDLLの使用:あり(厳しい)

IronLevelDB
https://github.com/tg123/IronLeveldb
ライセンス:MIT(可)
ネイティブDLLの使用:なし
しかし、githubのREADMEをよく読むと、「This project is still under hard working」このプロジェクトはまだ作業中みたいなこと書いてあるし、読み込み関数しかまだ書いてないぜ見たいこと書いてある……。むむむこれに期待したいけど……厳しい。

Nugetの上位のそれっぽいやつもリンク切れてたり。ライセンスがよくわからなかったり……

そもそもMOJANGのLevelDBは若干改造されたやつである。圧縮方法がどうも違うらしい。
https://github.com/Mojang/leveldb-mcpe

うううむ……どうしようか。
.NET Standardにするとやはり、ネイティブDLLはない方がいいわけで。(うざい・使いにくい・各自コンパイル面倒くさい64bit/32bitでも変わる)

やはり……車輪の再発明しちゃう?

Minecraftの地形生成を考える【2】

Minecraftの地形生成を考える【2】

前回、一応基本となる地形生成のパーリンノイズについて一応書きましたので、今回はBeta1.8以降のバイオームわけについて。

バイオーム拡大法
バイオームを拡大していく方法です。
ゆえにMinecraftの地形生成は時間がかかります。

簡単な仕組みは
16×16(チャンク)を生成するために、もっと小さいブロックの四角形(例:4×4)を拡大・補完することで無限の生成を可能にしています。
無限といってもint値やlong値には最大が有るわけですから、その最大のなかのちょっとを何回も拡大することで擬似的に無限世界を生成することができるのです。
一番最初は固定シード値によってランダムに点をばらまくだけです。

拡大・補完の仕方
2×2ならば3×3に拡大します。(n x n => (2n – 1) x (2n – 1))

A B
C D

一番最初の拡大のときは下記のように拡大して補完します

A A or B B
A or C A, B, C or D B or D
C C or D D

この処理の際、シード値を常に座標から計算するなどして一定にしておかないと次のチャンクとの補完結果がずれる場合があります。また隣のチャンクとの差異吸収のために16×16は補完後18×18になるようにしてそこから16×16を取り出すことで次の拡大に影響が出ないようにします。

それ以降の拡大時には大陸や海をちゃんとつなげていくために上下または左右の最頻値をとって補完していきます。
ただし全て異なる場合などは上記同様ランダムに決定していきます
例:

A B
A A

これを、

A A B
A A B
A A A

これをもう一回拡大すると

A A A B B
A A A A B
A A A B B
A A A A A
A A A A A

この拡大処理を十分に繰り返し、あるていどの大きさになったところで終了します。
このようにバイオームのあの複雑なバイオームの境界線を生み出すことができるのです。

Minecraftの地形生成を考える【1】

Minecraftの地形生成を考える【1】
最初はずっと2D世界の話をしていきます。
Minecraftでいうと上からみた世界みたいな感じです。

Minecraftはどこまで行ってもワールドが続きます。
つまり……無限の生成を考えるということである。

有限の生成は実は結構簡単であったりする。
例えば64×64みたいな奴
実装方法としては64×64の世界に、海と陸のブロックをばら撒きランダムで結合したりばらしていったりする。
まあここでは省略しますが。
ランダムが重要になってきます。

しかし無限となると初回で全部ワールドを生成してしまうわけには行きません。
何らかの手段でなめらかに地形を繋げる必要があります。

コレを見てください。Googleでy=2xのグラフです。

この画像の範囲外を想像することはできますか?きっと容易だと思います。
なぜなら数式が与えられている=関数が与えられているからです。
ずっと同じ角度で直線が続いていきます。

もう一つ、プログラム上での乱数は擬似乱数。つまり関数です。
つまり、この疑似乱数を使っている時点で次にくる値が明らかだということ。

javaデフォルトのランダムで同じシード値を与えて初期化すれば、実行するたびに同じ値が出力されるはずです。

Minecraft Beta1.7、使われてるのがパーリンノイズ。同じシード値を与えれば常に同じ値が出ます。

パーリンノイズの周期を調整して2~4つ重ねることでそれっぽい地形を無限で生成することができます。

バイオームを分けるのは難しいです。
簡単にできる方法としてはボロノイノイズを使うのが良いですが、直線的になってしまいます。

しかし、Beta1.8以降はかなり複雑です。海沿いにビーチバイオームなどがあり、生成の基準がバイオームになっています。
これは今度解説することにします。