【マインクラフト（統合版）】Websocketサーバーを使って「スタンドの弓矢」を作ってみました

# はじめに

今回の実装アイテムはジ〇ジョネタです。
以下のように「スタンドの弓」で矢を放つと．．．

![スタンド召喚](https://socket-manager.github.io/document/minecraft-contents/img/stand/stand-summon.gif "スタンド召喚")

矢を放った場所にスタンドが現れます。知る人ぞ知るエージェント君ですｗ

このスタンド召喚の仕組みは矢のアイテムシリーズである「いなずまの矢」「はかいの矢」「機雷の弓」の以下のページでご紹介したものを応用しています。

https://qiita.com/glasses_seven/items/a34873dfb559e49d5095/

https://qiita.com/glasses_seven/items/98ea8e43b406f75c41df/

https://qiita.com/glasses_seven/items/294da5d23bd2e894f7d0/

ジ〇ジョの作中の使い方とは異なりますが「スタンドの弓矢」を使うと以下の２つの役割を持たせる事ができます。

<dl>
    <dt>1)荷物の輸送</dt>
    <dt>2)スタンド攻撃</dt>
</dl>

それでは順を追って使い方を説明していきます。


# 動作環境

<dl>
    <dt>プラットフォーム</dt>
    <dd>Windows10</dd>
    <dt>マインクラフト（統合版）</dt>
    <dd>Windows Edition v1.21.2</dd>
    <dt>socket-manager</dt>
    <dd>v1.13.3</dd>
    <dt>言語</dt>
    <dd>PHP v8.2.4（v8.1.0以降）</dd>
</dl>


# 荷物の輸送

エージェントにはインベントリが存在しますので右クリックすると以下のようにインベントリが開きます。

<img src="https://socket-manager.github.io/document/minecraft-contents/img/stand/inventory.png" height="600px" width="728px" />

アイテムを取り出したり格納したりする時には「スタンドの弓」を使ってスタンドを好きな位置に召喚してから使います。

一度スタンドを召喚すると以下のように「ネザー」や「エンド」でもついてきてくれますので、あらゆるところで召喚できるエンダーチェストのように使う事ができます。

エージェントは無敵なので他のモブに倒される心配はありません。
常に浮いているので奈落に落ちる心配もありません。
溶岩に浸かってもダメージを受けません。

<img src="https://socket-manager.github.io/document/minecraft-contents/img/stand/nether.png" height="600px" width="728px" /><br />
<img src="https://socket-manager.github.io/document/minecraft-contents/img/stand/end.png" height="600px" width="728px" />

:::note info
「いなずまの矢」や「はかいの矢」などの特殊機能が付与されている矢は、それぞれの機能が発動してしまうので使えません。
:::


# 「スタンドの弓」の取得

socket-manager環境のビヘイビアパック／リソースパックなどのアドオンパックを適用しておけば、以下の方法でユニークアイテムとして「スタンドの弓」が手に入ります。

### ショップで購入する場合

以下のショップで購入できます。

https://qiita.com/glasses_seven/items/e77bfb43baf55e35680b/

### コマンドで取得する場合

以下はワールドオーナーやシステム組み込み用としてコマンドで取得する方法です。

<img src="https://socket-manager.github.io/document/minecraft-contents/img/stand/command-bow.png" height="600px" width="728px">

<img src="https://socket-manager.github.io/document/minecraft-contents/img/stand/get-bow.png" height="600px" width="728px">

あとはsocket-managerでWebsocketサーバーを起動後、マインクラフトからの接続が完了すれば「スタンドの弓」を含めた各種コンテンツが使えるようになります。

:::note info
socket-managerの導入方法やアドオンパックの所在については以下のページでご紹介していますのでご興味のある方はご覧ください。
:::

https://qiita.com/glasses_seven/items/433ac9d9fcbdb72c6d18/

:::note info
アドオンパックの適用方法については以下のページでご紹介しています。
:::

https://qiita.com/glasses_seven/items/a7d276b44c9437e7b0a4/


# スタンド攻撃

