【不動の杖】

「不動の杖」の使い方

杖をメインハンドに持った状態で右クリックすると以下のように範囲内の相手を動けないようにします。
牛のモーションがないので少し分かり辛いですが強制的に座らせて足止めしています。


その状態で以下のように「ダッシュ+スニーク」を実行すると術中の相手を浮遊させる事ができます。


そしてある程度の高さになってからもう一度杖を使うと浮遊状態が解除されますので、以下のように落下ダメージで倒す事ができます。


攻撃力は鉄の剣並みなので、以下のように足止めした状態でも比較的サクっと倒せます。


足止め(右クリック)と浮遊発動(ダッシュ+スニーク)の射程距離は共に10ブロックですが、浮遊解除の射程制限はありません。

「不動の杖」の取得

本環境のビヘイビアパック/リソースパックなどのアドオンパックを適用しておけば、以下の方法で「不動の杖」が手に入ります。

クラフトする場合

▼必要な素材


▼レシピパターン


ショップで購入する場合

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

コマンドで取得する場合

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

サーバー側の実装


右クリック時の足止め

今まで実装したアイテムと同様に今回の実装でも"ItemUsed"というサブスクライブイベントを使用しています。
マインクラフト上でアイテムを使ったと認識されると発生するイベントのようで、フレームワークを使って以下の内容を実装しています。

※サブスクライブイベントの処理内容については>> こちらでご紹介しています。
「不動の杖」を使った時に発生するイベントデータの形式
{
    "body":
    {
        "count":<数字>,
        "item":
        {
            "aux":<数字>,
            "id":"immovable-rod",
            "namespace":"customize"
        },
        "player":
        {
            "color":<16進数?>,
            "dimension":<数字>,
            "id":<数字>,
            "name":<文字列>,
            "position":
            {
                "x":<数字>,
                "y":<数字>,
                "z":<数字>
            },
            "type":<文字列>,
            "variant":<数字>,
            "yRot":<数字>
        },
        "useMethod":<数字>
    },
    "header":
    {
        "eventName":"ItemUsed",
        "messagePurpose":<文字列>,
        "version":<数字>
    }
}
                    
今回はデータ値を使用していないのでアイテムID("immovable-rod")を参照してアイテムの使用を判断しています。

また、▶階段チェアの実装時に使っていたモブの搭乗が可能なダミーエンティティを使ってコントロールしています。
足止め発動時の処理の流れは以下の通りです。
1)召喚済みのダミーエンティティを消去(デスポーン)
タグをセレクターとしてkillコマンドを発行
2)モブが搭乗可能なダミーエンティティを足元へ召喚
サーバーから10ブロックの範囲指定でsummonコマンドを発行
3)召喚したダミーエンティティへタグを付与
サーバーからtagコマンドを発行
1)のデスポーンの処理には以下の2つの意味があります。
ダミーエンティティの数の制限
範囲指定なしでデスポーンする事によりワールド上で一定以上増えないようにする
浮遊解除
範囲指定なしでデスポーンする事により浮遊中の相手の浮遊状態を解除できる

「ダッシュ+スニーク」時の浮遊発動

▶スウィープロッド(範囲攻撃)の実装で使っていた"PlayerTravelled"というサブスクライブイベントを使用しています。
travelMethodの値(7:スニーク、8:ダッシュ)をみてそのイベントがスニークなのかダッシュなのかを判断できるようになっています。

スニーク or ダッシュ時に発生するイベントデータの形式
{
    "body":
    {
        "isUnderwater":<ブール値>,
        "metersTravelled":<数字>,
        "newBiome":<数字>,
        "player":
        {
            "color":<16進数?>,
            "dimension":<数字>,
            "id":<数字>,
            "name":<文字列>,
            "position":
            {
                "x":<数字>,
                "y":<数字>,
                "z":<数字>
            },
            "type":<文字列>,
            "variant":<数字>,
            "yRot":<数字>
        },
        "travelMethod":7(スニーク) or 8(ダッシュ)
    },
    "header":
    {
        "eventName":"PlayerTravelled",
        "messagePurpose":<文字列>,
        "version":<数字>
    }
}
                    

ダミーエンティティには物理法則を適用していないので、上記のイベントを受信した時にdamageコマンドでノックバックを発動させる事により、慣性による浮遊状態が働いています。

以上の事を踏まえて今回は以下のように実装しています。


キューとステータスUNITの登録

今回は「いなずまの弓」と「スウィープロッド(範囲攻撃)」の処理をそのまま使っているので追加分はありません。


新規実装箇所

