🎇

【Minecraft BE】Script APIでModみたいなものを作ろう(超入門編)

2024/03/31に公開

何をするのか

マイクラBEのScript APIを使ったビヘイビアーパックを自作して機能追加をしたい。
なお、開発する端末はWindowsを対象としている。
この記事はプログラミングが未経験でも理解しやすいように正確でない表現や呼び方をするので、予めご了承頂きたい。

作るもの

雪玉が当たった場所に爆発を起こすスクリプトを作りたい。

テキストエディタのお話

最悪メモ帳があればプログラム自体は書くことができるが、これは例えるなら釜と薪でご飯を炊くようなものである。現代人の我々は炊飯器という便利なアイテムを使うように、プログラミングにも便利なメモ帳が存在する。

  • Visual Studio Code
    持っていない方は今すぐインストールして日本語化もしておこう。
    インストール時は特に設定を触らず「次へ」連打で良い。
    ちょっと名前が長いのでvsCodeと呼ぶことにする。

https://code.visualstudio.com/Download

フォルダーの構成

全体像

testScript
    ├─ pack_icon.png
    ├─ manifest.json
    └─ scripts
        └─ main.js

testScript

いわゆるプロジェクトフォルダで、このスクリプト全体を管理するフォルダー。
Cドライブの中なら基本好きな場所に作って良い。好きな名前を付けるときはできればアルファベットで入力すべし。

pack_icon.png

アドオンのサムネイル画像。
正方形にしておくのが望ましい。

manifest.json

これは新しいテキストファイル等を作成して、名前をmanifest.jsonに変更すればファイルの用意ができる。

拡張子を変更すると、ファイルが使えなくなる可能性があります。

などとおどかされる事があるが、気にする必要はない。変更しよう。
vsCodeを起動し、manifest.jsonをvsCodeにドラッグ&ドロップしてファイルを開き、以下のコードを貼り付ける。

manifest.json
{
	"format_version": 2,
	"header": {
		"name": "テストスクリプト",
		"description": "説明文",
		"uuid": "■■■■■■■■■■",
		"version": [1, 0, 0],
		"min_engine_version": [1, 20, 30]
	},
	"modules": [
		{
			"description": "Script resources",
			"language": "javascript",
			"type": "script",
			"uuid": "■■■■■■■■■■",
			"version": [1, 0, 0],
			"entry": "scripts/main.js"
		}
	],
	"dependencies": [
		{
			"module_name": "@minecraft/server",
			"version": "1.9.0"
		},
		{
			"module_name": "@minecraft/server-ui",
			"version": "1.1.0"
		}
	]
}

2か所「■■■■■■■■■■」が見つけられると思う。ここにはそれぞれ別のUUIDと言う8-4-4-4-12桁の16進数を入力する。
ここに書いたUUIDはリソースパックやビヘイビアーパック(アドオン)の識別IDとして使われるため、新しいパックを作るたびにここを書き換える必要がある。

こちらのページで生成することもできるのだが、vsCodeには候補に出して自動生成する機能があるので、開発をスムーズにするために以下の設定をおすすめする。

vsCodeでuuidを候補&生成する設定
  1. vsCode上で ファイル → ユーザー設定 → ユーザースニペットの構成 と進み、上の検索窓に「json.json」と入力して「json.json」を選択する。

  2. json.jsonファイルの内容を以下に書き換える。

    json.json
    {
    	"UUID": {
    		"prefix": "uuid",
    		"body": [
    			"$UUID",
    		]
    	}
    }
    

  3. manifest.jsonに戻って適当なところに「uuid」と入力すると候補が出るので、マウスやTabキーで選択するとランダムなUUIDが自動生成される。

