アレフガルド as Code（ナレッジ編）

# はじめに
　この記事は、[NSSOL Advent Calendar 2024](https://qiita.com/advent-calendar/2024/nssol)の3日目の記事です。
　12/2のAdvent Calendar記事では、マインクラフトのCodeBuilderを使って、JavaScriptのコードでアレフガルドを生成する取り組みについて紹介しました。この取り組みを進めていく中で、CodeBuilderを使って地形を生成する上での知見がいくつか得られています。本稿ではそれらをまとめてご紹介しようと思います。CodeBuilderを使って建築や地形生成に取り組む際の参考としていただければ幸いです。

# コード実行時の距離の制限
　通常のマインクラフトで`/fill`などのコマンドを用いてブロックを配置することができる距離の上限は、演算距離[^a]の設定値で決まります。が、CodeBuilderで`blocks.fill()`などのコードを用いてブロックを設置する場合には、演算距離ではなく描画距離[^b]の設定値までブロック操作を行うことが可能です。
[^a]:マインクラフトで、プレイヤーの周囲でブロックやエンティティの動作が計算される範囲のこと。設定値によって範囲が変わります。
[^b]:マインクラフトで、プレイヤーの周囲に表示されるブロックやエンティティの範囲のこと。設定値によって範囲が変わります。

　Minecraft Education Editionの場合、演算距離はワールド作成時に指定するパラメータで、4～12チャンク[^c]の範囲で設定可能です。ワールドをオープンする際に値を変更することが可能ですが、ワールドをオープンしている間は変更できません。一方で、描画距離はワールドオープン中にも変更可能なパラメータで、5～96チャンクの範囲で指定可能です。描画距離はワールド毎のパラメータではなく、マインクラフト全体のパラメータの様で、あるワールドをオープン中に変更した描画距離の設定は、別のワールドをオープンした後にも引き継がれているようです。
 [^c]:マインクラフトのワールドを構成する16x16ブロックの単位。ワールドの生成や描画、演算の基本単位となります。
 
　設定値のレンジの違いからも分かるように、演算距離よりも描画距離の方が大きな値に設定することが可能なので、CodeBuilderでコードを実行する方が遠方までブロックを配置することが可能となっています。実際に、16倍のアレフガルドの地形を生成した時には2048x2048ブロックの範囲で地形生成コマンドを実行しましたが、描画距離を最大値である96チャンク（≒プレイヤーから1536ブロック）に設定することで、問題なくコードを実行することができました。描画距離よりも遠方にブロックを配置するコードを実行しようとしたときの振る舞いに関しては、[こちらの記事](https://qiita.com/yamamorisoba/items/f7aa638539b3dfaf6ef9)に検証結果をまとめています。端的に言うと、コードは実行されず不発に終わります。
　なお、一回のコマンドで設置可能なブロック数の上限は、CodeBuilderでも32768ブロックのようなので、一度に広範囲にブロックを設置しようとすると、距離ではなくブロック数の上限に引っかかることがあるので注意が必要です[^1]。
 [^1]:Java Editionの場合、`/gamerule commandModificationBlockLimit`コマンドで、一回のコマンドで設置可能なブロック数の上限値を変更することが可能らしいのですが、Education EditionやBedrock Editionでは使えないようです。

# 利用可能なコマンドの制限と対応策
　CodeBuilderで、JavaSciprtのコードとして実装されているマインクラフトのコマンドは、[MakeCodeのリファレンス](https://minecraft.makecode.com/reference)で確認することができます。残念ながら、マインクラフトのすべてのコマンドが実装されているわけではないため、コードとして直接実行することができないコマンドも存在します。また、JavaScriptのコードとして実装されているコマンドでも、マインクラフトのコマンドで実行可能な全てのオプションが実装されているわけではありません。
　マインクラフト上にコマンドとしては存在しているけれども、CodeBuilderのJavaScriptには実装されていないコマンド・オプションを実行したい場合は、`mobs.execute()`を使います。マインクラフトの`/execute`に相当するコードの様で、利用する際の構文は以下となっています。

 ```JavaScript
mobs.execute(mobs.target(<target>),world(<x>,<y>,<z>),<command>)
 ```

　このコードは、`<target>`で指定したmobに、座標x,y,zで`<command>`を実行させるという処理を行います。`<command>`の部分にマインクラフトのコマンドを指定することができるため、CodeBuilderに実装されていないコマンド・オプションも実行させることが可能です。<target>としては任意のエンティティを指定できそうですが、エージェント(MY_AGENT)[^d]を指定しておけば、mobがスポーンしていないワールドでもコードを実行することが可能です。
 [^d]:マインクラフトのCodeBuilderで使用される仮想キャラクター。プレイヤーの代わりにコマンドを実行することができます。

　`<command>`部分にコマンドを指定する上での注意点としては、オプションを指定するための符号が=ではなく:になるということです。例えば、`/fill`コマンドでブロックを逆さまに設置したい場合、マインクラフトのコマンドでは`"upside_down_bit" = true`のように等号を使ってオプションの値を指定しますが、`mobs.execute()`にコマンドを渡すときには、`"upside_down_bit" : true`のようにコロンを用いてオプションの値を指定する必要があります。

　`mobs.execute()`を用いてCodeBuilderに未実装のコマンドをコード化した事例に関しては、[こちらの記事](https://qiita.com/yamamorisoba/items/26905b328cff581102d0)を参考にしていただければ幸いです。

# コマンドブロックの効果範囲の制約と対応方法
　生成する地形の中で、コマンドブロックを用いて、特定の条件をトリガーとしてコマンドを実行させたい場合があります。アレフガルドの生成においては、村人等、NPCに近づく（プレイヤーとNPCの距離が指定した値よりも小さくなる）ことを条件に会話を発生させたり[^3]、毒の沼地へ踏み込んだ時にダメージを発生させたり[^4]する処理をコマンドブロックを使って実装しています。
[^3]:https://qiita.com/yamamorisoba/items/fdd1dfdc42510e64af5a
[^4]:https://qiita.com/yamamorisoba/items/a7b6ac2c74ea7730b0b8

　ただ、コマンドブロックは演算距離の範囲外になってしまうと動作しなくなってしまいます。この制限を回避するためには、`/tickingarea`というコマンドを利用します。このコマンドの構文は以下となります。
```
/tickingarea add <from: x y z> <to: x y z> [name: string] [preload: Boolean]
```
　preloadをtrueとして、コマンドブロックを設置した範囲をtickingareaに登録しておくことで、プレイヤーとコマンドブロックが演算距離以上に離れていても、コマンドブロックを作動させることができるようになります。ただし、tickingareaとして登録可能な領域は最大で10個なので、上限を超えないように注意する必要があります。

　tickingareaを使って、遠く離れたコマンドブロックが動作するように実装した事例は、[こちらの記事](https://qiita.com/yamamorisoba/items/fdd1dfdc42510e64af5a)です。メルキドの街並みを再現したものですが、村人との会話などを制御するコマンドブロック群は(0,-60,0)付近に設置され、tickingareaとして常時読み込まれています。コマンドブロックの制御対象が配置されているメルキドの街は(1000,-60,1000)付近にあり、プレイヤーがメルキドの中にいる時、コマンドブロックは演算距離の外側にありますが、コマンドブロックを用いた村人の会話機能が問題なく動作してくれています。

# 構造物の複製における課題と対応方法
　マインクラフトで、何かを複製しようとするときには`/clone`コマンドを用いるのが一般的だと思いますが、ある程度の広さがあるマップの中で利用しようとすると以下のような制約が生じます。

- 複製対象が演算距離よりも離れていると複製できない
- 複製対象をtickingareaに含めることで、`/clone`で複製可能となるが、tickingareaは最大で10個という制約があるため、多用できない

　そこで、ある程度広い範囲で複製処理を行う場合には、`/structure`コマンドを用います。複製対象をstructureとして登録しておき、複製したい場所にロードする形をとることで、距離の制約を受けずに任意の場所に対象を複製・設置することが可能となります。`/structure`コマンドで構造物を登録する際の構文は以下となります。

```
/structure save <name: string> <from: x y z> <to: x y z> [includesEntities: Boolean] [saveMode: StructureSaveMode] [includesBlocks: Boolean]
```
|主なオプション|内容|
|:-:|:-:|
|name: string|構造物の名前|
|from: x y z| 保存する領域の一方の角の座標|
|to: x y z| 保存する領域の反対側の角の座標|
|includesEntities: Boolean|エンティティを含むかどうか（省略可能）|
|saveMode: StructureSaveMode|保存モード（diskまたはmemory）|
|includesBlocks: Boolean|ブロックを含むかどうか（省略可能）|

saveModeはdiskを指定しておくと登録情報を永続化できるのでお勧めです。

登録した構造物を読み込んで設置する際の構文は以下となります。

```
/structure load <name: string> <to: x y z> [rotation: Rotation] [mirror: Mirror] [includesEntities: Boolean] [includesBlocks: Boolean] 
```
|主なオプション|内容|
|:-:|:-:|
|name: string| 読み込む構造物の名前|
|to: x y z| 読み込む先の座標|
|rotation: Rotation| 読み込む際の回転角度（省略可能）|
|mirror: Mirror| 読み込む際の反転方向（省略可能）|
|includesEntities: Boolean| エンティティを含むかどうか（省略可能）|
|includesBlocks: Boolean| ブロックを含むかどうか（省略可能）|

　利用上の注意点としては、登録済みのstructureをリストアップするオプションがないため、何を登録したかは自分で記録しておく必要があるという点が挙げられます。
　アレフガルドの生成においては、[こちらの記事](https://qiita.com/yamamorisoba/items/2e6fb100b4ed73d77a27)で、フィールド上に森を生成する際の木の複製に`/structure`コマンドを利用しました。

 # おわりに
 本記事では、マインクラフトのCodeBuilderを使ってアレフガルドを生成する際に得られた知見を共有しました。通常のコマンドでは実現が難しい広範囲のブロック配置や、CodeBuilder未実装のコマンドをCodeBuilderで実行する方法、遠方のコマンドブロックを作動させる方法など、さまざまな課題を克服する方法を紹介しました。

　これらの知見が、皆さんのマインクラフトでの建築や地形生成の参考になれば幸いです。今後も新たな発見や工夫を共有し、マインクラフトの可能性を広げていきたいと思います。

　最後までお読みいただき、ありがとうございました。皆さんのクリエイティブなマインクラフトライフを応援しています！