石橋を叩いて壊すページ

bukkitでplayerがブロックの上に乗った場合を検出する

いただいたご質問の返信として。
自分もプラグイン作り始めて2週間くらいの初心者なので
他にもっと有用な方法が無いかも探してみてくださいね。

今ほしいのですが、playerがブロックの上に乗った場合のevent?ソースコード?がないのでコメントさしてもらいました。
それは何か教えてくださいお願いします

「プレイヤーがブロックの上に乗った」というBukkitイベントはないと思うので、
「プレイヤーが移動した」という"PlayerMoveEvent"を使用しつつ
その移動先が目標ブロックの上かどうかを調べることになると思う。

ソースコードは以下。
「プレイヤーがレッドストーンブロックの上に立ったらサーバーメッセージを流す」ように書いてみた。

package jp.jias.bukkit;

import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Entity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.plugin.java.JavaPlugin;

public class TestPlugin extends JavaPlugin implements Listener {

    /**
     * プラグインが開始するとき呼び出される
     */
    public void onEnable() {

        // イベントリスナーを登録
        getServer().getPluginManager().registerEvents(this, this);
        
    }

    /**
     * プラグインが終了するとき呼び出される
     */
    public void onDisable() {

    }

    /**
     * プレイヤーが移動したとき呼び出される
     * @param e 
     */
    @EventHandler(ignoreCancelled = true)
    public void onPlayerMoveEvent(PlayerMoveEvent e) {
        
        //プレイヤーは地面に立っているか
        if(((Entity)e.getPlayer()).isOnGround())
        {
            //移動先の座標を得る
            Location loc=e.getTo();
            
            //座標を10センチ下に移動する
            loc.add(0,-0.1,0);
            
            //その座標にはレッドストーンブロックがあるか
            if(loc.getBlock().getType().equals(Material.REDSTONE_BLOCK))
            {
                getServer().broadcastMessage("§9"+e.getPlayer().getName()+"は今、レッドストーンブロックの上に立ちつくした!");
            }
        }
    }
}

まずonPlayerMoveEventメソッドでPlayerMoveEvent(プレイヤーが移動した)イベントを捕まえる。
つぎにプレイヤーが今地面の上に立っているのかを確認するためisOnGround()メソッドでtrueが返ることを確認する。
最後に、プレイヤーの足元10センチ下のところに何があるか確認し、
レッドストーンブロックであればサーバーメッセージを流している。

ハーフブロックの高さが50センチなので、今回は「10センチ」下のブロックを判定基準にしてみた。
50センチより大きな数字を使ってしまうと、ハーフブロックの上に立ったとき、
ハーフブロックの高さをすり抜けて、その下にあるブロックを判定基準にしてしまう。

ところで、Entity#isOnGround()メソッドについてひとつ気になったので補足。
メソッドの説明には「This value is a state updated by the server and is not recalculated unless the entity moves.」
(この値はエンティティが移動しない限り再計算されない)と書かれていて、実際ためしたところ
「ブロックの上でジャンプして、ブロックにまっすぐ着地した場合」に、isOnGround()がfalseを返してしまう。
次に一歩歩こうとした段階で、再計算されて、isOnGround()がtrueを返し始める。
このため、ジャンプや飛行から着地した瞬間を見定めるには上記では足らない。

このあたりをもっと厳密にチェックしたい場合は、isOnGround()を使わずに
プレイヤーの位置のY座標を見て地面から1ミリ以上浮いていないことを確認して
ついでにクリエイティブで飛行中でないことを確認するためPlayer#isFlying()でfalseが返ることを確認する…
とか色々試行錯誤が必要になるかと思う。

ご不明な点があればまたコメント下さい。

この記事を評価

この記事にコメント

  1. ...

【この記事にコメント】
お名前:
コメント:

Menu