本記事の内容は、私が以前noteにて投稿したものと同一です。
詳細はこちら
投稿者のYoutubeチャンネルはこちら
ここではマインクラフトに関する専門的な情報を発信しています。
はじめに
みなさん、こんにちは!
突然ですが、「API Script」をご存じでしょうか?
「API Script」というのは、マインクラフトの統合版において、プログラミング言語(Javascript)を用いてゲームシステムをカスタマイズできる機能のこと。Javascriptの知識さえあれば、マインクラフトのシステムをある程度いじることができるんです。普通のゲームはそんなことできません。マインクラフトのこういうところが私は好きです。
さて、本稿では、この「API Script」を使ったアドオンの制作において、ある程度よく用いられるフレーズを備忘録もかねて5つまとめてみたいと思います。主観が多分に含まれています。また、本記事では「API Script」の基本的な事項については触れません。「API Scriptって何ぞや?」とお思いの方はまずこちらの記事からご覧いただくことをお勧めします。
Import文
API Scriptはimport文から始まります。これがなければただのjsファイルです。具体的には:
import * as server from '@minecraft/server';
のように記述し、これによって、マインクラフトの世界に干渉できるようになります。今のは一例で、人によっては
from '@minecraft/server' import {world,system};
のように書くこともあるらしいですね。好みが別れるところです。
言うまでもないですが、ここで同時に変数の宣言を行っています。以下で「server」という変数が突拍子もなく出てきますが、ここで宣言されたものです。
毎ティック実行
コマンドブロックに「常時実行」というモードがありますよね。これと同じように、常時プログラムを動かしたいときに重宝する関数があります。
server.system.runInterval(() => {
//ここに内容を記述
});
それがsystemクラスの runInterval() です。これは、関数と間隔(int)を引数とすることで、名前の通り、一定周期で関数を実行することができます。上のように間隔を明記しない場合は常に実行します。常にプレイヤーの動きを監視するのにも使えます。ジャンプしたらkillされるAPI Script:
にもこの関数が使われていますね。
ちなみに、「常時実行」と言えば、functionsファイル内の tick.json を想起させます。ご存じのない方に向けて一応説明しますと、tick.jsonはワールド内で常時実行される関数スクリプト(一連のコマンド群で、mcfunction形式で記述されたもの)を定義します。このtick.jsonを用いることでも簡単に常時実行を達成することはできますが、こちらはあらかじめ定義されたコマンドしか使えないので一長一短です。必要に応じてrunInterval()とtick.jsonを使い分ける感じですね。
各プレイヤーについて実行
マインクラフトの主人公は、プレイヤーです。このプレイヤーを主体として何かを実行したいときもありますよね。そんな時に重宝するフレーズがあります。
for (const player of server.world.getAllPlayers()){
//ここに内容を記述
}
それが、
for (const player of server.world.getAllPlayers())
というもの。worldクラスのgetAllPlayers()関数は、ワールド内にいる全プレイヤーを取得し、配列形式で出力します。したがって、各プレイヤーについて何かを処理したいときは、これとfor文を組み合わせれば良いのです。ちなみに、プレイヤーの名前を取得したいときは、player.nameでOKです。
for文の中では、同時に変数playerを宣言しています。このplayerは、playerクラスを有し、コマンドを実行したり(注:下記も参照のこと)、イベント処理をしたりと大きな役割を担います。
コマンド実行
マインクラフトのコマンドは非常に優秀で、大抵のことはコマンドで成し遂げられます。そんなコマンドをAPI Scriptの味方につければ正に鬼に金棒。API Script上でコマンドを実行するにはどうすればよいでしょうか?
その答えを握るのが、 runCommand()関数 です。しかし利用できる状況が限られます。というのも、このrunCommand()関数、クラスがdimensionまたはplayerでないと使えないのです。なので、回りくどいですが、実践的には以下のように使われます。
//ディメンションクラスで実行する例
server.world.getDimension("overworld").runCommand("give @a diamond 3")
//プレイヤークラスで実行する例
for (const player of server.world.getAllPlayers()){
player.runCommand("give @a 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()を使うとうまくいくことが偶にあります(経験則)。
手に持っているアイテムを取得
先日のアップデートで、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チャンネルでもまとめていますので、お時間が宜しければ是非ご覧ください。その他、技術的な視点からマインクラフトに関する情報を発信しています。