はじめに
先日の「ホリデークリエイターの特徴」の削除に伴って、オリジナルアイテムを使用した際の挙動をjsonファイル上で制御することができなくなりました。従って、使用可能なアイテムを作る場合、ScriptAPIの使用が前提となります。
ScriptAPIとは、javascriptというプログラミング言語を用いてゲームシステムをカスタマイズすることができる機能のことです。本アップデートに関する詳細については、こちらの記事をご覧ください。
しかし、ScriptAPIの使用にあたっては、事前準備や基礎知識が必要です。ScriptAPIについてよくご存じでない方は、本記事を閲覧する前にこちらの記事に目を通していただくことをお勧めします。
以下では、APIScriptについてご存じであることを前提に、どんなアイテムでも使用可能にする方法についてお話しします。
Youtube動画もあります
本記事の内容について詳細に解説したYoutube動画を制作しました。こちらから視聴できます。本動画では、キャラクターの掛け合い形式で分かりやすく説明することを目的としていますので、テキスト形式の情報が苦手な方は是非こちらもご覧いただくと理解が深まるかもしれません。
概要
SciptAPIのテンプレートをご使用の場合は、scriptフォルダ内のmain.jsを開いてください。まずは、いつも通り、import文を記述します(この文が既に存在する場合はこの処理は不要です)。
import * as server from '@minecraft/server';
これによって、マインクラフトのモジュールを定義する変数serverの宣言が完了しました。以下でこのserverを用いていきます。
スクリプトを記述
いよいよ、スクリプトを記述していきます。任意のアイテムを使用可能にするにあたって、以下のプロセスを経てこれ実装しましょう。
例えば動画内にある通りの、「木の棒を使用したらダイアモンドが入手可能」というスクリプトは以下のようになります。
server.world.beforeEvents.itemUse.subscribe(ev => {
if (ev.itemStack.typeId == "minecraft:stick"){
ev.source.runCommandAsync("give @a diamond 1");
}
})
先のimport文のすぐ下にこの文章をコピー&ペーストしましょう。
このスクリプト自体は前の記事で登場していますが、本記事ではこのスクリプトに関して詳細な解説を行います。
解説
マインクラフトのモジュールにはworldクラスのbeforeEventsクラスが存在します。これは、ワールドにおける様々なイベントをトリガーし、イベントが起きたときに関数を起こすものです。これはScriptAPIにおいて非常によく使われるので、覚えておきましょう。今回は、その中のitemUseクラスを使用してアイテムが使用されたことを検知し、関数を発火させています。subscribe()関数は、ある関数の実行を約束するものです。このカッコの中に関数の内容を記述していきます。
関数の名前は、上記にある通り、ev(「event」の頭文字)です。
if文の中にあるev.itemStack.typeIdは、使用されたアイテムのidです(String型)。今回は、これがminecraft:stickと等しい場合にtrueが返され、次の処理に進みます。
ev.sourceは、イベントを起こしたエンティティです。今回は、棒を使用したプレイヤーですね。このエンティティの下で、runCommandAsync()関数でコマンドを実行します。今回はgiveコマンドとしました。これによって、棒を使用した際にダイアモンドが与えられます。
上記の「minecraft:stick」や「give @a diamond 1」の部分を変えることでお好みにアレンジできます。これによって、任意のアイテムを使用可能にできるわけですね。
クールダウンを実装
本記事はここで終わりません。というのも、Youtube動画のコメントを見ていると、クールダウンに関して需要があるように感じたので、本記事ではさらに使用可能なアイテムにクールダウンを実装する方法について解説します。
そもそも、「クールダウン」とは「一度アイテムを使ったら一定時間は使えなくなる」仕組みのことです。これを実装するには、以下のようなアプローチが取り得ます。
今回は、runInterval()関数を用いた方法で考えていきましょう。tick.jsonについては別の動画&記事で解説します。スクリプトは以下のようになるでしょうか。
let cooldown_time = 3
let item_name = "minecraft:stick"
let command = "say hello!"
server.world.beforeEvents.itemUse.subscribe(ev => {
if (ev.itemStack.typeId == item_name){
ev.source.runCommandAsync("execute as @s[scores={test_score=0}] run " + command);
ev.source.runCommandAsync("execute as @s[scores={test_score=0}] run scoreboard players set @s test_score " + cooldown_time*20);
}
});
server.system.runInterval(ev => {
for (const player of server.world.getAllPlayers()){
player.runCommandAsync("scoreboard objectives add test_score dummy");
player.runCommandAsync("scoreboard players remove @s[scores={test_score=0..}] test_score 1");
player.runCommandAsync("scoreboard players set @s[scores={test_score=..-1}] test_score 0");
}
}
);
これは、木の棒を使用した際に「say hello!」というコマンドを実行する例です。クールダウン時間は3秒で、最後に使用した瞬間から3秒が経過しないとコマンドは実行されません。
上記のcooldown_timeやitem_name、commandを自由に変えてアレンジしてみてください。
解説
このスクリプトは大きく2つに分かれています。前半はアイテムの使用時に発火する関数を定義し、これは前のスクリプトと大きくは変わりません。一つ異なる点はアイテムを使用した際にscoreboardコマンドを使用してスコアを加算していることだけですね。
後半では常に実行される関数を定義しています。ここでは主にscoreboardコマンドを用いて、毎ティックスコアを1ずつ減らす機能を担っています。
使用を制限
最後に、アイテムの使用を制限する方法について解説します。これまでは、アイテムを右クリックすると必ずコマンドが発動しました。しかし、場合によっては、特殊な条件においてのみコマンドを実行したいこともあります。あるいは、一つのアイテムに2つの機能を持たせたいこともあるでしょう(実際、私はそう思うことがよくあります)。このような状況を想定し、ここではプレイヤーがある特定の条件にある場合にコマンドを発動する例を示します。
server.world.beforeEvents.itemUse.subscribe(ev => {
if (ev.itemStack.typeId == "minecraft:stick"){
if (ev.source.isSneaking == true){
ev.source.runCommandAsync("say Hello!");
}
}
});
これは、棒を使用していた時にスニークしていたら「say Hello!」というコマンドが発動する例です。このように、アイテムの使用条件を設定することもできるんですね。
上記のアイテムのidやコマンドを変えることで、お好みでアレンジできます。
また、同様にスニークしていない場合の処理を設定することで1つのアイテムに2つの機能を搭載することができます。以下はその例です。
server.world.beforeEvents.itemUse.subscribe(ev => {
if (ev.itemStack.typeId == "minecraft:stick"){
if (ev.source.isSneaking == true){
ev.source.runCommandAsync("say Hello!");
}else{
ev.source.runCommandAsync("say I'm standing!");
}
}
});
これは、スニークしている時は「Hello!」と発し、そうでない時は「I’m standing!」と発する例です。このように、if~else~文を用いた条件分岐によって、アイテムに複数の機能を持たせることができます。
条件の例
ここでは、「スニークしているか否か」という事実を判定しました。これは、isSneakingプロパティがスニークしている場合はtrueを、そうでない場合はfalseを返すためです。このような性質を持つ、主なプロパティとして以下が挙げられます。
isInWater | 水の中にいるかどうか |
isOnGround | 足が地についているか |
isSleeping | 眠っているかどうか |
isSneaking | スニークしているかどうか |
isSwimming | 泳いでいるかどうか |
isFlying | (クリエイティブで)飛んでいるかどうか |
isJumping | ジャンプしているかどうか |
これらを組み合わせて、独創的なアイテムを作るのもありでしょう。
おしまい
ここでは、ScriptAPIを用いてアイテムを使用可能にする方法について解説しました。ScriptAPIについては以下の記事も詳しいので、こちらもご参照ください。