【統合版アドオン】究極の機能、ScriptAPIを徹底解説!

スポンサーリンク

初めに

こんにちは、餅わらびすとです。この記事では、ScriptAPI(gametestとも言う)というものを解説します。

ScriptAPIというのは、JavaScriptという言語を使いプログラムしていく、マイクラアドオンの機能です。
複雑な計算、イベントのデータを読み取っての処理…コマンドやJSON系の要素だけではできない機能がたくさんあり、アドオンの幅を広げてくれます。プラグインのようなことも実現可能!

少しでもお役に立つ記事となれば幸いです。

目次
  • マニフェスト
  • ベータバージョン
  • JavaScript
  • リファレンスの読み方
  • よく使われる機能
  • エラー
  • 最後に

~個人的おすすめテキストエディタ~


~前提知識~

  • JSONの構造、用語
  • 基本的な記号の名称
  • マイクラアドオンの基本的知識

マニフェスト

まず、ScriptAPIを使う際にはマニフェストを変える必要があります。

サンプルコードです。

{
    "format_version": 2,
    "header": {
        "name": "ビヘイビアテストBP",
        "description": "ビヘイビアテストBP",
        "min_engine_version": [1,21,10],
        "uuid": "d8229b16-c69a-40f3-baa6-926f96a5ca6c",
        "version": [1,0,0]
    },
    "modules": [
        {
            "type": "data",
            "uuid": "81344285-81fc-44b7-b8da-6f6f61288c4b",
            "version": [1,0,0]
        },
        {
            "type": "script",
            "language": "javascript",
            "uuid": "440ac9d1-d6f8-4eff-a5aa-29ed51b893f5",
            "entry": "scripts/main.js",
            "version": [1,0,0]
        }
    ],
    "dependencies": [
        {
            "module_name": "@minecraft/server",
            "version": "1.15.0"
        }
    ]
}

modules

ScriptAPIを使うマニフェストは、使わないマニフェストと違い、typeがdataのオブジェクトに加えて新しくtypeがscriptのオブジェクトが入っています。
新しいオブジェクトといっても、中のuuidを変える以外はほぼコピペでok。
ただ、entryは実行したいファイルの場所に合わせましょう。

dependencies

ここでは変数や関数などをまとめたモジュールというものの、種類やバージョンを指定するオブジェクトが入っています。
主に使われるモジュールは、ワールドに関する操作ができる@minecraft/server、uiに関する操作ができる@minecraft/server-uiの2つです。
バージョンは複数存在しており、その中でも今回は、最終確認時マイクラバージョン1.21.44時点で最新の安定版バージョンである1.15.0を指定しています。バージョンはアップデートに伴い増えていきますが、過去のバージョンが使えなくなるわけではないので、毎回のアップデートでバージョンを更新する必要はありません。

ベータバージョン

scriptapiには、ベータバージョンという実験段階のものがあります。安定版とは違いアップデートで毎回変更されるので注意。マイクラバージョン1.21.44では1.16.0-betaが使えます。

ベータバージョンの魅力は、実験段階の最新機能がいち早く体験できる点にあります。
ワールド内のチャットを監視できるChatSendAfterEvent(ChatSendBeforeEvent)や、ワールド参加プレイヤーのデバイスについての情報が取得できるClientSystemInfoがその一例です。

このベータバージョンは、モジュールバージョンを

<使いたいベータバージョン>-beta

とし、ワールドの実験機能の設定からベータAPIを有効にすることで利用できます。minecraft previewなどのマイクラ自体のプレビューは必要ありません。

モジュールのバージョンが追加される際はアップデートでの変更ログにその内容が記載されているので、アップデートされたらこまめに確認しておきましょう。

(2.0.0-alphaを指定すれば常に最新のベータが適応されるという術もあると聞く)

JavaScript

