0. 初めに
build.gradle
や plugin.yml
の設定は終わらせた前提で進めます。
プロジェクトを作成する を参考にメインクラスを作るまで終わらせておいてください。
また、コマンドを作成して進めていきます。
詳しい説明は 2.2 コマンドを新しく作る でしていますので省略します。
1. plugin.yml にコマンドを登録する
commands:
head:
usage: "/<command> [Player]"
description: "プレイヤーの頭を取得します"
permission: minecraft.command.give
このようなコマンドを登録しておきます。一番初めの引数はプレイヤーのIDです。
これは /give
の拡張コマンドです。実行に minecraft.command.give
という権限を必要としています。
2. 準備をする
コマンド処理のところで、メッセージに色をつけたいので getColored
関数を実装しておきましょう。詳しくは こちら
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
の拡張になっています。
要するに meta
が SkullMeta
であれば 固有の設定 も行える のです。
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
というオブジェクトを作成します。
実行したプレイヤーが頭を取得する仕様にしましょう。
その場合、コンソールから実行することは出来ません。言い換えると プレイヤーのみ実行可能 です。
その条件分岐を書きましょう。
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
の中括弧の中であれば sender
は Player
として扱われます。
次に、コマンド引数の処理をしましょう。(一番最初の引数がプレイヤーの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を入力してください"))
}
}
そうするとこのように、取り消し線がかかれると思います。
非推奨関数と言って、「あまり使わないほうがいいよ」といった意味です。
getOfflinePlayer(String)
というものが非推奨になっているのは、プレイヤーのIDが変更可能だからです。
例えば、データを保存するという時にIDを使っていると、データが消えてしまいます。
そういった場合には UUID
を使いましょう。しかし、今回は問題ありません。
このまま無視してしまうと毎回警告が出るので、出ないようにしておきましょう。
取り消し線の上で右クリック → Inspection 'DEPRECATION' options
→ ... for val
を選択。
そうすると、このようになると思います。
@抑制する("非推奨")
こんなような意味です。
注意しなければいけないのは、非推奨であったということ。その使い方が間違えではないかを考えて使いましょう。
では、先ほど作成した 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の頭を取得しました"))
}
これでコマンドの処理は書き終わりました。
完成するとこんな風になっていると思います。
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. コマンドを登録する
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 を登録できませんでした")
}
}
}
さあ、サーバーでテストしてみましょう。
まず、コンソールから入力したときにエラーが出るか確認してみましょう。
このように出ていたら成功です。
ではプレイヤーからコマンドを入力しましょう。正常に頭が取得できれば成功です。
お疲れ様でした。