[MineCraftプラグイン]コマンドを受け付けてイベントを発生させる
前提条件
我們將以使用Eclipse創建的Spigot插件為基礎,進一步開發插件。
步骤1:实施基本命令
在插件的配置文件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中定义的命令时被执行。
その引数は4つありそれぞれ以下の通りです.
– CommandSender sender – コマンドの発行元
– Command cmd – 実行されたコマンドの内容
– String commandLabel – 利用されたコマンドエイリアス
– String[] args – コマンドの引数を格納した配列
并且,这个方法的类型是布尔型,因此它的返回值只能是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;
}
}
由于仅有这个可能会难以理解,我们将添加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。
第二步:多个命令
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>
编辑主类
当调用 plugin.yml 中的命令时,onCommand 方法会被执行。
如果 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类型具有的方法,它将参数字符串与执行的字符串进行比较,并以布尔类型返回它们是否匹配。
技巧
当方法执行 return 后,其后的处理将停止并强制终止。
步骤3:子命令
插件配置文件(plugin.yml)的设置
这不是必须的,但为了让qiita命令接受参数作为功能,我们将按以下方式更改使用方法,以使其更加易懂。
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的变量中。这是一个字符串数组。
由于它是一个数组,因此可以使用args[x]等方式进行获取,其中x从0开始,每次递增1。
> qiita 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。
所以,這就是我們今天的內容了!
第四步:示例插件(猜拳)
最后,我们将创建一个使用本次所学知识的示例插件。
这是一个可以用电脑来玩剪刀石头布游戏的程序。
对手的手势在插件开启时会随机确定,之后不会再改变。
在命令行中实现的功能是什么?
(Translation: What functionality is implemented via command?)
-
- じゃんけんを行う
- 相手の手を確認する
这是两个选项。
插件配置文件
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
相手の手を確認主要的类
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的变量作为主类的字段,用于存储对手的手。
随后,作为该程序生效时的处理,初始化了Random类的实例。通过这个实例,就可以使用生成随机数的方法。
然后调用nextInt方法获取随机数。这个方法的参数将成为生成随机数的最大值。
在这个程序中,生成了0以上、3未满的随机数。
通过将其用作数组索引,可以从0〜2,即hand数组的三个元素中随机选择一个。
进行石头剪刀布游戏 wǒ
// 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”而已。
我认为没有特别难的部分。
実行結果
文献引用
-
- Plugin.ymlの設定一覧
-
- [Bukkitプラグイン制作講座-其之三]コマンドに応答する
- 【Bukkit Plugin開発】コマンド入力を受け付ける