llllon_888のコマンドメモ帳

minecraft歴は長いけどコマンド歴は短い男のコマンド作成で気に留めておこうと思ったことまとめ場所。要は備忘録。偶然誰かの役に立ったらいいなって感じでわりと適当に書いてる。

minecraftで会話するコマンドを作りたい!

軽い前置き

RPG系で必須な会話コマンド。
話す内容を全部一つにまとめてsayコマンド使うのもまあ悪くはないだろう。
でも、さすがにそれじゃあ読みづらいしよくないよね?
だから、時差アリで表示する会話コマンドを使いたい!
でも、scheduleコマンドとかを使うとたくさんのfunctionが必要になるし、すさまじくダルい。
ということで一つのfunction内で時差あり会話をするコマンドを作っていこう!

ちなみにこの話はデータパック使う人限定の話で、使わずコマンドブロックでやる人はふつうにレッドストーンリピーターとか使えばいいと思うよ。

どんな仕組みか

まず最初にどんな仕組みで動くのかざっくり説明しよう

データパックにはtick.jsonで指定したfunctionを毎tick実行し続けるというものがあります。ここにtalkで使うfunctionを入れておく。
そして、その中身は

talk1というタグを持ったプレイヤーに毎tick、talk1というファンクションを実行させる。

というような感じ。
そして次に、talk1というファンクションの中身は

スコアボード[timer]を1増加させる
timerが1になったとき[台詞1]を表示
timerが40になったとき[台詞2]を表示
timerが80になったとき[台詞3]を表示
timerが80になったときタグtalk1を削除
timerが80になったときtimerを0にする

というような内容のコマンドを使う。
これが毎tick実行されてるので、1tick経つたびにtimerが増える。(ちなみに1秒につき20tick経過する)
そしてtimerが少しずつ増えていくので少しずつ台詞が表示される。
最後に台詞が終わったときに、タグを消して、timerもリセットすれば元通りになって会話が終了する

というような仕組みです

こういうようなコマンドを使うことで、会話を発生させたいタイミングでタグをつけるだけで会話をさせることができるお手軽コマンドが実装できます。
コピーしてタグの名前とファンクションの名前を変更するだけで新しい会話を作れるので会話を増やすのも簡単です。

事前準備

データパックを用意しましょう
timer というダミーのスコアを用意しておきましょう

実演

構造を理解した上で実際に書いていこう

リピート実行コマンド

execute as @a[tag=talk1] run function (データパックの名前):talk1

talk1のfunctionの中身

scoreboard players add @s timer 1
execute if score @s timer matches 1 run tellraw @a {"text":"台詞"}
execute if score @s timer matches 40 run tellraw @a {"text":"台詞"}
execute if score @s timer matches 80 run tellraw @a {"text":"台詞"}
execute if score @s timer 80 matches run tag @s remove talk1
execute if score @s timer 80 matches run scoreboard players set @s timer 0

これでタグtalk1を持ったプレイヤーが居たら40tick(2秒)に一回台詞を表示して元通りになるコマンドになる
特定の人だけに表示したいときはtellrawをいじって対象を選んであげてください

注意点

たくさんの会話を作るときに、中身をコピーして量産するけどそのとき書き換える必要のある物を忘れないで!
書き換える物は
timer matches ~の時差を制御する部分
tag remove talk~の最後に削除するタグの名前

まとめ

タグを与えるだけで会話コマンドを起動できる簡単な会話コマンドの紹介でした。
今回使ったスコアボードでタイマーを制御する構造はmobを移動させるときに使ったりすることもあるらしいので、覚えておくととっても便利かもだから頭の片隅においておこう。

複数の額縁を透明にする

minecraft java 1.17

しょうもない前置き

この前作ろうとしたものの中に 五十音表を壁に貼り付けて謎解きにしたい! という感じの発想がありそれを試した。
方法は画像データをminecraft専用に変換して、それを地図に貼り付ける。これについても今度書こうかな。
そんでその地図を額縁に入れて壁一面に貼り付けた。
でも、その画像が透過素材だったから裏の額縁見えまくりで不格好だったから額縁を透明にしようと思い立ったわけだ。
ということでコマンド行こう

額縁を透明にするコマンド


/data merge entity <エンティティのUUID> {Invisible:1}

このコマンドの<エンティティのUUID>はカーソル合わせながらコマンド打って、tabの予測変換で出せる。



これが額縁を透明にするコマンド。
dataコマンドでエンティティにInvisibleというデータを与えてます

