【ダレトク】Java 版 Minecraft のコマンドの境地 NBT を頼りに、ついでに IT 用語に触れる記事

# はじめに
この記事は IT 用語に触れる記事です。マイクラ好きな人が多いみたいなので、マイクラを頼りに IT の勉強でもしてみませんか？
楽しいマイクラの NBT とは何なのかを考えながらコマンドへの恐怖心を無くし、そのついでに IT 用語を少しかじって成長して行く。そんな感じの無駄話がツマッタ記事を載せておきます。
（マイクラのコマンドを求めてる方は、この記事では紹介していないので、いつか書くかもしれない別の記事をお待ちください。）

この記事の中では、以下の IT 用語の一端に触れることができます。

- JSON
- API

この記事は10分程度で読めます。

#1. NBT とは
入り口はマイクラからにして、まずは NBT について紹介します。NBT は Named Binary Tag の略で、極論を言ってしまうとユニクロへ行ったときに新品の靴下に付いてる "タグ" と同じです。靴下のサイズとか値段とかメーカーとか色々な「情報」がタグに書かれています。それです。
マイクラで NBT という単語を使うタイミングは2種類くらいあります。1つはコマンドで「データタグ」を入力するとき、もう1つは自分達が普段遊んでいるワールドデータやセーブデータなどのマイクラが取り扱っているほぼ全ての情報（実は中身は NBT の集まり）の中に潜んでいます。勘違いすると良くないので最初だけしっかり説明します。

#2. コマンド
#2.1. データタグ
NBT をコマンドで見かけるタイミングは以下の画像の通りです。ここでは "名前" が 「私は防具立てです。」という防具立てを召喚し、更に "名前を遠くからでも見える" ように補足情報を与えようとしています。
![nbt1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/22fb9183-522e-91c6-2214-f3fe939f75f9.png)
ゲーム内では画像の通り \<nbt> と表示されているため、NBT と呼ばれていても特に違和感はありませんし、間違いでもありませんが、この長ったらしい文字列には NBT ではなく「データタグ」という名称があります。上記のコマンドの中で中括弧（波括弧）から中括弧までの文字列全ての事を「データタグ」と呼びます。この中括弧部分を見やすく整形すると以下の表記になります。

```shell
{
    CustomName:"\"私は防具立てです。\"",
    CustomNameVisible:1
}
```

これを更に一般化すると以下のような形式になります。

```shell
{
    <tag name>:<value>,
    <tag name>:<value>,
    ・・・
    <tag name>:<value>
}
```

改行しない場合を考えてみると分かりますが、最後の \<value> の後ろにカンマは付かないので気を付けて下さい。要するに、{品名:靴下,価格:300} のような情報の集まりで、コロン（:）の左と右に何かの文字が書かれていて、それをカンマ（,） 区切りで繋げただけです。出てきた用語の説明は下記の通りです。

```shell
 <tag name>  タグ名：値を識別する名前（項目名）
 <value>     値：持っている情報、数字や文字列などで表される。例えば300円なら「300」など。
```

それぞれ任意の文字列を記載可能ですが、マイクラの中で意味のないものは無視されます。例えばですが、オオカミはヘルメットを装着することができないため、\<tag name> に "頭装備" などと書いてあっても無視されます。

ここで話を一旦 NBT に戻しますが、マイクラで NBT を取り扱う2つ目の事例として、ワールドデータやセーブデータという話がありました。上記のデータタグというのは、コマンドを見栄え良く中括弧で囲った表記のことであり、データタグの表記を使って、マイクラのワールドデータ（中身は NBT の集まり）を書き換えたり、読み出すことができます。データタグとは NBT を読み書きする命令だと考えれば分かりやすいでしょうか。

もう少しデータタグを見てみたい方は、以下のコマンドを入力してみて下さい。プレイヤーが持っている「情報」が一覧表示されます。

```shell
/data get entity @s
```

![nbt2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/e3cbad9a-ff58-de4e-489b-8e2c18e57d56.png)

