アドバンスメント(進捗)を自作しよう

前回はtellrawでJSON Textを使い、チャット欄に色・装飾・クリックイベントを付けたリッチなメッセージを表示する方法を学びました。今回はそのJSON知識を活かして、アドバンスメント(進捗)を自作します。JSONファイルを1枚書くだけで「ダイヤモンドを入手したときに自動でfunctionを呼び出す」「特定のモブを倒したら演出を発動させる」といった仕組みが作れます。さらに、非表示アドバンスメントを使った汎用トリガーのテクニックまで解説しますので、ぜひ最後まで読んでみてください。

対応バージョン:Java Edition 1.21.11

目次

前提知識

アドバンスメントとは

アドバンスメントはJava Editionの「進捗」システムです。特定の条件を満たしたとき、画面右上にポップアップが表示されます。Datapackでは、このアドバンスメントを「条件が満たされたときに自動でfunctionを呼び出すトリガー」として使うのが最も実用的な活用方法です。前回のtellrawの記事で「一般プレイヤーには/functionを実行する権限がない」という話をしました。アドバンスメントの報酬として関数を呼び出す場合は、サーバー側(Operator権限)として実行されるため、この制限を回避できます。

ステップ1:フォルダ構成とファイルを作る

アドバンスメントのファイルは data/<名前空間>/advancement/ フォルダ内にJSONファイルとして配置します。今回は「ダイヤモンドを入手したらfunctionを呼び出す」仕組みを作ります。

my_datapack/
├── pack.mcmeta
└── data/
    └── my_datapack/
        ├── advancement/
        │   └── get_diamond.json
        └── function/
            └── on_diamond.mcfunction

advancement/ フォルダはDatapackに同梱するだけで自動的に読み込まれます。/advancement コマンドで後から付与・剥奪もできるため、デバッグのしやすさも魅力です。

ステップ2:基本のJSON構造を書く

アドバンスメントJSONは大きく3つのブロックで構成されます。"display"(表示設定)・"criteria"(達成条件)・"rewards"(報酬)です。前回のtellrawのJSON Textと同じく、プロパティをオブジェクト形式で並べて書きます。

{
  "display": {
    "icon": {
      "id": "minecraft:diamond"
    },
    "title": {"text": "初めてのダイヤモンド"},
    "description": {"text": "ダイヤモンドを入手しました"},
    "frame": "task",
    "show_toast": true,
    "announce_to_chat": true
  },
  "criteria": {
    "get_diamond": {
      "trigger": "minecraft:inventory_changed",
      "conditions": {
        "items": [
          {"items": "minecraft:diamond"}
        ]
      }
    }
  },
  "rewards": {
    "function": "my_datapack:on_diamond"
  }
}

各プロパティの意味を確認しましょう。"frame" は実績のアイコン形状で、"task"(四角)・"goal"(丸)・"challenge"(六角)の3種類があります。"show_toast"true にすると右上にポップアップが出ます。1.21からアイコンの指定は "item" ではなく "id" になった点に注意してください。1.20以前のDatapackを流用する場合はここを書き直す必要があります。

【ダイヤモンドを拾った瞬間に画面右上にアドバンスメントのポップアップが表示されているGIF

ステップ3:よく使うトリガーの種類

"criteria" 内の "trigger" には、どんな状況で達成するかを指定します。主なトリガーは以下のとおりです。

  • minecraft:inventory_changed:インベントリが変化したとき。アイテム入手の検知に使う
  • minecraft:player_killed_entity:プレイヤーがエンティティを倒したとき。モブ討伐イベントに使う
  • minecraft:location:プレイヤーが特定の座標・バイオームにいるとき
  • minecraft:impossible:絶対に自動達成されない特殊トリガー。手動で /advancement grant して使う(ステップ5で詳しく解説します)

ステップ4:rewardsでfunctionを呼び出す

"rewards""function" に指定したfunctionは、アドバンスメントが達成されたとき一度だけ自動的に呼び出されます。実行権限はOperatorと同等なので、一般プレイヤーが達成しても /give/function を安全に呼べます。

# on_diamond.mcfunction

tellraw @a ["",{"text":"[達成] ","color":"gold","bold":true},{"text":"ダイヤモンドを入手したプレイヤーがいます!","color":"white"}]
give @s minecraft:diamond 1

前回学んだ tellraw の配列形式をそのまま使っています。このようにアドバンスメント(条件の検知)→ mcfunction(処理)という役割分担にしておくと、処理の追加・変更がfunctionファイルだけで完結するため管理しやすくなります。

ダイヤモンドを入手した後、チャット欄に「[達成] ダイヤモンドを入手したプレイヤーがいます!」が金色・太字で表示されているスクリーンショット

ステップ5:非表示アドバンスメントと汎用トリガー

アドバンスメントは画面に表示させないこともできます。"display" ブロックを丸ごと省略するか、"display" 内に "hidden": true を加えると、ポップアップが出ない「隠しアドバンスメント」になります。これを "trigger": "minecraft:impossible" と組み合わせると、「任意のタイミングで一度だけfunctionを呼び出す」汎用トリガーが作れます。

{
  "criteria": {
    "trigger": {
      "trigger": "minecraft:impossible"
    }
  },
  "rewards": {
    "function": "my_datapack:on_event"
  }
}

このアドバンスメントは自動では達成されないので、別のmcfunctionから /advancement grant を呼んで手動で発火させます。

# 任意のmcfunctionから実行する
advancement grant @s only my_datapack:on_event

ただし、アドバンスメントは一度達成されると同じプレイヤーには再発火しません。繰り返し使いたい場合は、on_event.mcfunction の末尾でリセットを忘れずに入れましょう。

# on_event.mcfunction
# ---- ここに処理を書く ----
tellraw @s {"text":"イベントが発生しました!","color":"aqua"}

# ---- 最後にリセットして次回も発火できるようにする ----
advancement revoke @s only my_datapack:on_event

この「grant → function実行 → revoke」のパターンはDatapackで非常によく使われます。scoreboardのtriggerと組み合わせると、プレイヤーのクリック操作を検知して処理を動かす仕組みも作れます。

非表示アドバンスメントのフォルダ構成
コマンドで進捗達成しているGIF

まとめ

  • アドバンスメントJSONは "display""criteria""rewards" の3ブロックで構成される
  • 1.21からアイコンの指定キーが "item" から "id" に変わった点に注意する
  • "rewards": {"function": "..."}} で達成時にfunctionを自動呼び出しできる。実行権限はOperator相当なので一般プレイヤーの達成でも安全に動く
  • よく使うトリガーは inventory_changed(アイテム入手)・player_killed_entity(モブ討伐)・impossible(手動発火)など
  • 非表示アドバンスメント+minecraft:impossible の組み合わせで「任意タイミングでfunctionを1回だけ呼び出す」汎用トリガーが作れる。繰り返す場合は末尾で advancement revoke を忘れずに

次の記事「/dataコマンド基礎:NBTを読み書きしよう」では、エンティティやブロックのNBTデータを data get / data modify で読み書きする方法を解説します。アドバンスメントで検知した情報をNBTと組み合わせることで、さらに細かい条件分岐ができるようになります。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次