dataコマンドは複数選択できない

なんと複数選択できないという罠。当時50個近い額縁を透明にしようと思ってた俺にとってまさしく地獄の仕様でした。
うーんどうしたものかと頭をひねっていた時に思いついたひらめき

俺が50個の額縁にコマンド打つのができないなら...こいつら各自に自分にコマンド打ってもらえばいいのでは?

複数の額縁を透明にする方法


execute as @e[distance=..30] run data merge entity @s {Invisible:1}

自分から半径30ブロック以内の額縁を透明にするコマンド



文を一個一個紐解いていこう

execute as

コマンドの実行主の選択
このコマンドを使うことでコマンドを使ったプレイヤーをここで指定したプレイヤーに変更できる。minecraftはエンティティもコマンドを実行できるので今回使う。

@e

すべてのエンティティを示すセレクター。
mob、額縁、トロッコ、プレイヤー、その他もろもろありとあらゆるエンティティを含むセレクター。
うっかり/kill @e なんてやった日には世界が終わる。

[distance=..30]

コマンドの実行主との距離を指定する。
今回はexecuteコマンドの実行主である自分との距離が30マス以内を指定する。
「..」というようにドットを二つ付けると 以上 以下 を指定できる。
例: ..30  30ブロック以内
   10..  10ブロック以上
   10..30 10ブロック以上30ブロック以内

run data merge entity @s {Invisible:1}

上で説明していた通りの透明にするコマンド。
ただし、対象を@sという実行主を対象とするセレクターに変更してある。
execute as を使っているとこの実行主に置き換えられる。

まとめ

こんな感じで複数の額縁を一斉に透明にしたよっていう話でした。
これは対象を単体しか選べない系コマンド全部に応用できそうだから覚えておいて損はなさそうだなって感じ

playsound コマンドについて

minecraft java 1.17

ちょっと使いづらいなという印象を受けた。

まずは構文

playsoundコマンド 構文

playsound [流したい音] [なんの音として流すか] [誰に流すか] [流す場所] [聞こえる距離]

というのが主な文

一つ一つ説明していこう

[流したい音]

そのまんまの意味、流したい音を決めよう

例:minecraft:entity.wolf.ambient(オオカミの鳴き声)

[なんの音として流すか]

これはMinecraftの設定部分に関する話。Minecraftの音量設定は主音量、BGM、ジュークボックス、天候、ブロック………って感じで音が分類分けされていてそれぞれの音量を個別で調整できる。

これをどれにするかでどの音として流すか決められる。

例えば、主音量100%、BGM50%の人に流す時、ココをmasterにすると爆音で流れるけど、musicにして流すと半分の音で流れる。

主音量=master、BGM=music、ジュークボックス=record という感じで紐づいている

[誰に流すか]

至ってシンプル。誰に再生するか決めよう。@aとか@pとか入れておこう。

[流す場所]

どこで再生するか位置を決めれる。xyzでの座標を書いておこう。

これを設定すると音の位置を使ったギミックが作れるから嬉しい。

あと、場所から離れるとフェードアウトもしていく。店内BGMとかとして使うならこの要素は便利かも。

[聞こえる距離]

文字通り聞こえる距離を決める。流す場所から聞こえる距離を設定する。1に設定すると半径16マスまで聞こえる。つまるところ設定単位はチャンクやね。

例文

ここまで解説したから例文を1つ。そんな複雑なものでもないけど。

playsound minecraft:entity.wolf.ambient master @a ~ ~ ~ 2

ってやると狼の鳴き声が自分から半径32ブロック以内のプレイヤーに主音量の音量設定を参照して再生する


という感じ。
ここまでなら普通にいい感じの音楽再生コマンドだった。

しかし…このコマンド、失敗することがある。

コマンドの失敗する条件

それは、音楽再生範囲内に対象のプレイヤーがいない場合再生されないというもの。

つまり、店内BGMを流したいなら常に流しっぱという楽な処理ではなく、店に来たタイミングで再生し始めなければならない。
音楽を利用したギミックを作る時にこの仕様にすごい苦労した。

ちなみに、その時解決した方法は、一瞬でもその場にいれば再生できるので


tp 再生したい場所
playsound 音楽
tp 再生したい場所
playsound 音楽
tp 再生したい場所
playsound 音楽


というようなfunctionを用意した。functionなのでその場に居た時間は1tickにも満たないような極小時間だけど、これでもちゃんと再生されたんだから驚きだった。