#2.2. データタグの記法
さて、データタグと NBT の関係について分かったところで、データタグの記法について簡単に説明します。データタグの記法について理解しておくと、今まで見るたびに恐怖を感じていたコマンドが幾分か易しく見えるかも知れません。
データタグが中括弧と \<tag name> と \<value> からできているところまでは説明しましたが、記法にはルールがあります。\<tag name> には、それが何なのかを識別するための名前を書けば良いとして、\<value> には以下の値を記載することができます。

|\<value>  |説明                  |
|----------|----------------------|
|数値  |整数、小数の記載が可能。数字の後ろに b,s,l,f,d などとアルファベットを1つ付けることで整数／小数、表現可能な数字の範囲を決めることもできるがここでは詳細は説明しない。|
|真偽値|整数の１種。1b または 1 で true（真、有効、ON）、0b または 0 で false（偽、無効、OFF）を表す。 |
|文字列|ダブルクォート(")で両端を囲って文字の羅列を記載できる。ダブルクォート自体を文字に含めたい場合にはバックスラッシュとダブルクォート(\")を並べて記載するか、またはシングルクォート(')で両端を囲う。|
|配列|大括弧で囲んだ中に \<value> をカンマ区切りで複数記載できる。但し、最初の値が数値だった場合は２つ目以降の値も数値である必要がある。最初が文字列なら、２つ目以降も文字列が必要となる。|
|データタグ|\<value>の中に更に中括弧から始まり中括弧で終わるデータタグを記載できる。|

例を１つ記載しておきます。

```shell
{
 id:1,
 name1:"Taro",
 name2:"\"太郎\"",
 "\"身長\"":172.4f,
 favorite:[
  "manga",
  "\"カレー\""
 ],
 "\"更にデータタグを記載する例\"":{
   address:"Tokyo",
   age:30
 }
}
```

整数、小数、文字列、そして複数の要素を並べる配列、また配列の中には文字列を書いたり数字を書いたり、更に \<value> にデータタグ自体を書くことでデータタグの階層構造にしたりすることができます。

基本的な構文として括弧で始まったら括弧で終わる、ダブルクォートで始まったらダブルクォートで終わる、コロンの前後にはタグ名と値がある、つなぎ目にはカンマがある、最後の要素の後ろにはカンマは付かない、文法はたったのこれだけです。英語の文法を勉強するよりはるかに楽ですね。

中括弧が多いと呪文のように見えてしまうのですが、あとはマイクラ特有の項目名を覚えてあげれば、動かない村人や強い装備を持ったゾンビなどが作れるようになります。
上の例を summon コマンドなどの後ろにそのまま貼り付ければエラー無く実行できますが、意味のある項目名が無いため、データタグとしては無視されます。

#2.3. JSON
ここで１つ IT 用語について触れておきます。恐らくはデータタグの元ネタになった JSON（JavaScript Object Notation：ジェイソン）と呼ばれるものについてですが、私が知る限り JSON が登場したのは2000年以降です。
2000年台の初期は掲示板、チャットサイト、Web サイト上で動くチープな育成ゲームなど「動的に閲覧中のWeb サイトを動かす手法」が乱立し終わった時代だったと記憶しています。その中で徐々にクライアント（Web ブラウザや自分のPC内のアプリ）とサーバ（Web サイトなど）の間で「効率的にデータをやりとりする手法」や「Web サイト自体を効率的に作成する手法」が登場し始めていました。

JSON は名前の通り、JavaScript を発祥としていますが別に JavaScript に限らず、色々なところで使われています。JavaScript がたまたま Web ページを綺麗にお手軽に動かすための手法の１つだったというだけであり、一方 JSON は情報の伝達手段（表現方法）の１つであり、また「効率が良い」というだけです。
「効率が良い」というのは、同じ情報をより短い情報で表現できる。という観点で評価することができます。
例えば、Mojang Studios がマインクラフトのプレイヤー情報を Web から参照できる「窓口」を用意してくれているので、以下URLにアクセスしてみて下さい。

[Mojang API] https://api.mojang.com/users/profiles/minecraft/JohnikiJoestar

これは JohnikiJoestar というプレイヤーを世界で１つのユニークな ID で表現する UUID を取得するサイトです。見て頂ければわかりますが、名前と ID の他に余分な情報は中括弧とダブルクォート、コロン、カンマだけであり、有名どころではこれ以上短く表す記法は存在しません。（書こうと思えば書けますが読みにくいだけです。）

マインクラフトは Java という言語で 200X 年頃に開発されていますが、その時代に JSON が丁度成熟していたからなのか、開発者の Notch さんが JSON を好きだったからなのかは定かではありませんが、上の URL から得られる ID はデータタグではなく JSON で表されています。

#2.4. JSON の記法
最初に説明したデータタグとほとんど同じ記法です。一般化すると以下のようになります。

```shell
{
    <key>:<value>,
    <key>:<value>,
    ・・・
    <key>:<value>
}
```

データタグとの違いに注目しつつ説明すると、

```shell
 <key>       キー：値を識別する名前（項目名）、ダブルクォートで囲った文字列でなければならない。
 <value>     値：持っている情報、数字や文字列などで表される。例えば300円なら「300」など。
```

ただ呼び名が違うだけですが、\<tag name> の代わりに \<key> という呼び名に変わったことと、\<key> はダブルクォート（"）で囲われた文字列である必要があります。<\value> について、データタグと違う箇所を赤文字にしておきました。以下の通りです。

|\<value>  |説明                  |
|----------|----------------------|
|数値  |整数、小数の記載が可能。小数は 42.195e3（42.195 × 1000）のような<font color="Red">指数表記も使ってよい。</font>|
|<font color="Red">ヌル</font>|何もないことを表すときには小文字半角で null と記載する。|
|真偽値|英半角小文字で true（真、有効、ON）、false（偽、無効、OFF）を表現する。|
|文字列|ダブルクォート(")で両端を囲って文字の羅列を記載できる。ダブルクォート自体を文字に含めたい場合にはバックスラッシュとダブルクォート(\")を並べて記載するか、またはシングルクォート(')で両端を囲う。|
|配列|大括弧で囲んだ中に \<value> をカンマ区切りで複数記載できる。<font color="Red">最初の値が数値だったとしても２つ目以降が数値である必要はない。</font>|
|<font color="Red">JSON</font>|\<value>の中に更に中括弧から始まり中括弧で終わる JSON を記載できる。JSON 自身の事をオブジェクトや JSON オブジェクトなどとも呼ぶ|

JSON の例を１つ紹介しておきます。

```shell
{
  "id": 1,
  "name1": "Taro",
  "name2": "太郎",
  "身長": 172.4,
  "favorite": [
    "manga",
    "カレー",
    1,
    null,
    true
  ],
  "更にJSONを記載する例": {
    "address": "Tokyo",
    "age": 30
  }
}
```

データタグとそんなに違いはないですね。

#3. セーブデータ
#3.1. NBT の可視化
マイクラの中でもう１つの NBT を使っている場所ですが、それは目にみえる所にはありません。Java 版マインクラフトの「saves」フォルダの中を NBTExplorer などの特別なツールで閲覧すると以下のような画面を見ることができます。
![nbt3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172479/1ef18305-00ee-b21c-bd55-4c8043a399c6.png)

ツールを使うことで NBT を閲覧したり、NBT を書き換えることで、バグったブロックを取り除いたり、ワールドの中から好きな情報を取り出したりと「セーブデータを直接編集する」こともできます。

#3.2. セーブデータの中身
そもそもセーブデータとは何なのかという疑問に答えないといけません。まずは、マインクラフトの世界の中であなたが思い浮かべるものをずらずらと列挙してみて下さい。時系列でも良いですし、あいうえお順でも良いです。思いつくもの全てを挙げてみた結果「この情報は次ログインしたときに消えていると何か変だな。」と思ったものは大体セーブデータに含まれているはずです。

例えば、ワールドを作ってから以降、時系列順に適当にいくつか考えてみるとすると、

- 初期スポーン地点
- プレイヤーの現在地
- プレイヤーの持っているアイテム
- プレイヤーの体力、空腹ゲージ、経験値
- チェストの中身
- 村人の立っている場所
- 村人の交易結果
- 置いたブロックの場所
- 天気、時刻
- リスポーン地点

まだまだありますが、とりあえず10個だけ挙げてみました。この中に座標に関する情報がいくつかあることに気付くと思いますが、座標は X（東西）、Y（上下）、Z（南北） の３つの情報で表現できます。
天気はどうでしょう？天気は "晴れ" とか "雨" かも知れませんし、"晴れ" の代わりに "A"、"雨" の代わりに "B" などと書いてあるかも知れませんが、いずれにしても１つの情報で表現できます。
ではここで、天気が "晴れ"、村人１の座標(X=100、Y=68、Z=-50)、村人２の座標(X=90、Y=67、Z=-40) の３種をできるだけ短い文字数で表すことを考えてみて下さい。

例えば以下のような書き方を思いつきます。

```shell
{"天気":"A",{"id":1,"座標":[100,68,-50]},{"id":2,"座標":[90,67,-40]}}
```

```shell
A 100 68 -50 90 67 -40
```

```shell
A100068-50090067-40
```

1つ目は JSON で書いてみました。情報そのままですね。2つ目はなるべく省略して、文字の間にスペースを開けてみました。3つ目はどうでしょう？天気は1桁、村人の数は2人まで、座標は3桁までだと仮定してスペースを無くしました。それぞれに良い点、悪い点があります。

1つ目の形式は "id" という箇所を見てあげれば、どの村人の座標か分かるため、村人１と村人２の情報は順不同だという特徴があります。
2つ目と3つ目の形式は文字数が少ないという特徴がありますが、村人の情報が順不同ではないということや、仮に後ろにプレイヤーの座標があったとすると、それが３人目の村人なのかプレイヤーなのか表現できない問題があります。3つ目については座標が4桁になったらセーブデータが壊れてしまいますね。

マインクラフトJava版というゲームがセーブデータを読み込むときに、1桁目は天気、そこから9桁ずつ村人の情報が２人分入っていると知っていれば、3つ目の例でもセーブデータを読み込むことができます。
2つ目3つ目の例は極端に短くし過ぎましたが、必要な場所にはタグを付けてあげて、場合によっては村人が２人いるという情報や、座標の情報は3桁が上限です、などと決めてあげればセーブデータとしては成立しそうです。

という感じで、タグ付きの情報というのはセーブデータの形式としてとても優秀で、区切り文字が中括弧なのかスペースなのか固定長の桁数区切りなのか、それだけ決めてあげれば、それをそのままファイルに書くだけでセーブデータにすることができます。
後は情報を短く書く工夫をしてあげればセーブデータを小さくすることができますが、それはまた別の話。

# 余談
余談ですが、あるアプリケーションが何らかの情報（先の Mojang Studios の例であれば UUID）を読み書きする「窓口」を提供していることがありますが、これを API （Application Programming Interface）と呼びます。
Mojang の場合は Mojang API でした。Web から利用できる場合には WebAPI などと呼び、WebAPI の流行りはここ10年くらいで誕生したものです。

自分の作ったアプリケーションをみんなに使ってもらいたいときに全部を提供するのはハードルが高いことが有ります。そこで一部の機能だけでも、みんなが API を使って提供しあうことで新たなサービスが生まれることがあります。
例えば、SNS からフォロワー情報を提供する API と、住所に関連しそうな API と、食べログ API を組み合わせたら、深夜３時に呟く飯テロサービスができました。というふうに WebAPI の考え方が普及し出すと共に、色んな企業がインターネットをベースにしたサービスをどんどん作り始めました。

今までは御堅い体質のあった金融業界でも最近ようやく法律が整って API が普及し始めていて、Web 系のエンジニアが大量に必要になっているような状況です。10年くらい前に FinTech とかの単語が騒がれましたが、その流れの１つですね。あ、これは来る。って思った人や企業は当時から Web 系のエンジニアを育成していたんだろうと思います。