【1.20.5+】タイマーの優しくない作り方【データパック/コマンド講座】

スポンサーリンク

ということで

タイマーの作り方とか最近の記事でも見かける気もしますが、効率的に最適化された記事はほとんど見ないということで、
超簡単(大嘘)なタイマーをつくってみましょう!

てかさ、効率的に最適化ってどうするの?っていう話。

この記事を読んでいる人は1.20.2にデータパックにマクロが登場したことを知っているでしょう。
なので、1000個のタイマーを効率的に作りたい!というときにマクロで作った方が楽なので、今回はめちゃくちゃ作成が楽になるタイマーを作りましょう!

ちなみに、マイクラは1秒間に20ティック動いているのが普通なので、tickコマンドなどで変えるとタイマーが早くなります。逆に言えば、tickコマンドで5倍速にすればタイマーも5倍速になります。
そんなんいやだよっていう人は計算するときに20で割る部分を全て好きな数字に変えましょう。

1. load

まずは、みんな大好きスコアボードを追加しましょう。

#> timer:1_all_load
function timer:3_set_num

このスコアボードは何?という話、このタイマーにおいて計算用スコアボードはとても大切です。
なんせ今回の記事では scoreboard operation をとても沢山使います。
続いてこのスコアボードに今回使う計算数字をあらかじめ入れておきます

#> timer:3_set_num
scoreboard objectives add timer.num dummy ["", {"text": "計算用スコアボード", "color": "gray"}]

scoreboard players set 10 timer.num 10
scoreboard players set 20 timer.num 20
scoreboard players set 60 timer.num 60

operation で追加したいものがあれば、このスコアボードにじゃんじゃん入れていきましょう。

続いて、コマンドストレージを追加しましょう。
なんですか?これはと思う人は試しに使いましょう。痒い所に手が届くので。

#> timer:1_all_load
function timer:3_set_num

data modify storage timer:_ Version set value [1, 0, 0]

え、何?バージョンを入れてなんか意味あるのと思う方、そうです。まったく意味ないです。
(強いて言えば予測変換でtimer:_が出るようになるくらいです)

2. タイマー

それでは、タイマーを作っていきましょう!

タイマー… えと、カウントアップ?カウントダウン?

さてその辺なんも決まってないので、どちらでも対応できるように今回はあえて設定しないでおきましょう。

まずは、タイマーの下処理をしましょう。
最初に作ったスコアボードは計算用なので、今回は自作タイマーのスコアボードを作りましょう。

#> test:timer1/all_load
scoreboard objectives add testtimer dummy ["", {"text": "テストタイマー", "color": "yellow"}]

じゃあとりあえず10分のカウントダウンタイマーを作りますか。
タイマー開始時に次のコマンドを実行します。

#> test:timer1/start
scoreboard players set timer1 testtimer 12000

続いて常時実行するコマンドを作りましょう。

#> test:timer1/every_tick
scoreboard players remove timer1 testtimer 1
function timer:api/set {name: "timer1", "objective": "testtimer"}

execute if score timer1 testtimer matches ..0 run function test:timer1/end

おやおや、新しいfunctionのファイルがありますね、これは…

3. APIを作ろう~

ということでタイマーをどーん!

#> timer:api/set
#マクロ $(name)=スコア名 $(objective)=スコアオブジェクト
#出力 {"nbt": "show.$(objective).$(name).title", "storage": "timer:_", "interpret": true}

$scoreboard players operation $(name)_S $(objective) = $(name) $(objective)
$scoreboard players operation $(name)_S $(objective) /= 20 timer.num

$scoreboard players operation $(name)_M $(objective) = $(name)_S $(objective)
$scoreboard players operation $(name)_S $(objective) %= 60 timer.num
$scoreboard players operation $(name)_M $(objective) /= 60 timer.num


$scoreboard players operation $(name)_S10 $(objective) = $(name)_S $(objective)
$scoreboard players operation $(name)_S10 $(objective) /= 10 timer.num

$scoreboard players operation $(name)_S1 $(objective) = $(name)_S $(objective)
$scoreboard players operation $(name)_S1 $(objective) %= 10 timer.num

$data modify storage timer:_ show.$(objective).$(name).title set value "["", {"score": {"name": "$(name)_M", "objective": "$(objective)"}}, {"text": ":"}, {"score": {"name": "$(name)_S10", "objective": "$(objective)"}}, {"score": {"name": "$(name)_S1", "objective": "$(objective)"}}]"

※このサイトの仕様上”(シングルクォーテーション)が”(ダブルクォーテーション)になってしまっています。
コピペ用にダブルクォーテーションに変換したものは下記ですが、編集が面倒なので推奨しません。

$data modify storage timer:_ show.$(objective).$(name).title set value "[\"\", {\"score\": {\"name\": \"$(name)_M\", \"objective\": \"$(objective)\"}}, {\"text\": \":\"}, {\"score\": {\"name\": \"$(name)_S10\", \"objective\": \"$(objective)\"}}, {\"score\": {\"name\": \"$(name)_S1\", \"objective\": \"$(objective)\"}}]"

はい、いきなりびっくりしたと思います。こちらのコードを1つずつ解説していきましょう。

まず、秒に設定したいので、秒のスコアを作ります。
続いて、秒のスコアを20で割ります。そうすることで、マイクラの1秒を計算することができます。

次に、秒のスコアを分のスコアにいれます。ここからコマンドの順番が大事になります。
代入した後に秒のスコアを60で割った余りにします。%っていうのはそのスコアで割った余りを出してくれます。小学生でも高学年になると余りなんてテストに出てきませんね。この余りの機能がマイクラにあるのが凄いと思いました。

