【Spigot】Bukkitプラグインの作り方講座 – プレイヤーの移動と回転の検出
今回は、プレイヤーの移動と回転を検出する方法を紹介します。
※バージョン1.16時点の情報です。異なるバージョンでは対応できない場合があります。
PlayerMoveEvent
PlayerMoveEventを使うと、プレイヤーの移動や回転を検出できます。
このイベントは、プレイヤーの移動、落下、回転、エリトラの飛行、エンティティに押されるとき、ノックバックにより移動するときに実行されます。
プレイヤーの座標は足元です。
スニークしてもプレイヤーの座標は変わりません。
また、プレイヤーが死亡してもリスポーンするまで座標は変わりません。
できること
- プレイヤーの取得:
e.getPlayer()
移動前のLocation(座標と向き)の取得:
e.getFrom()
- 移動前のLocation(座標と向き)の設定:
e.setFrom(Location)
- 移動先のLocation(位置と向き)の取得:
e.getTo()
- 移動先のLocation(座標と向き)の設定:
e.setTo(Location)
- イベントが取り消されたか:
e.getCancelled()
- イベントを取り消すか設定:
e.setCancelled(boolean)
プレイヤーの移動と回転をキャンセルする
@EventHandler
public void onPlayerMove(PlayerMoveEvent e) {
if (e.getPlayer().isSneaking())
e.setCancelled(true);
}
プレイヤーがスニークしているときは動けなくなります。
移動だけできないようにする(回転はできるようにする)
@EventHandler
public void onPlayerMove(PlayerMoveEvent e) {
if (e.getPlayer().isSneaking()) {
Location from = e.getFrom();
Location to = Objects.requireNonNull(e.getTo());
from.setYaw(to.getYaw());
from.setPitch(to.getPitch());
e.setTo(from);
}
}
プレイヤーがスニークしているときは向きは変えられますが、移動ができなくなります。
PlayerMoveEventが実行されない場合
PlayerMoveEventは次の場合では実行されません。
- ログインするとき→PlayerJoinEvent
- ログアウトするとき→PlayerQuitEvent
- テレポートするとき→PlayerTeleportEvent
- リスポーンするとき→PlayerRespawnEvent
- ピストン、粘着ピストンにより押されるとき(ブロックを間に挟む場合も含む)→BlockPistonExtendEventで検出できるが、押し出されるエンティティはかんたんに検出できない
- シュルカーボックスにより上方向に押されるとき(横方向では実行される)
- 乗り物の乗り降りによる移動→VehicleEnterEvent、VehicleExitEvent、EntityDeathEvent(VehicleExitEventでは乗っているトロッコ、ボートが壊れた場合も実行されますが、乗っている動物[ブタ、ウマ、ロバ、ラバ、ラマ、商人のラマ、ストライダー=LivingEntity?]が死亡した場合は実行されないため、EntityDeathEventを使う必要があります)
次の場合は1.16では動作しませんが、1.8などでは動作する場合があります。
- トロッコに乗っているとき
- ボートに乗っているときにプレイヤーが回転するとき
- ニンジン付きの棒を手に持っていないときにブタに乗っているとき
- 鞍(サドル)をつけていないウマ、ロバ、ラバに乗っているときにプレイヤーが回転するとき
- ラマ、商人のラマに乗っているとき
- 歪んだキノコ付きの棒を手に持っていない状態でストライダーに乗っているとき
乗り物が移動してる場合はVehicleMoveEventを使うと検出できますが、
乗っている状態でプレイヤーが回転するのを検出する場合など、
Eventシステムでかんたんに検出できないものは、全プレイヤーを総当りする必要があります。
その場合は、プレイヤーが少ない場合はスケジュールシステムを使用してTick毎に、乗り物が少ない場合はVehicleUpdateEventを使用すると良いでしょう。
また、VehicleMoveEventは、プレイヤーがトロッコに乗ったブタに乗っているときに移動しても実行されません。