【マイクラ統合版】プレイヤーのスコアを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上でプレイヤーのスコアを読み取って動的な処理を行うことが可能になります。本記事の内容が皆様のお役に立てれば幸いです。

今回解説したスクリプトを使って、友人・コミュニティー内で24時間いつでも遊べるマルチサーバーを構築したい場合は、VPS(レンタルサーバー)の導入が近道です。

私の開発・検証環境では「シンVPS」を使用しています。

シンVPS コントロールパネル画像

以前は自宅PCでホストしていましたが、PCの電源を切り忘れるストレスや、電気代を考慮して移行しました。シンVPSを選んだ決め手は、圧倒的なコストパフォーマンスです。

  • 月額の安さ 4GBプランでも月額1,200円程度(長期契約なら1,000円以下)と維持費が安く済みます。
  • 高速な読み込み 全プランでNVMe SSDを採用しており、ワールドの読み込みや重いコマンド処理でもラグを感じにくいです。
※最低利用期間が3ヶ月からという縛りはありますが、サーバーを長期で安定運用するならむしろ割安になります。

以下のリンクから申し込むと初回利用料金が10%OFFになります。
(1ヶ月以上の契約対象。「安くて速い」サーバーを探している方はぜひ試してみてください)

シンVPS 公式サイトを見てみる
(10%OFF適用)
マルチサーバーの立て方はこちら
assorted books on book shelves
最新情報をチェックしよう!