受信したイベントデータをコマンド名へ変換する処理を以下のコマンドディスパッチャーへ追加します。
※ここではimmovable_rodというアイテム名を検知しています。
※以下の黄色の部分が今回追加したところです。
app/InitClass/InitForMinecraft.php
public function getCommandDispatcher()
{
    return function(ParameterForMinecraft $p_param, $p_dat): ?string
    {
        $minecraft = $p_param->isMinecraft();
        if($minecraft === true)
        {
            ・
            ・
            ・
            if(isset($p_dat['data']['header']['eventName']) && $p_dat['data']['header']['eventName'] === 'ItemUsed')
            {
                // 弓イベントの場合
                if($p_dat['data']['body']['item']['id'] === 'bow')
                {
                    return CommandQueueEnumForMinecraft::ITEM_USED->value;
                }

                // 矢イベントの場合
                if($p_dat['data']['body']['item']['id'] === 'arrow')
                {
                    return CommandQueueEnumForMinecraft::ITEM_USED->value;
                }

                // 「いなずまの剣」イベントの場合
                if($p_dat['data']['body']['item']['id'] === 'thunder_sword' || $p_dat['data']['body']['item']['id'] === 'thunder_sword_revised')
                {
                    return CommandQueueEnumForMinecraft::ITEM_USED->value;
                }


                // 「不動の杖」イベントの場合
                if($p_dat['data']['body']['item']['id'] === 'immovable_rod')
                {
                    return CommandQueueEnumForMinecraft::ITEM_USED->value;
                }

            }
            ・
            ・
            ・
        }
    }
}
                    

「いなずまの弓」を実装した時のUNIT処理に以下の内容を追加しています。
※以下の黄色の部分が今回追加したところです。
app/CommandUnits/CommandForMinecraft.php
protected function getItemUsedStart()
{
    return function(ParameterForMinecraft $p_param): ?string
    {
        ・
        ・
        ・

        if($rcv['data']['body']['item']['id'] === 'immovable_rod')
        {
            // コマンド送信(immovableエンティティのkill)
            $cmd_data = $p_param->getCommandDataForKillImmovable($rcv['data']['body']['player']['name']);
            $data =
            [
                'data' => $cmd_data
            ];
            $p_param->setSendStack($data);

            // コマンド送信(足止め発動)
            $cmd_data = $p_param->getCommandDataForImmovable($rcv['data']['body']['player']['name']);
            $data =
            [
                'data' => $cmd_data
            ];
            $p_param->setSendStack($data);

            // コマンド送信(タグの付与)
            $cmd_data = $p_param->getCommandDataForTagImmovable($rcv['data']['body']['player']['name']);
            $data =
            [
                'data' => $cmd_data
            ];
            $p_param->setSendStack($data);

            return null;
        }

        ・
        ・
        ・
    };
}
                    

範囲攻撃実行のUNIT処理に以下の内容を追加しています。
※以下の黄色の部分が今回追加したところです。
app/CommandUnits/CommandForMinecraft.php
protected function getMinecraftPlayerDashStart()
{
    return function(ParameterForMinecraft $p_param): ?string
    {
        $p_param->logWriter('debug', ['MINECRAFT PLAYER_DASH:START' => 'START']);

        // 受信データの取得
        $rcv = $p_param->getRecvData();

        // 「スウィープロッド(範囲攻撃)」実行のコマンド送信
        $cmd_data = $p_param->getCommandDataForSweepRod($rcv['data']['body']['player']['name']);
        $data =
        [
            'data' => $cmd_data
        ];
        $p_param->setSendStack($data);

        // 「いなずまの剣改」実行のコマンド送信
        $cmd_data = $p_param->getCommandDataForThunderSwordRevised($rcv['data']['body']['player']['name']);
        $data =
        [
            'data' => $cmd_data
        ];
        $p_param->setSendStack($data);


        // 「不動の杖」実行のコマンド送信
        $cmd_data = $p_param->getCommandDataForFloatingByImmovableRod($rcv['data']['body']['player']['name']);
        $data =
        [
            'data' => $cmd_data
        ];
        $p_param->setSendStack($data);


        return null;
    };
}
                    

おわりに

今回のタグ付けはプレイヤーのマインクラフトアカウント名を使って付与しているので、基本的に他のプレイヤーと被る事はありませんが、同時使用で発動領域が被る時には先勝ち発動となります。
ダミーエンティティをデスポーンする時もユニークタグをセレクターとしているので、他のプレイヤーが使用中にデスポーンさせられる心配もありません。
発動領域が被って先勝ち発動したとしても足止めや浮遊の目的で使用するので大きな問題になる事はないでしょう。