見出し画像

【マイクラ統合版】よく使うAPI Scriptのフレーズ 5選

みなさん、こんにちは!
突然ですが、「API Script」をご存じでしょうか?

API Script」というのは、マインクラフトの統合版において、プログラミング言語(Javascript)を用いてゲームシステムをカスタマイズできる機能のこと。Javascriptの知識さえあれば、マインクラフトのシステムをある程度いじることができるんです。普通のゲームはそんなことできません。マインクラフトのこういうところが私は好きです。

コードの一例。ジャンプしたらkillされるらしい。

さて、本稿では、この「API Script」を使ったアドオンの制作において、ある程度よく用いられるフレーズを備忘録もかねて5つまとめてみたいと思います。主観が多分に含まれています。また、本記事では「API Script」の基本的な事項については触れません。「API Scriptって何ぞや?」とお思いの方はまずこちらの記事からご覧いただくことをお勧めします。


1,import文

API Scriptはimport文から始まります。これがなければただのjsファイルです。具体的には:

import * as server from '@minecraft/server';

のように記述し、これによって、マインクラフトの世界に干渉できるようになります。今のは一例で、人によっては

from '@minecraft/server' import {world,system};

のように書くこともあるらしいですね。好みが別れるところです。

もはや挨拶

言うまでもないですが、ここで同時に変数の宣言を行っています。以下で「server」という変数が突拍子もなく出てきますが、ここで宣言されたものです。

2,毎ティック実行

コマンドブロックに「常時実行」というモードがありますよね。これと同じように、常時プログラムを動かしたいときに重宝する関数があります。

server.system.runInterval(() => {
	//ここに内容を記述
});

それがsystemクラスのrunInterval()です。これは、関数と間隔(int)を引数とすることで、名前の通り、一定周期で関数を実行することができます。上のように間隔を明記しない場合は常に実行します。常にプレイヤーの動きを監視するのにも使えます。ジャンプしたらkillされるAPI Script:

再掲

にもこの関数が使われていますね。
ちなみに、「常時実行」と言えば、functionsファイル内のtick.jsonを想起させます。ご存じのない方に向けて一応説明しますと、tick.jsonはワールド内で常時実行される関数スクリプト(一連のコマンド群で、mcfunction形式で記述されたもの)を定義します。このtick.jsonを用いることでも簡単に常時実行を達成することはできますが、こちらはあらかじめ定義されたコマンドしか使えないので一長一短です。必要に応じてrunInterval()とtick.jsonを使い分ける感じですね。

3,各プレイヤーについて実行

マインクラフトの主人公は、プレイヤーです。このプレイヤーを主体として何かを実行したいときもありますよね。そんな時に重宝するフレーズがあります。


for (const player of server.world.getAllPlayers()){
    //ここに内容を記述
}

それが、
for (const player of server.world.getAllPlayers())
というもの。worldクラスのgetAllPlayers()関数は、ワールド内にいる全プレイヤーを取得し、配列形式で出力します。したがって、各プレイヤーについて何かを処理したいときは、これとfor文を組み合わせれば良いのです。ちなみに、プレイヤーの名前を取得したいときは、player.nameでOKです。

for文の中では、同時に変数playerを宣言しています。このplayerは、playerクラスを有し、コマンドを実行したり(注:下記も参照のこと)、イベント処理をしたりと大きな役割を担います。

4,コマンド実行

マインクラフトのコマンドは非常に優秀で、大抵のことはコマンドで成し遂げられます。そんなコマンドをAPI Scriptの味方につければ正に鬼に金棒。API Script上でコマンドを実行するにはどうすればよいでしょうか?
その答えを握るのが、runCommand()関数です。しかし利用できる状況が限られます。というのも、このrunCommand()関数、クラスがdimensionまたはplayerでないと使えないのです。(注:ちゃんと確認したわけではないので、間違っていたらごめんなさい)なので、回りくどいですが、実践的には以下のように使われます。

【例1:dimensionクラス】

server.world.getDimension("overworld").runCommand("give @a diamond 3")

【例2:playerクラス】

for (const player of server.world.getAllPlayers()){
    player.runCommand("give @a diamond 3")
}

実はこれ、落とし穴があります。というのも、ターゲットセレクターの「@s」(自分自身)が使えないのです。その理由は、コマンドの発動者が明確ではなく、「自分」が定義されていないからです。では、上の例2において、「自分」だけにダイアモンドを与えたい場合はどうすればよいでしょうか?
・・・答えはplayer.nameが握っていまして、

for (const player of server.world.getAllPlayers()){
    player.runCommand(`give ${player.name} diamond 3`)
}

のように直接コマンドにプレイヤー名を代入すればよいのです。

これらを応用して、

function kansu(item,command){
	server.world.beforeEvents.itemUse.subscribe(ev => {
		if (ev.itemStack.typeId == item){
			ev.source.runCommand(command);
		}
	});
}

のように、アイテムを使ったら自動でコマンドを実行する関数を作成することもできます。

マイクラのコマンドでできることは多岐にわたります。コマンドでできること(例:プレイヤーにダイアモンドを与える、メッセージを表示するなど)は、色々コードを書くよりもrunCommand()関数一発で行ったほうが早いことが往々にしてあります。


よく似た関数に、runCommandAsync()があります。こちらは、runCommand()とは異なり、非同期でコマンドを実行することができます。基本はどちらを使っても良いですが、runCommand()でうまくコマンドを実行できない場合、runCommandAsync()を使うとうまくいくことが偶にあります(経験則)。


5,手に持っているアイテムを取得

先日のアップデートで、API Scriptの界隈にも変貌が訪れました。というのも、手に持っているアイテムを簡単に取得できるようになったのです。ターゲットセレクターhasitemと同じような機能ですね。
例えば、現在プレイヤーが持っているアイテムをメッセージ欄に表示する場合には、

server.world.sendMessage(player.getComponent("inventory").container.getItem(player.selectedSlotIndex).typeId)

のように記述すればOKです(注:変数playerは別に定義する必要があります)。ここのポイントは
getItem(player.selectedSlotIndex)
ですね。getItem()関数は、スロット番号(integer)を引数として、インベントリ上でそのスロットに存在するアイテムを返す関数です。今まではスロット番号を具体的に記述する(0番、1番・・・etc)必要があったのですが、アップデートを機にplayer.selectedSlotIndexと記述することで現在選択しているスロット番号を代入することができるようになりました。

おしまい

・・・と、ここまでAPI Scriptについて語ってきました。
API Scriptを始めとするアドオン制作については、私のYoutubeチャンネルでもまとめていますので、お時間が宜しければ是非ご覧ください。その他、技術的な視点からマインクラフトに関する情報を発信していますので、ご興味がありましたら是非訪れてみてください!

また、この記事が役立った場合は、「スキ」をしていただくと今後の記事執筆のモチベーションにもなりますので、よろしくお願いします。

この記事が気に入ったらサポートをしてみませんか?