2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Kotlin+Spigot】2.3 プレイヤーの頭を取得する

Last updated at Posted at 2020-05-01

0. 初めに

build.gradleplugin.yml の設定は終わらせた前提で進めます。
プロジェクトを作成する を参考にメインクラスを作るまで終わらせておいてください。

また、コマンドを作成して進めていきます。
詳しい説明は 2.2 コマンドを新しく作る でしていますので省略します。

1. plugin.yml にコマンドを登録する

commands:
  head:
    usage: "/<command> [Player]"
    description: "プレイヤーの頭を取得します"
    permission: minecraft.command.give

このようなコマンドを登録しておきます。一番初めの引数はプレイヤーのIDです。
これは /give の拡張コマンドです。実行に minecraft.command.give という権限を必要としています。

2. 準備をする

コマンド処理のところで、メッセージに色をつけたいので getColored 関数を実装しておきましょう。詳しくは こちら

Util.kt
object Util {
    fun getColored(text: String): String {
        return ChatColor.translateAlternateColorCodes('&', text)
    }
}

さあ、プレイヤーの頭を取得する関数を作りましょう。
それも Util に実装しましょう。プレイヤーの頭というアイテムは ItemStack というクラスになります。
任意のプレイヤーの頭を取得するので、プレイヤーを引数としておきます。

    fun getPlayerHead(player: OfflinePlayer): ItemStack {
        
    }

実際の処理を書いていきましょう。
まず、アイテム(ItemStack)を作成します。

    fun getPlayerHead(player: OfflinePlayer): ItemStack {
        val head = ItemStack(Material.PLAYER_HEAD)

    }

ItemStack の中には ItemMeta というアイテムのデータが入っています。
それを一度、変数として保持しておきましょう。

    fun getPlayerHead(player: OfflinePlayer): ItemStack {
        val head = ItemStack(Material.PLAYER_HEAD)
        val meta = head.itemMeta

    }

アイテムのデータと言っても、アイテムの種類(Material)によって固有の設定というものが存在しています。
今回は PLAYER_HEAD 、答えから言うと SkullMeta という固有の設定があります。
また、SkullMeta というものは ItemMeta の拡張になっています。
要するに metaSkullMeta であれば 固有の設定 も行える のです。

    fun getPlayerHead(player: OfflinePlayer): ItemStack {
        val head = ItemStack(Material.PLAYER_HEAD)
        val meta = head.itemMeta
        if(meta is SkullMeta){

        }
    }

では、頭の見た目を変えてみましょう。

    fun getPlayerHead(player: OfflinePlayer): ItemStack {
        val head = ItemStack(Material.PLAYER_HEAD)
        val meta = head.itemMeta
        if(meta is SkullMeta){
            meta.owningPlayer = player
            head.itemMeta = meta
        }
    }

owningPlayer という値を書き換えると見た目がそのプレイヤーになります。
しかし、設定を変えたらそれをアイテムに反映する必要があります
そのため、アイテムメタに対して代入しています。
残りは、head を戻り値とするだけです。

    fun getPlayerHead(player: OfflinePlayer): ItemStack {
        val head = ItemStack(Material.PLAYER_HEAD)
        val meta = head.itemMeta
        if(meta is SkullMeta){
            meta.owningPlayer = player
            head.itemMeta = meta
        }
        return head
    }

これで完成になります。

3. コマンドの処理を書く

CommandExecutor を継承した GetHeadCommand というオブジェクトを作成します。
image.png

実行したプレイヤーが頭を取得する仕様にしましょう。
その場合、コンソールから実行することは出来ません。言い換えると プレイヤーのみ実行可能 です。
その条件分岐を書きましょう。

    override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
        if(sender is Player){
            
        } else {
            sender.sendMessage(getColored("&cプレイヤーからのみ実行できるコマンドです"))
        }
        return true
    }

Player に対してのみ処理をしたいので is を使います。
if の中括弧の中であれば senderPlayer として扱われます。

次に、コマンド引数の処理をしましょう。(一番最初の引数がプレイヤーのIDです。)
args には引数が全て入っていますが、これが空っぽだったら、プレイヤーのIDは入力されていません。

        if(sender is Player){
            if(args.isNotEmpty()){
                
            } else {
                sender.sendMessage(getColored("&c頭を取得するプレイヤーのIDを入力してください"))
            }
        }