準備はできた、早速コードを書いていこう!と言いたい流れではありますが、その前に、ScriptAPIで使われるJavaScriptというプログラミング言語の文法を覚えておきましょう。
ScriptAPIはJSON系の要素とは違って書き方は無限にあります。最悪6種類の記号だけで書くことも可能。
つまりは、文法を覚えなければ応用活用が利かないということです。外国語を話せるようになりたいからといって、この世に存在しうる会話を全て暗記しようと考える人はまず居ないでしょう。そういうことです。

ただ、ここで伝えるのはあくまでも最低限の基礎なので、これで完璧なコードを書けるようになるかと言えば微妙です。少し複雑な処理をしたい時や今回紹介したことのもっと詳しい仕様を知りたいという時は、サイトやYouTube、生成AIなんかに聞きましょう。(生成AIにScriptAPIはほとんど書けないので、ScriptAPIとしてではなくJavaScriptとしての質問をするのがおすすめ)

1. コメント

jsでは、コメントは

//このようにスラッシュをコメントにしたいところから2つつけるか、

/* スラッシュとアスタリスクで囲むとできます。 */

/**
 * 複数行にわたって
 * 書くこともできます
 */

コメントをするとコメントをした範囲がコードとして認識されなくなるため、処理のメモに使えます。

2. データ型

プログラミングにおいて、データには種類があります。ScriptAPIでよく使われるものは

・string(文字列)
・number(数値)
・boolean(真偽値)
・object(オブジェクト)
・undefined(未定義)

の5つです。


stringは、“このようにダブルクォーテーションか,シングルクォーテーションで囲むことにより”   表すことができます。

+で2つの文字列を合わせる、といったことも可能です。(例:”あいさつは” + “大事だよ”)


numberは、そのまま0や100のようにして表せます。

+(加算) -(減算) *(乗算) /(除算)などの”演算子”で計算ができます。(例: 1 + 2 は3を返す式)


booleanは、trueとfalseで表すことができます。

はい と いいえ のようなもの。


objectは、[]で囲まれたものと{}で囲まれたものがあります。

[]で囲まれたものはArray(配列)と呼ばれ、コンマで区切って複数のデータを入れることができます。(例:[“1つ目”, 2, 2 + 1])そして、その中のデータは要素と呼ばれます。
それらは、オブジェクトの名前[番号]で取り出せます。番号は0から始まるので注意。頭の中ではオブジェクトの名前[番号 – 1]と考えておくと楽。

{}で囲まれたものは、「プロパティ」と呼ばれるものにデータを入れることができます。

//例
{ 
    apple: "red",
    grape: function() {
        world.sendMessage("purple");
    }
}
//こうでもok
{ apple: "red", grape: function() { world.sendMessage("purple"); } }

appleがプロパティの名前(keyという)で、grapeがメソッド(プロパティに関数を入れたもの)の名前です。

プロパティは、オブジェクト名.プロパティ名で取得でき、メソッドはオブジェクト名.メソッド名()で呼び出せます。
オブジェクト名[プロパティ名(文字列)]という書き方もあったり。


undefinedは、値が定義されていないものなどに入っている値です。

例えば、未定義の変数にはundefinedが入っています。

3. 定数・変数

データを自分の決めた名前で保存することができます。

//定数の宣言
const 定数の名前 = 入れたいデータ;

//変数の宣言
let 変数の名前 = 入れたいデータ;

こんな感じ。

日本語での命名は非推奨です。初めに数字をつけるのは言語的にNG。

変数は、定義した以降に 変数の名前 = 入れたいデータ、とすると再代入できます。

変数、定数はどんなときに使うかというと、

object.red.fruit.apple

例えばこんな、「objectというオブジェクトのredというプロパティのオブジェクトのfruit(以下略)…」のように場所が複雑な値があるとします。
これを毎回このまんま書くのは長ったらしいし面倒。

しかし、定数(変数)を使うと

const apple = object.red.fruit.apple;

これからはappleと書くだけであの長いコードと同じ意味になります。嬉しい。

4. 関数

関数とは、いくつかの処理を1つにまとめたものです。値を返すものとも言えます。

関数は、

function 関数名(仮引数) {
    処理
}

と書いて定義できます。
呼び出すときは、関数の名前(引数) 。

関数名はJavaScriptの命名規則に則っているのならば自由。

そして処理。
return 値 をつけると、処理の中で出した値などを、関数を呼び出した場所に入れることができます(値が返ってくるという)。そのときに関数内で以降の処理が実行されないので、returnの値は設定せず「特定の条件で処理を止める」といった処理にも使われます。この場合関数はundefinedを返します。

仮引数には、関数名(引数) で関数が呼び出されるときに、渡された値(引数)が入ります。

//関数を定義
function plus10(number) {
    const n = number + 10;
    return n;
}

//関数の呼び出し
world.sendMessage(plus10(20).toString()); //ワールドに30とチャットされる

こんな関係。
仮引数はコンマをつけて増やすことができます。

アロー関数という書き方もあります。

const 関数変数名 = (仮引数) => {
    処理
};

で書けます。
これは関数に名前を付けているだけであって、関数自体は() => {}だけ。なので、関数が無名でも問題ないときによく使われます。

5. if・for

if文は名前から大体予想がつきます。条件です。

if (条件) {
    処理
}

if文の中の処理は、()の中にtrueが入ったときに実行されます。
例えば、1 === 1を入れると、1 === 1trueを返す式なので処理が実行されます。

結果は、!をつけると反転できます。trueがfalseになったりfalseがtrueになったり、、、if (!(1 === 1))、if (1 !== 1)

条件は&&でどちらもtrueならという条件にできif (true && true)、||でどちらかがtrueならという条件にできますif (true || false)

for文は反復処理ができます。

for (let i = 0; i <= 実行したい数; i++) {
    処理
}

for (constof 配列) {
    処理
}

for (constin オブジェクト) {
    処理
}

1つ目は、let i = 0; で変数の定義、i <= 実行した数; でループが終わる条件、i++でループの中のひと処理が終わったら実行されるコード(今回の場合、iの値を1上げている)となっています。
2つ目は、配列の要素1つ1つに処理を行います。executeコマンドで言うと、as @e の@eが 配列 、その後の@sが 名 の部分。
3つ目は、オブジェクトに存在するプロパティの名前がそれぞれ 名 の部分に入り、処理が行われます。

6. クラス・インスタンス

よく言われる例えで、クラスは設計図、インスタンスは設計図に基づいて生成されたオブジェクト。

無くともコードは書けるので、詳しい説明は省略します。慣れてきたら使ってみてください。

リファレンスの読み方

一通り基礎は分かったところで、一旦コードを書いてみましょう。
まず、ビヘイビアのフォルダscriptsというフォルダを作ってください。

作り終えたら、その中にmain.jsというファイルを作ってください。jsonとjsでは違うので注意。

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

system.runInterval(function() {
    for (const player of world.getPlayers()) {
        const playerName = player.name;
        player.sendMessage(playerName);
    }
},20);

最後に、コピペでファイルを保存しワールドにアドオンを適用してみてください。

いかがでしょうか。1秒ごとに自分の名前がチャットに送られていると思います。
それではコードが実際にどんな動作をするかを確認したところで、このコードの各部分が何を意味しているかを説明していきます。

注意

この解説のクラスのリンクなどは、少し経ったらバージョンが古くなっています。
そのため、こちらの公式サイトから常にその時の新しいバージョンのものを確認してください。リファレンスの読み方は変わりません。
非公式ですがこのようなものもあります。今回はこちらのサイトを使い解説します。

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

ここでは、@minecraft/serverモジュールから、Worldクラスのworldというオブジェクト、Systemクラスのsystemというオブジェクトの2つをインポートしています。

system.runInterval(function() {…},20);

ここでは、インポートしたsystemを使用しています。
systemはSystemクラスのオブジェクトなので、Systemクラスのメソッドが使えます。
runIntervalというメソッドを見てみましょう。

%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2024-03-10-222142.png

始めに、Remarksという、その機能の説明を見てみます。
翻訳すると、「インターバルで一連のコードを実行する。」と書いてあることが分かります。
聞き慣れない言葉はインターバルぐらい。意味は、繰り返し一連のコードを実行する、ということです。

それでは、上から見ていきましょう。はじめに、runInterval(callback, tickInterval?): number。

callbackという引数の説明には、callback: (() => void)とあります。関数が入るということです。下の文には「このインターバルが発生したときに実行される関数コード。」とあります。

続いて、引数tickIntervalの説明を見ていきます。
Optional tickInterval: numberとあります。Optionalからも、tickIntervalがなくとも良いことがわかりました。そして、tickIntervalにはnumberを入れれば良いことも分かりました。
下の文も翻訳して、見てみると「コールバックが呼び出される間隔。」らしいです。名前がtickのintervalなのでtick単位で時間を入れればよさそうです。

そしてReturnを見ると、このメソッドを実行したときに返ってくる値はnumberで、説明によると「この関数の実行をインターバルで停止させるためにclearRunメソッドで使用できる不透明なハンドル。」みたいです。繰り返しをやめるメソッドを使用するのに必要ということです。

つまり、system.runInterval(function() {…},20);は、20ティックごとに{}の中身を実行するという意味だったということ。

for (const player of world.getPlayers()) {…}

ここでは、インポートしたworldを使っています。
worldは、WorldクラスのオブジェクトなのでWorldクラスのメソッドが使えます。
WorldクラスのgetPlayersというメソッドを見てみましょう。

%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2024-03-10-231015.png

今回もはじめに、Remarksを見ていきます。
このメソッドの機能は、「フィルタ条件の EntityQueryOptions セットを介して定義された一連の条件に基づくプレーヤーのセットを返します。」らしいです。

上から見ていきます。まず
getPlayers(options?): Player[]

とあります。これから、引数にはoptionsが入れられるということが分かります。

引数optionsの説明には、options: EntityQueryOptionsとあります。EntityQueryOptionsとはなんだと、クリックしてページへ飛んでみると、

%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2024-03-10-232942.png

色々出てきました。EntityQueryOptionsとはエンティティを取得する際、条件を付けられるインターフェイスのようです。インターフェースはクラスのような設計図であり、オブジェクトのような実態はないものと考えてください。このページは、まだ下に続いています。

%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2024-03-10-233514.png

1つ例を見てみます。このclosestというプロパティには、numberが入るようです。
Remarksを翻訳すると、「返すエンティティの数を制限し、このプロパティで指定された最も近いN個のエンティティを選ぶ。location 値もクエリオプションオブジェクトで指定する必要があります。」になります。ここでlocationも設定して、比較の中心を決める必要もあるようです。コマンドのセレクターで言うcのようなもの。

そんなこんなで、EntityQueryOptionsを引数に入れたメソッドはこんなふうに書けます。

world.getPlayers({ location: {x: 0, y: 0, z: 0}, closest: 1 });

話をgetPlayersに戻します。

optionsの次には、Return、つまり返ってくる値が書かれています。
見てみると、どうやらPlayer[]が返ってくるようです。
Playerクラスのオブジェクトが入った配列ということです。

つまりfor (const player of world.getPlayers()) {…}は、playerにgetPlayersで取得した配列の各要素を代入し、{}の中でその個々の要素に処理を行っているという意味だったということ。

forの処理の中

const playerName = player.name;
player.sendMessage(playerName);

ここまで読めたならばやってることはなんとなく分かると思います。詳しい説明は省略。

%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2024-03-11-001810.png

nameプロパティを見ると、Readonlyと書かれています。これは値を再代入できない、ということです。

nameTagあたりならば再代入で名前を変えることができます。

そして、sendMessage。これはまんま、メッセージを送れます。

%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%BC%E3%83%B3%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88-2024-03-11-002635.png

messageにはstring,RawMessage,(string,RawMessage)[]のどれかをいれることができるようです。

つまりこのコードは、プレイヤーの名前を本人にチャットで送るという処理だったということです。

このように、リファレンスを見れば何をどうすればどうなるのかということが分かります。なにか実装したい機能があればまずはリファレンスを見てみましょう。

よく使われる機能

World
System
Dimension
Entity
ItemStack
Block

↑マイクラの基本になる機能達なので大体はこのクラスの処理

worldのafterEvents、beforeEventsが個人的に強い。イベント系はとにかく色々出来る。

マイクラ内のdevelopment_behavior_packsにアドオンフォルダを入れて、そのアドオン入りワールドで/reloadを実行するとfunctionとscriptapiのファイルが更新されるのでいちいちワールドを変えなくとも良い。

エラー

エラーは、設定にあるクリエイターという欄にあるコンテンツログGUIの有効化をONにすることで見ることができます。
ScriptAPIに限らず、様々な要素のエラーが出てくるのでONにしておいて損は無いです。

エラーは、大抵の場合は翻訳すれば言っていることが分かると思います。

最後に

ここまで読んでいただきありがとうございます!

役に立ったと思ってもらえたら嬉しいです。

なにか質問があるときはこちらのディスコードサーバーから受け付けています。どんな人も大歓迎!一応ここでも受け付けますが内容が複雑になると判断した質問はサーバーでしか受け付けません。

まだScriptAPIについて知らないことも少なくないので、間違っているところがあれば教えてほしいです。

それでは良いアドオンライフを!

※投稿記事に含まれるファイルやリンクにより発生した被害についてクラフターズコロニーは責任を取りません
投稿通報

コメント

  1. 神ですね。ありがとうございます。

    • その言葉が嬉しいです!
      良かったです

  2. scriptAPIのオートコンプリート機能があれば使い方を教えてほしいです。コードエディタはVScodeを使っています。

    • npmをインストールし、https://www.npmjs.com/package/@minecraft/serverこのページからバージョンを選んで、パッケージのインストールのコマンドをコマンドプロンプトにコピペして実行すれば補完が出てくるようになります

  3. scriptapi最高

  4. 自分用メモ

    part-2 世界のイベントを自在にコントロールする
    https://minecraft-mcworld.com/70279/

  5. “dependencies”: [
    {
    “module_name”: “@minecraft/server”,
    “version”: “1.11.0”
    }
    ]
    のversionのbetバージョンの確認(最新アプデごとの)出来るサイト教えてほしいです。

  6. 僕はアドオンを作るときandroidタブレットを使うのですが。
    Minecraftないのファイルをいじれないので/reloadで出来ないんです。
    いちいちインポートしてあーだーこーだするのでアドオン作りがはかどりません。
    androidで利用出来るアプリ(Minecraftは確実)内のファイルをいじれるアプリありませんか?

    • ファイルマネージャーがおすすめです。

      • こんなの?
        %%https://play.google.com/store/apps/details?id=com.alphainventor.filemanager

        url%%

        • 実際に使って確かめてみるのが早いです

  7. 初めのところの
    ScriptAPI(gametestとも言う)というところの網掛けはどうやったんですか?

    • ブログエディタの文字の編集で、1番右のマークを選べば使えます。

      • 左揃えと中央揃えと一つ上に移動と削除と一つ下に移動しかないんですけどどうしたらいいですか?

        • その文字を選択したらペンみたいなマークがいくつか出てくるはずですが…

  8. “dependencies”: [
    {
    “module_name”: “@minecraft/server”,
    “version”: “1.13.0”
    }
    ]
    のversionの安定版のバージョンを確認は

    https://jaylydev.github.io/scriptapi-docs/#script-api-references

    のサイト内にありますか?
    あれば場所を教えて欲しいです。
    見つけきれません…

    • 1.13.0は安定版ですよ。合っています。

      • ありがとうございます!

        そして質問です。
        ===は何何は何何(?)
        &&&は何何と
        たけど(多分(?))
        またはってどう書くんですか?

  9. 質問です。
    ===は何何は何何(?)
    &&&は何何と
    たけど(多分(?))
    またはってどう書くんですか?

コメント通報