注目キーワード

【マイクラ統合版】プレイヤーのスコアをScriptAPIで読み取る方法 – scoreboardの概要も解説

前提

このサイトの読者なら既にご存じかとは思いますが、マインクラフトにはScriptAPIと呼ばれる拡張機能が存在します。簡単に言えば、Javascriptというプログラミング言語を用いてゲームシステムをカスタマイズする機能のことです。

これはScriptAPIの一例で、「プレイヤーがジャンプしたらkillコマンドを実行する」というスクリプトです。これは縛りプレイなどに用いられますが、このようにしてゲームシステムを改変できるわけですね。ScriptAPIについての詳細はこちらをご覧ください:

scoreboardコマンド

さて、話は変わりますが、同様にマインクラフトにはスコアボードと呼ばれる機能が存在します。これは、プレイヤーやエンティティにつけられた値のことであり、主にscoreboardコマンドを介して閲覧・編集することができます。主に配布ワールドなどでプレイヤーに点数をつけるのに用いられますね。

具体的には、scoreboardのオブジェクトを追加する場合は、

scoreboard objectives add test_score dummy

※「test_score」はオブジェクトの名前です。ここには各自好きな名前を入れることができます。

というコマンドを打ち込めばよいですし、プレイヤーに付与する場合は、

scoreboard players add @s test_score 1

といったコマンドによって可能です。(※上記はスコアを1付与する例ですが、「add」を「remove」に変えることで減らすこともできますし、「set」にすると任意の値に設定できます)

そして付与されたスコアを使って何かを行う場合は、

give @a[scores={test_score=3}] diamond 1

のように、ターゲットセレクターと併せてコマンドを使用することが一般的です。これは、test_scoreが3のプレイヤーにダイアモンドを1個与える例です。

問題点

一見するとこれは非常に自由度が高いように見えますが、動的に何かを起こそうとするとscoreboardコマンドはあまりに非力です。例えば、test_scoreが3の場合は3個のダイアモンドを、スコアが5の場合は5個のダイアモンドを与える、といった具合です。これを達成する場合、

give @a[scores={test_score=3}] diamond 3
give @a[scores={test_score=4}] diamond 4
give @a[scores={test_score=5}] diamond 5
give @a[scores={test_score=6}] diamond 6

のように非常に多くのコマンドが必要になり、数が多い場合この方法はあまりに非現実的です。

効率的に、スコアに応じて動的な処理を行う方法はないのでしょうか?

次章では、この問題に対する解決策を提示します。

解決策

この問題は、前述のAPIScriptを用いることで解決します。すなわち、プレイヤーのスコアを読み取る関数を次のように定義します。

function get_score(score_name, player_name){
    try{
        const scoreboard = server.world.scoreboard;
        let objective = scoreboard.getObjective(score_name);
        let score = objective.getScore(player_name.scoreboardIdentity);
        if (score != undefined){
            return score;
        }else{
            return 0;
        }
    } catch{
        return 0;   //scoreboardが定義されていないかも?
    }
}

これは、スコアボードのオブジェクトとプレイヤーの名前を引数としてそのプレイヤーのスコアを読み取る関数です。エラーを起こした場合、0を返し、その他の場合はスコアを整数型で返します。特に当該スコアオブジェクトが定義されていない場合0を返すので注意しましょう。

使用例

この関数を用いて動的な処理を行う例を提示します。

server.system.runInterval(ev => {
    for (const player of server.world.getAllPlayers()){
        player.runCommand("say 私のスコアは" + get_score("test_score",player) + "です");
    }
});

これは、現在のスコアを読み取ってそれをsayコマンドに組み込んだ例です。実際にこれを保存してゲームを動かすと、現在のスコアを発言すると思います(実機検証済)。

同様に、現在のスコアの分だけダイアモンドをプレイヤーに与えるスクリプトを書くこともできます:

server.system.runInterval(ev => {
    for (const player of server.world.getAllPlayers()){
        player.runCommand(`give @s[scores={test_score=${get_score("test_score",player)}}] diamond ${get_score("test_score",player)}`);
    }
});

これによって、先ほどの大量のコマンド群を書く必要がなくなり、非常にスマートです。

おしまい

このようにして、ScriptAPI上でプレイヤーのスコアを読み取って動的な処理を行うことが可能になります。本記事の内容が皆様のお役に立てれば幸いです。

assorted books on book shelves
最新情報をチェックしよう!