TpBackの技術的なところ

TpBackとかいうマクロを作った
https://note.com/king_amakusa/n/n7bdb826b1468

こちらの技術的な面の解説?になります。
長々しくならないように省いていましたが、需要があるみたいなので…!

TpBackのおおまかな仕組み

TpBackは、スタック(stack)とよばれる仕組みを基盤にして作っています。
入れ物にデータを足していって、取り出すときは一番上のものからとりだしていくというような考え方です。
ジューCっていうお菓子が雰囲気近いです。

わかりそうでわからない.png

マクロの記述

基本的に、マクロは
関数名;
または
関数名(引数);

という形式で記述します。
(例) echo(hello); など

変数

マクロでは、
<変数名>・・・Bool型(trueかfalseか)
#<変数名>・・・Int型(数値が入る)
&<変数名>・・・String型(文字列が入る)
というように頭文字で型を区別します。
(例) #number ,&text など

@<変数名>とするとグローバル変数(他のマクロからも呼び出せる)になります。
<変数名>[]とすると配列(値の入れ物)になります。
(例) @gamemode1 ,@#xpos[] など

また、変数以外が入る場所に変数を入れる際には、
%<変数名>%として変数と認識してもらう必要があるみたいです。
(例) if(%@#xpos[]% == 0); など

定数

マクロには、%XPOS%, %YPOS%, %ZPOS%や、%XP%(経験値)など、マクロに組み込むことができる定数が用意されていて、これらを使うことでより幅広い機能の実装ができます。
(例) echo(%XPOS% %YPOS% %ZPOS%); など

またイベントマクロなどでは、マクロ実行条件に応じて初めから定数が用意されている場合があります。
(例) ifmatches(%CHAT%, hello); など

ずらーっと書いてて教科書みたいですが、参考程度で大丈夫です。。

TpBackの中身の解説

機能ごとにひとつひとつ細かく見ていきます。

座標の保存

座標の保存は、主にイベントマクロのonSendChatMessage(何かしらのチャットを送信した際に呼び出される)の中身で行われています。

$${
ifmatches(%CHAT%,/tp); //送信したチャットに/tpが含まれていたら

@#xpos[]=%XPOS%; //x座標を保存
@#ypos[]=%YPOS%; //y座標を保存
@#zpos[]=%ZPOS%; //z座標を保存

endif;
}$$

ifmatches(%CHAT%,/tp);で、
%CHAT%(送信したチャット)に"/tp"が含まれていたら以下のマクロを実行する
といった処理を行っています。(endif;までが実行するマクロの範囲)

座標の保存は、x座標の保存を例にすると、@#xpos[]という名前の座標BOXを作り、そこに%XPOS%(x座標の定数)を格納するといった形で実行されています。
このとき、新しく入れたx座標は座標BOXの一番上に格納されます。(ここ重要)

@#xpos[] = %XPOS%;

同様にして、y座標・z座標もここで保存します。

保存した座標に戻る

"座標を取り出す・座標にテレポートする"
二つの処理を実行することで、保存した座標に戻ります。

[Back]ボタンから呼び出される、tpback.txtの中身です。
二つの処理をそれぞれ見ていきます。

$${
//座標を取り出す
pop(@#xpos[],#pos[0]); //x座標を取り出す
pop(@#ypos[],#pos[1]); //y座標を取り出す
pop(@#zpos[],#pos[2]); //z座標を取り出す

//座標にテレポートする
if(%#pos[0]% != 0); //#pos[0](x座標)が0でなければ

echo(/tp %#pos[0]% %#pos[1]% %#pos[2]%); //テレポート

endif;
}$$

pop(<配列>,<出力先>);で、配列(座標BOX)の一番上にあるものを取り出すことができます。また、このとき取り出したものは配列から削除されます。
x座標を例に出すと、
pop(@#xpos[],#pos[0]);で@#xpos[](x座標の座標BOX)の一番上にある座標を#pos[](xyz座標BOX)の0番目に格納する処理が行われています。
そして、このとき取り出される座標は、保存された座標の内最新のものになります。
同様にy座標、z座標も取り出します。

※ここで取り出す作業を繰り返してみると…?
保存されたものの内最新の座標を取り出す&削除 = 保存された時期が近いものから順番に取り出される = 過去にさかのぼっていく形になる!

あとは取り出した座標にテレポートするだけです。

if(%#pos[0]% != 0); //#pos[0](x座標)が0でなければ

echo(/tp %#pos[0]% %#pos[1]% %#pos[2]%); //テレポート

endif;

echo(/tp %#pos[0]% %#pos[1]% %#pos[2]%); で、
/tp #pos[]の0番目(x座標) #pos[]の1番目(y座標) #pos[]の2番目(z座標)
とコマンドが実行されることで保存した座標にテレポートします。

また、if(%#pos[0]% != 0); で、#pos[]の0番目(x座標)が0でなければ実行するという形をとっていますが、これには訳があります。
保存した座標を使い果たしてしまい、座標BOXが空っぽになった状態で上の/tpコマンドを実行されると、空っぽ = 0 という認識から /tp 0 0 0 となり(0, 0, 0)に飛ばされてしまいます。なのでこれを防ぐためにx座標を確認して空っぽかどうかを確認する必要があります。
他の座標を確認しないのは、座標保存のタイミングはxyz全部同時だからx座標が空っぽじゃなかったら他も大丈夫でしょっていうサボりです。

onJoinGameの中身

TpBackのつくりかたの記事でも触れていましたが、onJoinGame(ゲームに参加すると実行)で実行しているマクロで、初めに座標を全て削除しています。

$${
unset(@#xpos[]);
unset(@#ypos[]);
unset(@#zpos[]);
}$$

unset(<配列>); で配列の中身を一掃します。
保存された座標は、別のワールドにも引き継がれてしまうので、知らない場所にテレポートしてしまわないようにログイン時に消しておきましょう。

プレイヤーを選んでテレポートできるやつの中身

おまけですね。上の説明を読んだ後ならそれなりに仕組みは分かるはず…?
$$uでプレイヤー選択欄を表示することができます。
プレイヤーを選択してテレポートして、その際に座標を保存する仕組みです。

$${
echo(/tp $$u);

@#xpos[]=%XPOS%;
@#ypos[]=%YPOS%;
@#zpos[]=%ZPOS%;
}$$

最後に

ということで、細かい解説も含めこれらの処理の上でTpBackが一通り機能するようになっています…!
長文、難解で教科書みたいな記事になってしまいましたが、少しでも需要に届いていれば嬉しいです。個人的にもいつか解説は書きたいなと思っていたのでタイミングが合ってラッキーでした。
では、よりよいマクロライフをーーー!

この記事が気に入ったらサポートをしてみませんか?