はじめに
マインクラフトというゲームは、非常に自由度が高いゲームです。普通にサバイバルをしてエンドラ討伐に至るもよし、建築を極めて芸術性の高い作品を作るもよし、コマンドを使って配布マップを作成するもよし。まさに、無限の可能性を秘めています。
さて、アドオン制作はこうした自由度の増大に拍車をかけます。自分自身のオリジナルのアイテムや武器の制作はもちろん、システムをカスタマイズして配布マップを作ることだってできるのです。以下はその一例で、某ゲームに登場する「一撃の剣」をマインクラフトで再現したものです。
このアドオン制作は、単なるアイテムの創造・システムの改変にとどまりません。意外と知られていないのですが、独自のGUIを作成することもできます。本記事では、独自のGUIを作成する方法について一から解説し、アドオン制作の補助となることを目的とします。
これは私の制作動画の一コマで、「マック」と「マクド」のどちらが好きであるかを尋ねるGUIが表示されています。本記事を読むことで、このようなGUIを作成し、オリジナルの世界観を構築することができます。是非、最後までご覧ください。
Youtube動画
本記事の内容について解説したYoutube動画を制作しました。こちらより視聴できます。
語彙の定義
まず、簡単に本記事で頻出する主な用語の定義を説明します。これらが私が独自の解釈によって説明したものですので、もし間違っている場合にはご指摘ください。既にご存じの場合は飛ばしてください。
用語 | 意味 |
関数 | ある入力に応じて一意の出力を行うプログラム |
モジュール | プログラムを動作させるための要素・部品 |
JavaScript | プログラミング言語の一種で、主にWebページ上で用いられる |
GUI | Graphical User Interfaceの略。感覚的・直感的に操作できるようにしたもの。 |
本題
GUIの制作にあたっては、APIScriptの使用が必須となります。APIScriptとはJavascriptというプログラミング言語を用いてマインクラフトのシステムをカスタマイズすることができる機能のことです。APIScriptについてはこちらの記事が詳しいです。
本記事では、最初にAPIScriptの環境構築について説明します。既にご存じの場合はこの節を飛ばしてください。
環境構築
まず、環境構築にあたって必要なものを提示します。以下のリンクよりそれぞれをダウンロードできます。
必要なソフト名 | ダウンロード先 | 備考 |
Minecraft | amazon | 言わずと知れたゲームソフト。Win10版が望ましい。 |
vscode | https://code.visualstudio.com/ | コードの記述に特化したテキストエディタ(無料)。既に別のテキストエディタを持っている場合は不要。 |
node.js | https://nodejs.org/ | javascriptをパソコン上で実行するためのツール(無料)。ダウンロード後、msiファイルを実行。 |
必要なソフトのうち、Minecraftのみ有料で、その他は無料です。テキストエディタ(vscode)はなくても最悪できますが、あったほうが断然望ましいです。また、ScriptAPIはjavascriptに依存するので、このjavascriptをPC上で実行するためのnode.jsは必須です。
node.jsについては、別の方の記事ですが、こちらが非常に参考になりました。一応紹介いたします。
https://qiita.com/non_cal/items/a8fee0b7ad96e67713eb
以下では、これらのインストールを前提に、手順について説明します。
まず、com.mojangフォルダ内のdevelopment_behavior_packs内に移動し、新規にフォルダを作成します(名前は何でもいいです)。これがアドオンの作業フォルダとなります。com.mojangフォルダの場所については以下で説明します。既にご存じの場合は読み飛ばしてください。
com.mojangの場所
フォルダcom.mojangは
C:\Users\(ユーザー名)\AppData\Local\Packages\Microsoft.MinecraftUWP_8wekyb3d8bbwe\LocalState\games\com.mojang
に存在します。エクスプローラー上で、「AppData」というファイルは隠しファイルなので、これを選択するためには、エクスプローラーの「表示」設定から隠しファイルのチェックをオンにしてください。または、「ファイル名を指定して実行」というアプリを起動し、
「%LocalAppData%\Packages\Microsoft.MinecraftUWP_8wekyb3d8bbwe\LocalState\games\com.mojang」
と入力することでも開けます。
このcom.mojangの中にdevelopment_behavior_packsフォルダが存在するので、これを開いて新規にフォルダを作成してください。
manifest.jsonの作成
次に、新規に作成したアドオンのフォルダ内に移動し、「manifest.json」というjsonファイルを新規作成してください。右クリックして「新規作成」→「テキストドキュメント」を選択し、作成されるファイルの名前を「manifest.json」に変更すればOKです。
「manifest.json」はこのアドオンの要項(名前やidなど)を記述したファイルで、これによってマインクラフトがアドオンを認識できるようになります。
manifest.jsonの内容は以下の通りです。作成したmanifest.jsonを、先ほどダウンロードしたvscodeなどを用いて開き、以下をコピー&ペーストしてみましょう。
{
"format_version": 2,
"header": {
"name": "GUIを表示するアドオン",
"description": "これはテンプレートです",
"uuid": "b1ef9620-a18e-4fa3-bdca-f5f1d3c71c31",
"version": [0, 1, 0],
"min_engine_version": [1, 20, 0]
},
"modules": [
{
"type": "script",
"language": "javascript",
"uuid": "b1ef9620-a18e-4fa3-bdca-f5f1d3c71c32",
"entry": "scripts/main.js",
"version": [0, 1, 0]
}
],
"capabilities": ["script_eval"],
"dependencies": [
{
"module_name": "@minecraft/server",
"version": "1.10.0"
},
{
"module_name": "@minecraft/server-ui",
"version": "1.1.0"
}
]
}
上のnameやdescriptionはこのアドオンの名前・説明文です。この部分をアレンジしてお使いください。また、2か所あるuuidはアドオン固有の文字列で、重複すると面倒なことになるので以下のジェネレーターを用いて生成・変更することをお勧めします。
minecraft/serverのバージョン(ここでは1.10.0)ですが、以下のページを参考に変更しても良いかもしれません。執筆時点の最新は1.14.0-betaですが、ベータ版は挙動が不安定なので、安定を取る場合は1.13.0を用いることになるでしょうか。なお、ベータ版を使用する際はワールドの起動時に実験的な機能の「ベータAPI」をオンにする必要がある点に留意しましょう(ベータ版不使用時は不要)。
また、本アドオンではUIの表示を行う都合上、server-uiのモジュールの明記が必要です。今まで本サイトで紹介していた他のアドオンとは一線を画すので注意しましょう。
「@minecraft/server」のインストール
続いて、本アドオンでお世話になる「@minecraft/server」モジュールとUIの表示に必須となる「@minecraft/server-ui」のインストールを行います。タスクバーの検索欄に「cmd」と入力してコマンドプロンプトを起動するか、vscodeのターミナルを起動しましょう。そして、
cd (作業フォルダのパス)
というコマンドを入力します。cdコマンドは、ディレクトリを指定することでディレクトリを移動することができるコマンドです。例えば、アドオンのフォルダ(manifest.jsonがあるフォルダ)が、
C:\Users\User\AppData\Local\packages\Microsoft.MinecraftUWP_8wekyb3d8bbwe\LocalState\games\com.mojang\development_behavior_packs\test_pack
であった場合は、
cd C:\Users\User\AppData\Local\packages\Microsoft.MinecraftUWP_8wekyb3d8bbwe\LocalState\games\com.mojang\development_behavior_packs\test_pack
となります。フォルダの場所(特にユーザー名)は各自異なるので、ご自身でパスを確認してください。エクスプローラーの上部欄より確認できます。
上記のコマンドの入力が完了したら、続いて以下の2つのコマンドの入力を行いましょう。
npm install @minecraft/server
npm install @minecraft/server-ui
コマンド「npm」に関してエラーが発生した場合、node.jsのインストールが完了していない可能性があります。エラーが発生している場合はこの点を確認してみることをお勧めします。
スクリプトを記述
以上が完了したら、いよいよ準備は整いました。次に、UIを作成していきます。
アドオンのフォルダ内で「scripts」というフォルダを作成しましょう。そしてその中に「main.js」というjavascriptのファイルを作成します。ここにスクリプトを記述することになります。このjsファイルは、vscodeを始めとするテキストエディタで開くことができます。
モジュールの呼び出し
まずは、先ほどインストールした2つのモジュールをこのスクリプト内に呼び出します。これによってマインクラフトの世界に干渉できるようになり、さらにUI表示の準備が整います。
以下をコピーしてmain.js内に貼り付けましょう。
import * as server from "@minecraft/server";
import * as ui from "@minecraft/server-ui";
このスクリプト中における「*」の記号は、そのモジュールのすべてをインストールすることを表します。クラス(playerやworldなど)ごとに必要なものをインストールしても良いのですが、少々煩雑で手間だと考え、すべてをインストールしました。ここはお好みでどうぞ。参考までに、以下は@minecraft/serverのうちのworldクラスとsystemクラスのモジュールだけをインストールする例です。(これはスクリプト内に記述する必要はありません)
import {world,system} from "@minecraft/server";
UIの定義
次に、表示するUIの定義を行います。以下は、playerを引数としてUIを表示する関数であるshow_form()を定義する例です。
function show_form(player){
const form = new ui.ActionFormData();
form.title("選択メニュー あなたはどっち派?");
form.button("マック");
form.button("マクド");
form.show(player).then((response) => {
switch(response.selection){
case 0:
player.sendMessage("マックを選択しました。");
player.runCommandAsync("give @s emerald 1");
break;
case 1:
player.sendMessage("マクドを選択しました。");
break;
default:
player.sendMessage("何も選択していません。");
break;
}
}).catch(error =>
player.sendMessage("An error occurred: " + error.message)
);
}
少し解説を行います。form.title()はこのUIのタイトルを定義する関数です。ここにタイトルを入力することで、アレンジができます。また、formクラスのbutton()関数によってボタンを配置しています。これは文字列を引数とし、引数の文字列をボタン上に配置します。ご覧いただくと明らかですが、これは複数配置することが可能です。
最後のshow()関数によってこのUIを表示することが可能になります。また、show()以下でボタンを押した際の挙動を定義することができ、ここではそれぞれのボタンを押したときの挙動を定義しています。同時に、メッセージを表示する関数である「sendMessage()」と、コマンドを実行する関数である「runCommandAsync()」を用いています。これらはよく使われるので覚えておいて損はないでしょう。
参考
「case 0」や「case 1」という表記がみられますが、これはswitch文と呼ばれるもので、javascriptにおいて場合分けを行う際によく用いられます。ここでは変数responseの値によって、挙動を場合分けしています。このresponseの値は、一番上のボタンを押した際に0に、次のボタンを押した際に1になり、以下同様です。何も押さなかった場合は「default」が代入されます。
また、エラーが発生した場合の挙動も設定することができます。それがcatch()というもので、javascriptにおいてはしばしば用いられます。この設定は必須ではないです。
さて、これで終わりかと思いきや、そうではありません。これはUIを表示する関数を定義しただけで、実際にUIを表示する命令を出していません。これとは別に、定義した関数を実行してUIを表示する命令を出す必要があります。
UIの表示
上記で定義した「show_form()」関数を呼び出せばUIは表示されますが、ただ表示すればいいというものではありません。常にゲーム内にUIが出ていたら邪魔で仕方がないですからね。即ち、特定の条件でUIを出すというシステムを実装する必要があります。
以下は、「木の棒を使った時」にshow_form()を呼び出してUIを表示する例です。
server.world.afterEvents.itemUse.subscribe(ev => {
if (ev.itemStack.typeId == "minecraft:stick"){
let player = ev.source;
show_form(player);
}
});
一つ補足します。この関数show_formは引数としてplayerを指定することが条件ですので、事前にアイテムの使用者を変数「player」に代入し、宣言しています。このように、何らかの方法で引数playerを用意しておく必要がある点に留意しましょう。このplayerを起点に関数が実行されます。
なお、アイテム使用時に何らかの挙動を起こす方法についてはこちらの記事が詳しいです。併せてご覧ください。
なお、ここではアイテムの使用をトリガーするためにafterEventsプロパティを使用していますが、ここでbeforeEventsプロパティを使用するとエラーが発生します。この点についてはこちらの記事で言及しています。
実行
これでスクリプト上でのUIの定義が完了しました。後は実際にマインクラフトを起動して、挙動を確かめるのみです。このアドオンを有効化してワールドを起動してみましょう。すると、棒を使うとUIが表示されるようになるはずです。
また、この例では「マック」を選択するとエメラルドが与えられます。このように選択に応じて何らかの結果がもたらされることが確認できるでしょう。
ModalFormData
さて、UIの表示において、重宝する関数があります。それが、ModalFormDataと呼ばれるもので、これを使えばボタンの配置のみならず、テキストボックスやチェックボックスの配置などが可能になります。これによって、非常に柔軟性・拡張性に優れたアドオンを制作することができるようになります。
上の画像は、私の制作した動画の1フレームですが、スライダーやドロップダウンなど、様々な入力欄が存在することが確認できるでしょう。
Youtube動画
こうしたフォームの制作方法については、こちらの動画で詳細に解説しております。こちらも併せてご覧ください。
ここでは、簡単なスクリプトの紹介のみにとどめます。
スクリプト
以下は、ModalFormDataを用いて各種機能を搭載する例です:
function show_form(player){
const form = new ui.ModalFormData();
form.slider("スライダー",0,100,1,50);
form.textField("ここにテキストを入力","テキスト");
form.dropdown("ドロップダウン",["a","b","c"]);
form.toggle("チェックボックス");
form.show(player).then(response => {
if (response.canceled){
player.sendMessage("キャンセルされました");
return;
}
player.sendMessage("スライダーの値:" + String(response.formValues[0]));
player.sendMessage("テキストの入力:" + String(response.formValues[1]));
player.sendMessage("ドロップダウンの選択:" + String(response.formValues[2]));
player.sendMessage("チェックボックスの状態:" + String(response.formValues[3]));
})
.catch(error => {
player.sendMessage("エラー: " + error.message);
});
}
なお、動画内とスクリプトが若干異なりますが、大枠は一緒です。ここではsendMessage関数を使って入力されたデータをString型にした後出力する程度のシンプルなシステムしか定義していないのですが、実際は以下のように、runCommand関数などと組み合わせて柔軟な処理を行うことになるかと思います。
例1
以下は、スライダーの値に合わせてプレイヤーにダイアモンドを付与する例です:
player.runCommand("give @s diamond " + String(response.formValues[0]));
また、同様にプレイヤーのスコアを一定値に設定することもできます:
player.runCommand("scoreboard players set @s test_score " + String(response.formValues[0]));
例2
上記動画のコメント欄の質問で多かったのが、「ドロップダウンにプレイヤー名を表示するにはどうすればよいのか」というものでした。以下は、それを実装する関数の例です:
function generate_player_list(){
let player_list = [];
for (const player of server.world.getAllPlayers()){
player_list.push(player.name);
}
return player_list;
}
この関数を定義後、以下のようにdropdown関数内で用いることで、プレイヤー名の入ったドロップダウンを定義できます:
form.dropdown("ドロップダウン",generate_player_list());
逆に選択されたプレイヤー名を出力するのもひと手間必要です。本来、ドロップダウンの出力は値ではなく数字になるので、その数字から値に戻す必要があるからです。以下は、それを実装する例です:
let players = server.world.getAllPlayers();
for (let i = 0; i<= players.length; i++){
if (response.formValues[2] == i){
player.sendMessage("選択したプレイヤー: " + players[i].name);
}
}
おしまい
本記事では、APIScriptを用いてマインクラフトでUIを表示する方法について解説しました。UIが表示できるとアドオンの拡張性・自由度がかなり上がるので、皆さんも試してみてください。
アドオンの基本についてはこちらの記事が詳しいです。
また、よく使うAPIScriptのフレーズについてはこちらが詳しいです。
次の記事はこちら: