事前説明
こんにちは、さば2号です。
今回はScriptAPIのUIについて解説していきます。
事前準備、アドオンフォルダの作成、manifestの書き方は前回の解説をご覧ください。
【統合版】ScriptAPIでアドオンを作ってみよう #1 ダメージメッセージ
注意事項
・この記事は2024/03/26時点のものです。
・投稿者は素人です。間違えることがあります。
解説
ScriptAPIでは3つのフォームのUIを作成できます。
今回はボタンの選択肢を設定できる、ActionFormの解説をしていきます。
公式リファレンス ActionFormData Class
さっそくサンプルのフォームを作っていきましょう。
今回は次のようなフォームを作ります。
フォームを開く方法
・「フォームを開く」という棒のアイテムを使う
閉じられた(キャンセルされた)とき
・「キャンセルしました」とメッセージを送る
ボタンが押されたとき
・「〇番目のボタンを押しました」とメッセージを送る
import { world } from "@minecraft/server";
// フォームのインポート
import { ActionFormData, MessageFormData, ModalFormData } from "@minecraft/server-ui";
// アイテムを使用すると起動
world.afterEvents.itemUse.subscribe(ev => {
// 定数「player」にアイテム使用者(ev.source)を代入
const player = ev.source;
const itemStack = ev.itemStack;
// アイテムの種類が棒(minecraft:stick) かつ アイテムの名前が「フォームを開く」の場合
if (itemStack.typeId === "minecraft:stick" && itemStack.nameTag === "フォームを開く") {
// アクションフォームのを生成
const form = new ActionFormData();
// フォームの設定
form.title("タイトル");
form.body("ボディ");
// ボタンの追加
form.button("0番目のボタン");
form.button("1番目のボタン");
form.button("2番目のボタン", "textures/items/apple");
form.button("3番目のボタン", "textures/blocks/stone");
// フォームをプレイヤーに表示
form.show(player).then(response => {
// ここから下はフォームが送信される または フォームが閉じられると処理が始まる
// response - フォームの結果のデータ
// response.canceled - フォームをキャンセルした(閉じた)かどうか
// response.selection - 押したボタンの番号 (0から始まる)
if (!response.canceled) { // フォームをキャンセルしてない場合
// 押したボタン番号を送る
player.runCommand(`say ${response.selection}番目のボタンを押しました`);
} else { // キャンセルした場合
player.runCommand("say キャンセルしました");
}
});
}
});
サンプルコード:コマンドフォーム
今度は実用的なフォームを作ってみましょう。
フォームを開く方法
・「OP」タグを持っているプレイヤーが「コマンドフォーム」という棒のアイテムを使う
閉じられた(キャンセルされた)とき
・なにもしない
ボタンが押されたとき
・ボタンに応じてコマンドを実行する
import { world } from "@minecraft/server";
import { ActionFormData, MessageFormData, ModalFormData } from "@minecraft/server-ui";
world.afterEvents.itemUse.subscribe(ev => {
const player = ev.source;
const itemStack = ev.itemStack;
// アイテムの種類が棒(minecraft:stick) かつ アイテムの名前が「コマンドフォーム」の場合
if (itemStack.typeId === "minecraft:stick" && itemStack.nameTag === "コマンドフォーム") {
// プレイヤーがopタグを持っていたら
if (player.hasTag("op")) {
// フォームの生成と設定
const form = new ActionFormData();
form.title("コマンドフォーム");
form.button("アドベンチャーに変更");
form.button("クリエイティブに変更");
form.button("ロビーにTP (0,0,0)");
form.button("アイテムクリア");
// フォームをプレイヤーに表示
form.show(player).then(response => {
// response.canceled - フォームをキャンセルした(閉じた)かどうか
// response.selection - 押したボタンの番号 (0から始まる)
// フォームをキャンセルしていない場合
if (!response.canceled) {
// 選んだボタンによってコマンドを実行する
// <Player>.runCommand("command") - プレイヤーがコマンドを実行する
if (response.selection === 0) { // 0のとき
player.runCommand("gamemode a @s");
} else if (response.selection === 1) { // 1のとき
player.runCommand("gamemode c @s");
} else if (response.selection === 2) { // 2のとき
player.runCommand("tp @s 0 0 0");
} else { // 3のとき
player.runCommand("clear @s");
}
}
});
// タグを持っていない場合
} else {
// <Player>.sendMessage("message") - プレイヤーにメッセージを送る
player.sendMessage("opタグを持っていません。");
}
}
});
サンプルコード:コマンドフォーム(async/await,メソッドチェーン,switchを使用する場合)
これは上で作ったコマンドフォームを、さらに簡略化したプログラムです。
import { world, system } from "@minecraft/server";
import { ActionFormData, MessageFormData, ModalFormData } from "@minecraft/server-ui";
world.afterEvents.itemUse.subscribe(ev => {
const player = ev.source; const itemStack = ev.itemStack;
if (itemStack.typeId === "minecraft:stick" && itemStack.nameTag === "コマンドフォーム") {
if (player.hasTag("op")) {
showCommandForm(player);
} else {
player.sendMessage("opタグを持っていません");
}
}
});
// コマンドフォームを表示する関数
async function showCommandForm(player) {
// メソッドチェーンでまとめて定義
const form = new ActionFormData()
.title("コマンドフォーム")
.button("アドベンチャーに変更")
.button("クリエイティブに変更")
.button("ロビーにTP (0,0,0)")
.button("アイテムをクリア");
// フォームの表示と結果の代入
const res = await form.show(player);
// もしキャンセルされていたら、return;で処理を終了する
if (res.canceled) return;
// 押されたボタンに応じてコマンドを実行
switch (res.selection) {
case 0:
player.runCommand("gamemode a @s");
break;
case 1:
player.runCommand("gamemode c @s");
break;
case 2:
player.runCommand("tp @s 0 0 0");
break;
case 3:
player.runCommand("clear @s");
break;
}
}
参考URL
公式リファレンス
minecraft/server Module | Microsoft Learn
ディスコードサーバー
Script API 開発初心者コミュニティ
参考にしたサイト
マイクラの泉
コメント
質問失礼します。こちらの記事を参考に、作ってみたのですが、フォームが表示されなくて、原因分かりますか?
import { world } from “@minecraft/server”;
import { ActionFormData, MessageFormData, ModalFormData } from “@minecraft/server-ui”;
world.afterEvents.itemUse.subscribe(ev => {
const player = ev.source;
const itemStack = ev.itemStack;
// アイテムの種類がコンパス(minecraft:compass) の場合
if (itemStack.typeId === “minecraft:compass”) {
const form = new ActionFormData();
form.title(“§l§bServer menu”);
form.button(“§l§aback to lobby”);
// フォームの表示
form.show(player).then(response => {
if (response.canceled === false) {
// 選んだボタンによってコマンドを実行する
if (response.selection === 0) {
player.runCommand(“tp @s 0 1 0 0 0”);
}
}
});
コンテンツ ログに[main.js] run with error: [SyntaxError: unexpected token in expression: “ at main.js:23 とエラーが出ています。
返信お願いします。
返信してください。お願いします。
次の括弧がないためエラーとなっているようです。
4行目のsubscribe(ev => { の終わりの括弧 });
9行目のif (itemStack.typeId === … の終わりの括弧 }
一部コードを変更し、説明を加えました。