入力例、もしくは早くスクリプト書かせろな人向け
manifest.json
{
	"format_version": 2,
	"header": {
		"name": "テストスクリプト",
		"description": "説明文",
		"uuid": "98d9c771-f881-41f8-8520-f263504633df",
		"version": [1, 0, 0],
		"min_engine_version": [1, 20, 30]
	},
	"modules": [
		{
			"description": "Script resources",
			"language": "javascript",
			"type": "script",
			"uuid": "ba6e3ffb-d5af-4b2b-b552-9d1568bcc431",
			"version": [1, 0, 0],
			"entry": "scripts/main.js"
		}
	],
	"dependencies": [
		{
			"module_name": "@minecraft/server",
			"version": "1.9.0"
		},
		{
			"module_name": "@minecraft/server-ui",
			"version": "1.1.0"
		}
	]
}

scripts/main.js

ここに本体となるプログラムを書いていく。
作成方法はscriptsフォルダーを作ってから、その中にmanifest.jsonと同様に新しいテキストファイル等を作成し、名前をmain.jsに変更する。

いざプログラミング

早速main.jsにコードを書く。
main.jsをvsCodeにドラッグ&ドロップしてファイルを開き、ひとまず解説は後にして以下のコードを貼り付ける。

main.js
import { world } from "@minecraft/server";

world.afterEvents.projectileHitBlock.subscribe((event)=>{
	
	const D = event.dimension;
	const L = event.location;
	
	D.createExplosion(L, 5);
	
});

たったの10行である。

Minecraftに導入

プロジェクトフォルダであるtestScriptをMinecraftのアドオンを置く場所にコピーする。
Minecraft自体のフォルダは「C:/Users/(PCユーザーの名前)/AppData/Local/Packages/Microsoft.MinecraftUWP_8wekyb3d8bbwe/LocalState/games/com.mojang/」内で、アドオンは「com.mojang/development_behavior_packs」フォルダーの中にコピーする。

AppDataが見つからないんだけど?

AppDataが見つからない場合は隠しフォルダを非表示にされている場合がある。
エクスプローラーの 表示 → オプション → 表示 → 隠しファイル、隠しフォルダーを表示する をクリックしてOKを押すと表示されるようになる。

テストプレイをしよう

実際にMinecraftを起動して、ワールドに「テストスクリプト」を入れる。
雪玉の当たったブロックが爆発すれば成功。

コードの解説

一行ずつコードを解説する。

import { world } from "@minecraft/server";

@minecraft/serverというシステムにある「world」という機能をこのファイルで使うという意味。
基本はこの「world」機能を使って色々なコードを書く。


world.afterEvents.projectileHitBlock.subscribe((event)=>{
});

ここでは着弾イベントの登録を行っている。
プログラムは 「〇〇したときに、××する」 の集合であり、イベントは 「〇〇したときに」 の部分にあたる。
今回の場合は 「雪玉が着弾したときに、そこで爆発する」 を作りたいので、着弾のイベントを登録する。
上から順でなくてややこしいのだが、この2つworld.afterEvents.projectileHitBlock.subscribe((event)=>{});はセットになっている。
イメージ的には「ここからイベント」「ここまでイベント」のように着弾イベントと他のコードを区別するために、開始と終了を宣言する必要がある。
そのため、着弾したときに何をするかは「ここからイベント」「ここまでイベント」の間に書く。


const D = event.dimension;
const L = event.location;

D.createExplosion(L, 5);

実際に着弾イベントが呼ばれた(=着弾した)とき、爆発を起こすコードがここ。
処理の終わりには;を書いておく。

const D = event.dimension;

event.dimensionは着弾した次元を取得する。
Minecraftでは現世、ネザー、エンドの3種類の次元に座標があるので、座標だけだとどこを指しているのか分からなくなってしまう。
そこでまず着弾した次元情報を取ってから、座標を指定してその次元で爆発を起こす必要があるのだ。
で、その取得した次元情報に「D」と名前を付ける、というのがconst D = の部分にあたる。
わざわざ名前を付けなくても問題ないのだが、何度もevent.dimensionなんて長い文字は書きたくないのでDと置いておいた[1]


const L = event.location;

ここで着弾した座標情報を取得して「L」と名前を付けている[2]
Minecraftで左上に表示できる、あの座標のこと。


D.createExplosion(L, 5);

