前提条件
Eclipseを用いたSpigotプラグイン作成で作成したプラグインに追加する形でプラグインの開発を行なっていきます.
STEP1: 基本的なコマンドの実装
plugin.ymlの設定
自作プラグインのコマンドがコマンドに応答する機能を追加するためにplugin.yml
の編集を行います.
command:
コマンド名:
description: コマンドの概要をここに記載します
usage: コマンドの使用方法の記載
- description – コマンドの説明文.
- usage – コマンドの使い方.もし,ここで onCommand() でfalseを返したときにこの使用方法が表示されます.
ここでは基本的な要素しか追加していません.
description
,usage
以外を追加する事で色々いじる事が可能です.他の詳しい設定を行いたい場合はこのサイトを参考にしてください.
例としては以下のような感じです.
name: "QiitaTest"
version: "${project.version}"
main: "com.github.kubota.qiitatest.QiitaTest"
api-version: "1.13"
commands: #自作プラグインのコマンドを宣言
qiita:
description: this is a sample command.
usage: /<command>
メインクラスの編集
メインクラスに以下の要素を追加します.
@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
return false;
}
ここで onCommand
メソッドに関して軽く説明します.
このメソッドはplugin.yml
のCommand
で定義されたコマンドが実行される際に実行されます.
その引数は4つありそれぞれ以下の通りです.
- CommandSender sender – コマンドの発行元
- Command cmd – 実行されたコマンドの内容
- String commandLabel – 利用されたコマンドエイリアス
- String[] args – コマンドの引数を格納した配列
そして,このメソッドの型はBoolean
なので返す値はtrue
かfalse
かのいずれかです.
true
であれば,正常に動作することを表します.
false
であれば正常に動作しなかったことを表し, usage
に記載された内容が表示されます.
このメソッドを既存のプログラムに追加すると以下のようになります.
package com.github.kubota.qiitatest;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
public class QiitaTest extends JavaPlugin{
//↓ onEnableはロードされた時に実行されるメソッド
@Override
public void onEnable() {
// ↓ サーバー上にログを残す
getLogger().info("Hello, Qiita!");
}
// onCommand は plugin.yml に記載されたコマンドが呼ばれた時に実行
@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
return false;
}
}
これを実行するとこんな風になります.
Qiita
と言うコマンドが実行されるとonCommand
メソッド内のプログラムが実行されてfalse
が返されているのでplugin.yml
内のUsage
に記載された内容が表示されていますね.
これだけだとわかりにくいのでsendMessage
メソッドを追加します.
このメソッドはCommandSender
クラスのメンバメソッドです.
このメソッドの機能としてはこの対象者(インスタンスのユーザー)に引数内の文字列をメッセージとして送信すると言うものです.
前章で使用したgetLogger
メソッドとの違いはあちらはコンソールに文字列を表示し,こちらは対象者にのみ文字列を送信すると言う違いがあります.
以下が編集を加えたものです.
package com.github.kubota.qiitatest;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
public class QiitaTest extends JavaPlugin{
//↓ onEnableはロードされた時に実行されるメソッド
@Override
public void onEnable() {
// ↓ サーバー上にログを残す
getLogger().info("Hello, Qiita!");
}
// onCommand は plugin.yml に記載されたコマンドが呼ばれた時に実行
@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
sender.sendMessage("Command, Qiita!");
return true;
}
}
onCommand
メソッドの性質上,その第一引数であるsender
はコマンドを実行したユーザーとなっています.
なので,今回のプログラムではそのコマンドを実行したユーザーにのみメッセージを送信すると言うものになっています.
あと,戻り値による挙動の変更も確認するためにfalse
からtrue
へ変更しています.
STEP2: 複数のコマンド
plugin.ymlの設定
複数のプラグインを設定するには以下のようにCommand
下に追加していきます.
こんな風な感じです.
name: "QiitaTest"
version: "${project.version}"
main: "com.github.kubota.qiitatest.QiitaTest"
api-version: "1.13"
commands: #自作プラグインのコマンドを宣言
qiita:
description: this is 1st sample command.
usage: /<command>
sample:
description: this is 2nd sample command.
usage: /<command>
メインクラスの編集
onCommand
は plugin.yml
に記載されたコマンドが呼ばれた時に実行されるメソッドです.
もし, plugin.yml
に複数のコマンドが定義されていた場合はそのいずれかのコマンドが呼ばれれば実行されます.
既存のプログラムのままだと複数のコマンドを用意しても全て同じ動作を行ってしまいます.
これだと複数のコマンドを用意した意味がないので,実行されたコマンドによって処理を分岐させる必要があります.
package com.github.kubota.qiitatest;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
public class QiitaTest extends JavaPlugin{
//↓ onEnableはロードされた時に実行されるメソッド
@Override
public void onEnable() {
// ↓ サーバー上にログを残す
getLogger().info("Hello, Qiita!");
}
// onCommand は plugin.yml に記載されたコマンドが呼ばれた時に実行
@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
if(cmd.getName().equalsIgnoreCase("qiita")){
// qiitaコマンド が実行された時に実行
sender.sendMessage("Command, Qiita!");
return true;
}
if(cmd.getName().equalsIgnoreCase("sample")){
// sampleコマンド が実行された時に実行
sender.sendMessage("Command, sample!");
return true;
}
return false;
}
}
前述したようにcmdには実行されたコマンドの情報が格納されています.
このインスタンスの getName
メソッド を実行することで実行されたコマンドが文字列として取得できます.
equalsIgnoreCase
メソッド String型がもつメソッドで引数の文字列が実行した文字列を一致するかをBoolean型で返すメソッドです.
Tips
メソッドは
return
が実行された,それ以降の処理は実行されずに強制終了します.
STEP3: サブコマンド
plugin.yml の設定
これはマストではないですが,qiitaコマンドの機能として引数を受け付けるようにするために以下のようにusage
をわかりやすく変更します.
name: "QiitaTest"
version: "${project.version}"
main: "com.github.kubota.qiitatest.QiitaTest"
api-version: "1.13"
commands: #自作プラグインのコマンドを宣言
qiita:
description: this is 1st sample command.
usage: /<command> [text]
sample:
description: this is 2nd sample command.
usage: /<command>
メインクラスの編集
コマンド実行時の引数はargs
と言う変数に格納されます.これはString型の配列です.
配列なのでargs[x]
などとすれば取得できます、x
の部分は0から始まり,1ずつ増えて行きます。
> qiita a wa ka
と言うコマンドを実行した場合は
引数 | args[0] | args[1] | args[2] |
---|---|---|---|
値 | "a" | "wa" | "ka" |
と言う風に格納されます.
これを利用して以下のようなコードを書いてみます.
package com.github.kubota.qiitatest;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
public class QiitaTest extends JavaPlugin{
//↓ onEnableはロードされた時に実行されるメソッド
@Override
public void onEnable() {
// ↓ サーバー上にログを残す
getLogger().info("Hello, Qiita!");
}
// onCommand は plugin.yml に記載されたコマンドが呼ばれた時に実行
@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
if(cmd.getName().equalsIgnoreCase("qiita")) {
if(args.length == 0)return false;
sender.sendMessage("Command, Qiita by " + args[0]);
return true;
}
if(cmd.getName().equalsIgnoreCase("sample")) {
sender.sendMessage("Command, Sample");
return true;
}
return false;
}
}
args.length
にはargs
の配列に格納されている要素数が格納されています.
それが0と言うことはコマンド実行時の引数が何も入力されていないと言う状態になります.
今回はそのような状態はふさわしくないのでonCommand
メソッドはfalse
を返すようにします.
もし,その条件突破する(引数が存在した場合)は,Command, Qiita by
と表示された後に第一引数で入力された文字列を表示します.
これを実行すると結果は以下のようになります.
と言うことで今回は以上です!
STEP4: サンプルプラグイン(じゃんけん)
最後に今回の知識を使ったサンプルプラグインを作成します.
機能としてはコンピュータをじゃんけんを行うプログラムです.
相手の手はプラグインが有効になった際にランダムな手が決定され,それ以降は変更されません.
コマンドで実装する機能は
- じゃんけんを行う
- 相手の手を確認する
の2つです.
plugin.yml
name: "QiitaTest"
version: "${project.version}"
main: "com.github.kubota.qiitatest.QiitaTest"
api-version: "1.13"
commands: #自作プラグインのコマンドを宣言
janken:
discription: play the game of scissors-paper-roc.
usage: /<command> [your choice]
enemy:
discription: check enemy choice.
usage: /<command>
実装するプラグインのコマンドの機能
コマンド | 機能 |
---|---|
/janken [出す手] |
じゃんけんを行う |
/enemy |
相手の手を確認 |
mainクラス
package com.github.kubota.qiitatest;
// 乱数生成用のライブラリ
import java.util.Random;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
public class QiitaTest extends JavaPlugin{
String enemy = "";
// onEnableはロードされた時に実行されるメソッド
// このメソッドではenemy(相手の手)をランダムで決定する
@Override
public void onEnable() {
//手の情報が記載された配列
String[] hand = {"goo","tyo","paa"};
//乱数生成用のクラスをインスタンス化
Random r = new Random();
//nextIntメソッド で0以上3未満の乱数を生成し,対応する手をenemyに格納
enemy = hand[r.nextInt(3)];
}
// onCommand は plugin.yml に記載されたコマンドが呼ばれた時に実行
@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
// jankenコマンドを実行することでenemyとじゃんけんを行う
// 引数で自分の手を入力
if(cmd.getName().equalsIgnoreCase("janken")) {
// 引数が何も渡されない
if(args.length == 0)return false;
if(args[0].equalsIgnoreCase("paa") && enemy.equalsIgnoreCase("tyo") ||
args[0].equalsIgnoreCase("tyo") && enemy.equalsIgnoreCase("goo") ||
args[0].equalsIgnoreCase("goo") && enemy.equalsIgnoreCase("paa")){
//敗北のパターン
sender.sendMessage("俺の勝ち! 何で負けたか明日まで考えといてください");
}else if(args[0].equalsIgnoreCase("tyo") && enemy.equalsIgnoreCase("paa") ||
args[0].equalsIgnoreCase("goo") && enemy.equalsIgnoreCase("tyo") ||
args[0].equalsIgnoreCase("paa") && enemy.equalsIgnoreCase("goo")) {
//勝利のパターン
sender.sendMessage("やるやん! 明日は俺にリベンジさせて");
}else if(args[0].equalsIgnoreCase(enemy)) {
//あいこのパターン
sender.sendMessage("あいこやん! どうすんのこれ?");
}else {
// goo tyo paa 以外が入力されたパターン
return false;
}
return true;
}
// enemyコマンドで相手の手を表示する
if(cmd.getName().equalsIgnoreCase("enemy")) {
sender.sendMessage("Enemy choice is " + enemy + ".");
return true;
}
return false;
}
}
乱数の生成
// 乱数生成用のライブラリ
import java.util.Random;
このライブラリをインポートすることで乱数を生成するための以下で使用するクラスを使用することができます.
// 相手の手を格納する変数
String enemy = "";
// onEnableはロードされた時に実行されるメソッド
// このメソッドではenemy(相手の手)をランダムで決定する
@Override
public void onEnable() {
//手の情報が記載された配列
String[] hand = {"goo","tyo","paa"};
//乱数生成用のクラスをインスタンス化
Random r = new Random();
//nextIntメソッド で0以上3未満の乱数を生成し,対応する手をenemyに格納
enemy = hand[r.nextInt(3)];
}
ここが相手の手をランダムで決定しているプラグラムです.
まずは相手の手を格納する変数であるenemy
をmainクラスのフィールドとして用意します.
その後,このプログラムが有効になった時の処理として,Random
クラスのインスタンスを初期化します.
これによりこのインスタンスを経由することで乱数を生成するためのメソッドを利用可能にすることができます.
次にnectInt
メソッドを呼びだし乱数を取得します.このメソッドの引数が生成する乱数の最大値になります.
このプログラムではでは0以上、3未満の乱数を生成しています.
これを配列の添字とすることで0~2,すなわちhand
配列の三つの要素からランダムで一つを取得可能です.
じゃんけんを行う
// jankenコマンドを実行することでenemyとじゃんけんを行う
// 引数で自分の手を入力
if(cmd.getName().equalsIgnoreCase("janken")) {
// 引数が何も渡されない
if(args.length == 0)return false;
if(args[0].equalsIgnoreCase("paa") && enemy.equalsIgnoreCase("tyo") ||
args[0].equalsIgnoreCase("tyo") && enemy.equalsIgnoreCase("goo") ||
args[0].equalsIgnoreCase("goo") && enemy.equalsIgnoreCase("paa")){
//敗北のパターン
sender.sendMessage("俺の勝ち! 何で負けたか明日まで考えといてください");
}else if(args[0].equalsIgnoreCase("tyo") && enemy.equalsIgnoreCase("paa") ||
args[0].equalsIgnoreCase("goo") && enemy.equalsIgnoreCase("tyo") ||
args[0].equalsIgnoreCase("paa") && enemy.equalsIgnoreCase("goo")) {
//勝利のパターン
sender.sendMessage("やるやん! 明日は俺にリベンジさせて");
}else if(args[0].equalsIgnoreCase(enemy)) {
//あいこのパターン
sender.sendMessage("あいこやん! どうすんのこれ?");
}else {
// goo tyo paa 以外が入力されたパターン
return false;
}
return true;
}
そして次がぱっと見すごい難しそうに見えますが,条件式が複雑なだけで内容は単純です.
じゃんけんで勝つパターン,負けるパターンを全てを一つ一つ定義しています(アイコだけはenemy
とargs[0]
が等しいで判断しています).
相手の手を表示
// enemyコマンドで相手の手を表示する
if(cmd.getName().equalsIgnoreCase("enemy")) {
sender.sendMessage("Enemy choice is " + enemy + ".");
return true;
}
enemy
を表示しているだけです.
特に難しい箇所はないと思います.