弓は何を使っても構いませんが、スタンドを攻撃モードにするには「スタンドの矢」が必要です。

この矢を以下のように攻撃対象へ放つと地中を移動しながらスタンドが攻撃を始め、相手がデスポーンするまで継続します。

<img src="https://socket-manager.github.io/document/minecraft-contents/img/stand/attack1.gif" />

矢は攻撃対象へ命中しなくても以下のように近くを横切るだけでも発動します。

<img src="https://socket-manager.github.io/document/minecraft-contents/img/stand/attack2.gif" />

射程距離は１０ブロックですが攻撃中にプレイヤーからの射程距離から外れると攻撃を停止します。その場合は再度近づいてから矢を放ってください。


# 「スタンドの矢」の取得

socket-manager環境のビヘイビアパック／リソースパックなどのアドオンパックを適用しておけば、以下の方法でユニークアイテムとして「スタンドの矢」が手に入ります。

### ショップで購入する場合

以下のショップで購入できます。

https://qiita.com/glasses_seven/items/e77bfb43baf55e35680b/

### コマンドで取得する場合

以下はワールドオーナーやシステム組み込み用としてコマンドで取得する方法です。

<img src="https://socket-manager.github.io/document/minecraft-contents/img/stand/command-arrow.png" height="600px" width="728px">

<img src="https://socket-manager.github.io/document/minecraft-contents/img/stand/get-arrow.png" height="600px" width="728px">

あとはsocket-managerでWebsocketサーバーを起動後、マインクラフトからの接続が完了すれば「スタンドの矢」を含めた各種コンテンツが使えるようになります。


# サーバー側の実装

他の弓矢のアイテムと同様に"ItemUsed"のサブスクライブイベントを使用しています。

:::note info
サブスクライブイベントの処理内容については以下のページでご紹介しています。
:::

https://socket-manager.github.io/document/extra-minecraft.html

スタンド召喚時の仕組みは「いなずまの矢」や「はかいの矢」とほぼ変わりません。最後に`summon`コマンドで雷やエンドクリスタルを呼び出していたところをエージェントの移動コマンドに置き換えただけです。

また、スタンド攻撃時も含めて今回はWebsocketサーバーでしか使う事ができない以下の隠しコマンドを使用しています。

```text:隠しコマンド
> agent tp <coordinates>              エージェントの移動
> agent attack <direction>            エージェントによる攻撃
> querytarget <target selectors>      ターゲットエンティティの状態を取得する
```

スタンド攻撃時は大まかに分けると以下の処理フローで実装しています。

<dl>
    <dt>1)攻撃対象のモブに対して「スタンドの矢」を放つ</dt>
    <dt>2)攻撃対象のモブに対してタグを付与する</dt>
    <dt>3)攻撃対象のタグを持っているモブに対してエージェントを移動して攻撃をしかける</dt>
    <dt>4)攻撃対象のタグを持っているモブがデスポーンしているか検査する</dt>
</dl>

上記4)の検査でデスポーンしていなければ3)以降を繰り返しています。
上記2)でタグを付与する時には攻撃対象を特定するために座標計算用の矢をスポーンさせていますが、その計算ロジックは「いなずまの弓」を作った時と全く同じものを使っています。

実装内容の詳細は他のコンテンツも含めて以下のページでご紹介していますのでご興味のある方はご覧ください。

https://socket-manager.github.io/document/minecraft-contents/stand.html


# おわりに

エージェントはエンティティとして認識されないばかりかWebsocketサーバーからのみコントロールできるものなので扱いが少し複雑です。

`function`コマンドでの利用はできますがWebsocketサーバーがトリガーになっていないリピート利用や再帰コールも不可能です。

そのためスタンド攻撃で相手がデスポーンした事を検出するために隠しコマンドである`querytarget`を利用しています。

いずれにしてもワールド負荷に直結するリピート利用は極力避けるようにしているので結果オーライといったところです。

:::note info
今回の実装は以下ページの機能を使ってテストしています。
:::

https://qiita.com/glasses_seven/items/df5bc779d2cc6aff2d9f