これで秒の処理ができました。そして分も60で割りましょう。

これで秒と分に分けることができました。

タイマーをつくるときって、秒の部分が1桁の時に0はつけて揃えたいですよね。
ということで、秒が1桁の時と2桁の時で場合分け… ではなく、
秒をそのまま2桁にしてみましょう。

10の位と1の位のスコアをつくります。
この時10の位は10でそのまま割る。
1の位は10で割った余りを出せば1桁目と2桁目のスコアをつくれます。

さてこれをアクションバーやボスバーに表示… ではありません。

ここで役に立つのがコマンドストレージです。

4. コマンドストレージに長いコードをいれておく

いちいちタイトルに入れるとコードが見づらくなるので、コマンドストレージに代入までしてくれるマクロを作りました。

これでアクションバーに表示するときは、

title @a actionbar ["", {"nbt": "show.$(タイマーのオブジェクト).$(タイマーの名前).title", "storage": "timer:_", "interpret": true}]

と常時実行すればアクションバーとして表示されます。

ここで忘れがちなのが、「interpret」を「true」にすることです。
こちらはデフォルトで「false」なので、これを表示するとコードが表示されます。
「true」にすることで変換してくれると覚えましょう。

こちらの前や後に説明文を入れたり、colorやbold等を変更することもできるのでとてもコードが見やすくなります。

そんな感じでできたのがこちら。

#> test:timer1/show_actionbar
title @a actionbar ["", {"nbt": "show.testtimer.timer.title", "storage": "timer:_", "interpret": true}]

こうすることで全プレイヤーに簡易的なタイマーをアクションバーに表示させます。

いやいや、ボスバーだとどうなるの?と思う方。ボスバーは同じようにすれば大丈夫です。

#> test:timer1/show_bossbar
bossbar add test:timer1 ""
# 色
bossbar set test:timer1 color yellow
# スタイル
bossbar set test:timer1 style notched_6
# 必ず有効
bossbar set test:timer1 visible true
# 最大値
bossbar set test:timer1 max 12000
# 現在の数字を代入
execute store result bossbar test:timer1 value run scoreboard players get timer testtimer
bossbar set test:timer1 name ["", {"nbt": "show.testtimer.timer.title", "storage": "timer:_", "interpret": true}]
# 表示するプレイヤー (全員非表示にする場合はセレクターに何も入れない)
bossbar set test:timer1 players @a

ところで、nbtが使えない表示方法もいくつかあります。
アイテムだとか、エンティティだとか、スコアボードだとか…
その時にはアイテムに代入して変換させましょう。

え、アイテムもnbtとか使えないんじゃ… そんなことを全てぶち壊すのがルートテーブルです。

{
"json_path": "test:timer1/show_item",
  "pools": [
    {
      "rolls": 1,
      "entries": [
        {
          "type": "minecraft:item",
          "name": "minecraft:stone",
          "functions": [
            {
              "function": "minecraft:set_name",
              "entity": "this",
              "target": "item_name",
              "name": [
                "",
                {
                  "nbt": "show.testtimer.timer.title",
                  "storage": "timer:_",
                  "interpret": true
                }
              ]
            }
          ]
        }
      ]
    }
  ]
}

この中の「entity」を「this」にしている部分、実はこれがとても大事です。
この状態でエンティティが実行すると、そのエンティティが中心となって変換してくれます。
これをどこかに実行させましょう。

#> test:timer1/show_item
summon minecraft:armor_stand ~ ~ ~ {Invulnerable: 1b, Invisible: 1b, Marker: 1b, NoAI: 1b, Silent: 1b, Tags: ["timer.test1"]}
execute as @e[type=minecraft:armor_stand, tag=timer.test1] at @s run loot replace entity @s armor.head loot test:timer1/show_item
data modify storage timer:_ show.testtimer.timer.interpret set from entity @e[type=minecraft:armor_stand, tag=timer.test1, sort=nearest, limit=1] ArmorItems[-1].components."minecraft:item_name"
function test:timer1/show_sidebar with storage timer:_ show.testtimer.timer
kill @e[type=minecraft:armor_stand, tag=timer.test1]

さて、これを試しにサイドバーに表示させましょう。

#> test:timer1/show_sidebar
scoreboard objectives add sidebar_test dummy ["", {"text": "テストサイドバー", "color": "yellow"}]
scoreboard objectives setdisplay sidebar sidebar_test
scoreboard players set timer sidebar_test -1
$scoreboard players display timer sidebar_test $(interpret)

これでサイドバーに表示できました。めっちゃ簡単でしたね!

5. おわりに

こんなに見づらい記事なのに最後まで読んでくださりありがとうございます。
途中でマーカーするのが面倒になったので黒文字に統一しました。
めっちゃ見づらい記事になってしまっていてすみません。

コードが欄列していますが大事なのは

timer/function/api/set
timer/function/3_set_num

この2つさえ作れればあとは適当につくればいいだけなので簡単です。
特にtimer:api/setはどのタイマーでも使えると思います。1時間の表記も作りたいという方は自分で作りましょう(丸投げ)。

それではまたどこかでお会いしましょう。バイバイ!

この記事の内容/コード全てはMinecraftエンドユーザー使用許諾契約の範囲内の中で
あなたが自由に使用して頂いて構いません。
私はこの記事をこのサイトでしか作成していないので、
他のサイトで私を偽る人物がこの記事を作成しても決して私が作成したものではないことをご留意ください。

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

コメント

コメント通報