純規の暇人趣味ブログ

手を突っ込んで足を洗う

[Bukkitプラグイン制作講座-其之四]もっとコマンド!!

      2016/12/13    HimaJyun

ん~……、予想以上に書く事が無いですわねぇ……

もしかすると次回以降は講座と言うよりハウツーになっちゃうかも……?

とりあえず今回はコマンドで色々やってみましょう。

前回の記事は「[Bukkitプラグイン制作講座-其之三]コマンドに応答する」です。

コマンドの上手な使い方

「まともな」実装のプラグインを作りたいのであればこれらのテクニックは必須です。

少しずつ紹介していきましょうか。

(*^○^*)「Player型が欲しいんだ!!」

例えば、今、コマンドを実行したプレイヤーの座標が入手したいとします。

しかし、senderはCommandSender型であり、getLocation(座標を取得する関数)は定義されていません。

では、どうすれば良いのでしょうか?、簡単です、キャスト(型変換)してしまえば良いのです。

@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
	// これは不可能
	//sender.getLocation();
	// こっちなら可能
	Player player = (Player)sender;
	player.getLocation();
	return true;
}

しかし、この方法ではコマンドを実行したのがプレイヤーではない場合に問題があるので、以下も合わせてご覧下さい。

コマンドを使ったのは……プレイヤー?コンソール?

先程の手法でsenderをPlayer型に変換する事が出来ました。

このコマンドをコンソール(サーバ)から実行するとどうなるのでしょうか……?

サーバが可愛いメイドさんに化けるのでしょうか?、いいえ、残念ながら違います、例外が出ます。(まさに例外ですものね、ユーザが使うコマンドをサーバが実行するなんて)

では、どうすれば良いのでしょうか?、簡単です。

@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
	// これは危険
	//Player player = (Player)sender;
	// この様にしましょう(深い意味は考えず、定型文として覚えておけば良し)
	Player player = null;
	if (sender instanceof Player) {
		// プレイヤーが実行
		player = (Player) sender;
	} else {
		// コンソールが実行
		sender.sendMessage("あたいはそこからは使えないよ~っと……");
		// 処理を終わらせる
		return true;
	}
	player.getLocation();
	return true;
}

(sender instanceof Player)はsenderがPlayer型を持つ(実行したのがプレイヤーの場合)にtrueを返します。

単純にbooleanを返すだけなので変数に詰める事も可能です。

boolean isPlayer = (sender instanceof Player);

何度もプレイヤー/コンソール判定を行う場合は変数に詰めた方がほんの少しだけ効率が良いかもしれません(第一に何度も判定を行うその設計自体が問題だとは思いますが……)

権限

例えばあなたは「桁違いに強い剣」と言う管理者用アイテムを与えるコマンドを実装したとしましょう。

さて、このコマンドを誰でも使えてしまうとどうなるか……ま、蚊の頭でも理解出来ますね。

そこで、コマンドに権限を設定して、不必要な野郎共に利用されないようにしてしまいましょう。

権限の追加

プログラム内でも出来ない事はないですが、特にメリットがある訳でもないので、普段は「plugin.yml」内で設定した方が楽で手っ取り早いです。

権限の設定は以下の様な設定を追記する事で可能です。

permissions:
  <権限名>:
    default: <デフォルト設定>

権限名は文字通りです、「プラグイン名.コマンド名」が分かりやすくて良いでしょう。(例:sample1.hoge)

ただし、小文字で設定する事、大文字は色々とややこしい事になりそうなので……

デフォルト設定はデフォルトで権限を与えるか否か、です。

true(全員が実行可)、false(全員が実行不可)、op(OPのみ可)、not op(OPのみ不可)の4種類が設定出来ます、実際はtrueとopくらいしか使わないと思いますが……

実際に設定すると以下の様な感じになります。

permissions:
  sample.player:
    default: true
  sample.op:
    default: op

「sample.player」がプレイヤー用(デフォルトで全員許可)、sample.opが管理者用(デフォルトでOPのみ許可)としてみました!!

子権限の設定

面倒なのですけれども、ついでなので説明しちゃいましょう!!

例えば、プラグインなどに依っては「plugin.*」(.*を指定)などとする事で全ての権限をまとめて設定出来たりします。

これは(多分)プラグイン側で.*が指定されてあると全ての権限を含めるように設定しているのでしょう。

その場合は以下の様に設定します。

permission:
  <権限名>:
    children:
      <含める権限>: <設定>

先程とそう変わりませんね、設定はtrueかfalseが設定可能で、trueなら含める、falseなら除外する、です。(ただ、実際にはtrueしか使いません)

先程のsample.playerとsample.opをsample.*でまとめて設定出来るようにするには以下の通りです。

permissions:
  sample.player:
    default: true
  sample.op:
    default: op
  sample.*
    children:
      sample.op: true
      sample.player: true

簡単ですね!!

権限の確認

さて、実際に権限を持つユーザにだけ「桁違いに強い剣」を配布する様にしてみましょうか

とりあえず現段階ではこんな感じ。

@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
	/*
	ここに「桁違いに強い剣」を与える処理があるとする。
	*/
	return true;
}

これを「sample.op」権限を持つでのみ実行出来る様にする、難しくはない

@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
	if (sender.hasPermission("sample.op")) {
		// 権限を持つ
		/*
		ここに「桁違いに強い剣」を与える処理があるとする。
		//*/
	} else {
		// 権限を持たない
		sender.sendMessage("あんたには使えないよ!!");
	}
	return true;
}

CommandSender、もしくはPlayerが持つhasPermission()を利用して権限の有無を判定する。

hasPermission("権限名")とする事でそのプレイヤーが権限を持っていればtrue、持っていなければfalseが得られる。

コンソールからの実行でも問題ない(この場合……OP扱い?、少なくともdefaultがtrueとopの場合はコンソールからの実行でも権限を持っているとみなされる=true)

終わりに

もっと書こうとは思ったんだけども、(主にサーバ周りの事で)色々忙しくて死に掛けてるので今日はここまで。

おまけしちゃうわ、以下をごらんなさい。

Tips:ブロックコメントアウト、アンコメント

今、ふと思い付いた方法。

ここに
色々な
処理が
あると
する。

これを、まとめてコメントアウトするには……だいたいこうするだろう。

/*
ここに
色々な
処理が
あると
する。
*/

これを、こうすると

/*
ここに
色々な
処理が
あると
する。
//*/

アンコメント(コメントアウトの反対)したい時に、先頭の/*を//*に変えるだけで良くなる。

//*
ここに
色々な
処理が
あると
する。
//*/

原理的には、/*が//*になる事で*がコメントとみなされて、//*/の部分は*/がコメントとみなされる、楽しい!!

其之五は「[Bukkitプラグイン制作講座-其之五]コマンド、時々クラス分割

今回の記事のソースコードはGitHubからご覧いただけます。

 - プログラミング , ,