石橋を叩いて壊すページ

bukkitのWorldクラスがなかなか面白い

ちょっと練習にと、指定したアイテムIDのアイテムを生成してプレイヤーの位置からぶん投げるコードを書くことにした。
アイテムを無から生み出すには…どうやらWorldクラスの以下を使えばいいらしい。

Item dropItem(Location location, ItemStack item)
指定された場所にアイテムをドロップします。

そこでこういうコードを書いてみた。

//チャットコマンドが実行された時に呼び出される
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args){
    
    //コマンドを実行したプレイヤーを特定する
    Player player=null;
    for(Player p : getServer().getOnlinePlayers())
    {
        //現在オンラインのPlayerの一覧から、コマンド実行者と同じ名前の者を探す
        if(p.getName().equals(sender.getName()))
        {
            player=p;
            break;
        }
    }

    //万一プレイヤーを特定できなかったら失敗
    if(player==null)
    {
        log.warning("コマンドを実行したプレイヤー(" + sender.getName() + ")を特定できませんでした。");
        return false;
    }

    //アイテムを投げる「throw」コマンド
    //引数は2つ、アイテムIDと数量を指定する
    if(cmd.getName().equalsIgnoreCase("throw")){ 

        //引数は2つか
        if(args.length==2)
        {
            //引数1:アイテムIDを整数にする(文字列が空文字だったら?は練習と割り切って無視する)
            int id=Integer.parseInt(args[0]);

            //引数2:アイテム数量を整数にする(同上)
            int num=Integer.parseInt(args[1]);

            //プレイヤーの座標を取得    
            Location pos=player.getLocation();

            //アイテムを生成し世界へ落とす
            player.getWorld().dropItem(pos,new ItemStack(id,num));

            //プレイヤーにメッセージを送る
            player.sendMessage("あなたにアイテムを与えました。");

            return true;
        }
    }
}

これで、目の前にアイテムを落とすことができる。
あくまで目の前なので、アイテムが生成された直後にアイテムはプレイヤーに拾われる。

どうやら、「世界にアイテムを落とす」には、Worldクラスを使えばいいようだ。
見回してみたらいろいろ面白いものを見つけた。

boolean createExplosion(double x, double y, double z, float power, boolean setFire, boolean breakBlocks)
指定した座標で指定したパワーの爆発を作成する。爆発後の火災の発生と、爆発によりブロックを破壊するかを設定できる。

爆発でブロックが壊れないように設定できる。
爆発が起きたときのイベントEntityExplodeEventでイベントをsetCancelledし、
代わりに同じパワーの、ブロックを壊さない爆発を起こせば、マップの破壊を阻止できる。

void loadChunk(int x, int z)
指定された座標のチャンクを読み込む。

チャンクが作成されていない場合は作成する効果がある。
チャンクの生成はマルチプレイの中でも負荷のかかる処理なので、あらかじめまとめて生成しておけば
プレイ中の負荷やバージョンの壁を解消できるかもしれない。
でも生成しすぎると、新しいブロックが実装されたときどこにもないなんて展開もありうる。

いくつか使ってみたなかで、1点気になったのが以下。

Collection<T> getEntitiesByClass(Class<T> cls)
指定したクラス/インターフェイスと一致するこの世界のすべてのエンティティのコレクションを取得する。

たとえばgetEntitiesByClass(Wither.class)などと指定するとその世界のすべてのウィザーを取得できる…
はずなのだが、どうもチャンクが読み込まれてないと空のリストが返ってくるようだ。
ワープした直後などは空のリストが返ってきやすいので、使いどころは気をつけたほうがよさそう。

この記事を評価

この記事にコメント

  1. ...

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

Menu