args.isNotEmpty() というのは 0 < args.size と書いても正しいですが、isNotEmpty を使うことを IDE が推奨してくると思います。
一番最初の引数と表現していましたが、それは args の何番目でしょう?
正解は、0 です。これを間違えるとおかしくなってしまうので覚えておきましょう。
では、0番目の引数を一旦変数に保存しておきましょう。

        if(sender is Player){
            if(args.isNotEmpty()){
                val id = args[0]

            } else {
                sender.sendMessage(getColored("&c頭を取得するプレイヤーのIDを入力してください"))
            }
        }

そのまま、プレイヤーの取得をしましょう。
オンラインプレイヤー以外の頭も取得できるようにしたいので、getOfflinePlayer を使います。

        if(sender is Player){
            if(args.isNotEmpty()){
                val id = args[0]
                val player = Bukkit.getOfflinePlayer(id)
            } else {
                sender.sendMessage(getColored("&c頭を取得するプレイヤーのIDを入力してください"))
            }
        }

そうするとこのように、取り消し線がかかれると思います。
image.png
非推奨関数と言って、「あまり使わないほうがいいよ」といった意味です。
getOfflinePlayer(String) というものが非推奨になっているのは、プレイヤーのIDが変更可能だからです。
例えば、データを保存するという時にIDを使っていると、データが消えてしまいます。
そういった場合には UUID を使いましょう。しかし、今回は問題ありません。
このまま無視してしまうと毎回警告が出るので、出ないようにしておきましょう。

取り消し線の上で右クリック → Inspection 'DEPRECATION' options... for val を選択。
image.png
そうすると、このようになると思います。
image.png
@抑制する("非推奨") こんなような意味です。
注意しなければいけないのは、非推奨であったということ。その使い方が間違えではないかを考えて使いましょう。

では、先ほど作成した getPlayerHead を使ってプレイヤーの頭を取得しましょう。

            if(args.isNotEmpty()){
                val id = args[0]
                @Suppress("DEPRECATION") val player = Bukkit.getOfflinePlayer(id)
                val head = getPlayerHead(player)
                
            }

これを sender に渡します。言い換えると、インベントリにアイテムを追加します。
ついでに、メッセージも送信しておきましょう。

            if(args.isNotEmpty()){
                val id = args[0]
                @Suppress("DEPRECATION") val player = Bukkit.getOfflinePlayer(id)
                val head = getPlayerHead(player)
                sender.inventory.addItem(head)
                sender.sendMessage(getColored("&b${player.name} &fの頭を取得しました"))
            }

これでコマンドの処理は書き終わりました。

完成するとこんな風になっていると思います。

GetHead.kt
object GetHeadCommand: CommandExecutor {
    override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
        if(sender is Player){
            if(args.isNotEmpty()){
                val id = args[0]
                @Suppress("DEPRECATION") val player = Bukkit.getOfflinePlayer(id)
                val head = getPlayerHead(player)
                sender.inventory.addItem(head)
                sender.sendMessage(getColored("&b${player.name} &fの頭を取得しました"))
            } else {
                sender.sendMessage(getColored("&c頭を取得するプレイヤーのIDを入力してください"))
            }
        } else {
            sender.sendMessage(getColored("&cプレイヤーからのみ実行できるコマンドです"))
        }
        return true
    }
}

4. コマンドを登録する

Main.kt
class Main: JavaPlugin() {
    override fun onEnable() {
        registerCommand("head", GetHeadCommand)
    }

    private fun registerCommand(label: String, executor: CommandExecutor){
        val command = getCommand(label)
        if(command != null){
            command.setExecutor(executor)
            logger.info("/$label を登録しました")
        } else {
            logger.severe("/$label を登録できませんでした")
        }
    }
}

さあ、サーバーでテストしてみましょう。

まず、コンソールから入力したときにエラーが出るか確認してみましょう。
image.png
このように出ていたら成功です。

ではプレイヤーからコマンドを入力しましょう。正常に頭が取得できれば成功です。
image.png
image.png

お疲れ様でした。

リンク

次の記事に進む

目次に戻る

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?