石橋を叩いて壊すブログ

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が返ることを確認する…
とか色々試行錯誤が必要になるかと思う。

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

この記事を評価

50 29

コメント

  1. 【muu6012】 まや僕なのですが、作って欲しいプラグインがあるんです、僕じゃあ絶対無理ですwのでお願いしますm(_ _)m スカイプ&TwitterID:muu6012 です [2013/8/12 03:58]
  2. 【石橋】 すいません、依頼は付けつけてません。 [2013/8/12 11:00]
  3. 【muu6012】 わかりましたm(_ _)m [2013/8/12 13:54]
  4. 【ankou2525】 このイベント実装したんですが、1回通ると何個もメッセージ表示でますよね?それを1回とおるたびに1回だけメッセージを表示をしたいんですが、どうするんでしょうか? [2014/1/7 12:48]
  5. 【石橋】 前回と同じブロックの上に立っている場合はメッセージを抑止する、というのがいいんじゃないかな。Location#getBlock()を使ってBlockオブジェクトを取得する。次回もう一度同じイベントが着たら、また同様にBlockオブジェクトを取得する。2回のBlockが同じオブジェクトなら、同じブロックの上を移動したと判断してメッセージを出さない。とか。 [2014/1/7 14:09]
  6. 【qpwakaba】 PlayerMoveEventの場合、ピストンとかで押された場合に発生しないので、1Tickごとに判定してもいいかなと思います。 [2014/1/21 17:21]
  7. 【ゲスト】 イベントなんて作ればいいさ [2014/2/15 00:33]
  8. 【ブルー】 初めまして、ブルーという者です。
    このページにあるコードを一部改変(レッドストーンブロックを鉄ブロックに変更)してサーバーで実行したのですが、首を回す(マウスを動かした状態)だけで下のブロックに対するあたり判定が消え、地中に生き埋めになってしまいました。
    原因がわからず、この原理を応用したプラグインが作成できず、困っており、ぜひ解決方法などをご教示いただければ幸いです。
    参考動画:o2.upup.be/A0yezxnN4M(httpを抜いています) [2016/8/27 03:19]
  9. 【石橋】 ブルーさんこんにちは。確認しました。たしかに地面に沈みますね。
    以下のように、コードを1行書き換えてみてください。

    //移動先の座標を得る
    Location loc=e.getTo().clone(); //←「.clone()」の部分を追加

    おそらくですが、e.getTo()が、以前はプレイヤーの座標をコピーしたLocationオブジェクトを返してきていたところ、
    処理速度の向上目的かなにかで、プレイヤーの座標そのものを返すようになり、それをloc.add(0,-0.1,0);してしまったためにプレイヤーを10センチ沈ませたんだと思います。
    「.clone()」を追加することで、座標をコピーしたLocationオブジェクトが返されるようになるので、記事記載時点の挙動に治ります。 [2016/8/29 22:10]
  10. 【ブルー】 返信ありがとうございます。
    ご指摘くださった部分を書き換えたところ、無事に問題を解決することができました。
    ありがとうございました。 [2016/8/30 18:27]

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

295,349

記事カテゴリー

最近の記事

  1. FF14を翻訳したら国によって結構特色が違った[12/11]
  2. ゼロから始めるFactorioの回路構築(実践例編)[7/24]
  3. ゼロから始めるFactorioの回路構築(条件回路・論理演算編)[7/24]
  4. ゼロから始めるFactorioの回路構築(定数回路・算術回路編)[7/24]
  5. ゼロから始めるFactorioの回路構築(入力・出力・混合編)[7/24]

RSS1.0 RSS2.0

最近のコメント

  1. おー、お役に立てたようでなによりです。再起…[9/11]
  2. この記事が非常の役立ちました。おかげさまで…[9/9]
  3. 1.14.2のAPIで試しましたが、MapInitializeEv…[9/9]
  4. 天晴れ!押したらポーションのモヤモヤでまし…[5/26]
  5. 習うより慣れろって感じで。この記事は記事冒…[4/7]

記事を検索


管理人

石橋

パソコンデスクは座椅子