次元情報と座標情報の2つが集まったので、爆発が起こせる。
次元Dが持つcreateExplosion[3]機能を使って爆発させる。
()内で爆発の設定を行っていて、L5の2つを指定している。
一番目のLはさっき名前を付けた座標情報 で、爆発の中心を指定する。
二番目の5は爆発の半径 、つまり爆発力のこと。好きに指定して良いがあんまり大きいと爆発したときゲームが重たくなる。

ちなみに爆発部分では次元情報と座標情報の名前を付けたが、名前を付けず爆発を起こそうとするとこうなる。

event.dimension.createExplosion(event.location, 5);

これを1行で書けてスマート!と感じるか、ごちゃごちゃしててよく分からない!と感じるかは人それぞれだと思うので、是非自分が気に入った書き方を見つけてほしい。

バグあり

先ほど書いてもらったコード、実はバグがある。
察しの良い方はお気づきかもしれないが、 「雪玉が」着弾 とはどこにも書いていないのである。
なので着弾できるエンティティであればなんでも爆発するようになってしまう。
矢、ポーション、釣り竿、トライデントなど、雪玉でなくても爆発が起こる。スケルトンが爆発を操るMobに変身してしまった。
これは良くないのでコードに手を加える。
main.jsを以下のコードに書き換えてほしい。

main.js
import { world } from "@minecraft/server";

world.afterEvents.projectileHitBlock.subscribe((event)=>{
	const P = event.projectile; // 投げものの情報を取得
	if(P.typeId === "minecraft:snowball"){ // 投げものが雪玉だったら
		const D = event.dimension;
		const L = event.location;
		
		D.createExplosion(L, 5);
	}
});

さっきと比べて何かプログラムの中に日本語が混じっている。
これはコメントアウトと言い、実行に影響の出ない文を1行だけ書き込める。
//から始めてその行の終わりまでコメントとして認識される。

複数行でコメントアウトしたい場合はこんな感じ

/*から*/までがコメントと認識される。

/*
アコ複
ウメ数
トン行
 ト
*/

if(P.typeId === "minecraft:snowball"){
}

イベントのようにこの2行もセットである。
「投げものが雪玉だったら」{}の中身を実行。 となっていて、P.typeIdは投げものにある多くの情報の中で、typeIdというエンティティの種類をあらわす文を取ってきて、それがminecraft:snowballかどうか?つまり雪玉であるかを調べている。=の数は3個なので気を付けるべし。

あるいはこのように書いても良い
main.js
import { world } from "@minecraft/server";

world.afterEvents.projectileHitBlock.subscribe((event)=>{
	const T = event.projectile.typeId; // 投げもののエンティティ種類情報を取得
	if(T === "minecraft:snowball"){ // 投げものが雪玉だったら
		const D = event.dimension;
		const L = event.location;
		
		D.createExplosion(L, 5);
	}
});

テストプレイをしよう その2

書き換えたmain.jsを「com.mojang/development_behavior_packs/testScript/scripts/」内に上書きして貼り付ける。
ここのコピー作業が面倒だったら初めからMinecraft内にあるmain.jsを直接編集しても良い。ただし時折バックアップするのを忘れずに。
スクリプトを上書きしたらワールドを入りなおすか、入ったままでも/reloadコマンドを使えばスクリプトが再読み込みされる。
雪玉以外で爆発が起こらなかったらバグ修正完了となる。

おわりに

以上でこの超入門記事は終わりです。お疲れ様でした。
丁寧に解説することを心掛けたのでやたら長ったらしくなってしまったが、「雪玉の着弾場所を爆発させる」本体のmain.jsはたったの11行で書くことができる。
これを見たどなたかがScriptAPIを使ったアドオンの開発者に、またはプログラミングの門戸となれば幸いである。

次回以降はこのスクリプトの機能追加アップデートや、TypeScriptを用いた本格的な環境構築についても解説したいといったところで、筆を置くことにする。

脚注
  1. ここでは重複しないように分かりやすくDとしたが、本当は名前で何を表しているのか明確にするためにdimensionと名前を付けたほうが良い。 ↩︎

  2. dimensionと同様に本来はlocationとしたい。 ↩︎

  3. 直訳で「爆発を作る」 ↩︎

Discussion