※この記事では執筆時点で安定バージョンのPocketMine-MP API4.0.0に準拠しています。
パーミッションとは
権限です(そりゃそうだ)、コマンドの実行権限を制御するのに使われることが一番多いと思います。
でも、どうやって使えばいいのか、なんで使ったほうがいいのか分からない人もいるかもしれません。
使ってみるとそこまで難しくはないので、是非使ってみてください。お願いします。使ってください.......
パーミッションを使う理由
- OPであるかどうかに依存しない
- プレイヤーごとにパーミッションを与えるか制御することができる(e.g. VIPユーザー(OPではない)もOP専用コマンドを使用できるようにする)
- コマンドリスト(helpなど)にパーミッションが無くて使えないコマンドを表示させない
-
Permissible->hasPermission(DefaultPermissions::ROOT_OPERATOR)とか訳分からん長い謎の定型文を書かなくていい!!
使い方
パーミッションを登録する
パーミッションは、許可する物事ごとに作成します。
パーミッションを複数の許可で共有してはいけません。(myplugin.opやmyplugin.everyoneなどを作ってそのパーミッションを共用するなど)
- パーミッション名
- 一般的には
.区切りのアルファベットを使用します。他プラグインとの競合を防ぐために、接頭辞としてプラグイン名を追加すると良いです。(e.g.myplugin.command.hoge,myplugin.land_protection.bypass)
- 一般的には
- 説明
- このパーミッションによって何が許可されるのかの説明です。プラグインの開発方針によって、英語でも日本語でも良いです。(e.g.
/hoge コマンドの使用を許可します,土地保護をバイパスすることを許可します)
- このパーミッションによって何が許可されるのかの説明です。プラグインの開発方針によって、英語でも日本語でも良いです。(e.g.
- デフォルト値
- このパーミッションはデフォルトで誰に許可されるか。以下の表のどれかを設定します。沢山あって難しそうに見えますが、実際に使うのは
op,notop,true,falseだけです。
- このパーミッションはデフォルトで誰に許可されるか。以下の表のどれかを設定します。沢山あって難しそうに見えますが、実際に使うのは
| デフォルト値 | 許可対象 |
|---|---|
| op | OP |
| isop | OP |
| operator | OP |
| isoperator | OP |
| admin | OP |
| isadmin | OP |
| !op | OP以外 |
| notop | OP以外 |
| !operator | OP以外 |
| notoperator | OP以外 |
| !admin | OP以外 |
| notadmin | OP以外 |
| true | 全員 |
| false | 誰にも許可しない |
※falseは、コンソールのみに許可として使用されることも多いです。(コンソールはパーミッションの許可に左右されないため)
これは、コードで確認することもできます:
https://github.com/pmmp/PocketMine-MP/blob/4.0.0/src/permission/PermissionParser.php#L37-L54
plugin.ymlで以下のように設定することで、パーミッションを登録できます。複数設定することができます。
permissions:
パーミッション名1:
description: 説明1
default: デフォルト値1
パーミッション名2:
description: 説明2
default: デフォルト値2
パーミッションをコマンドで使用する
plugin.ymlでコマンドを追加した場合
上級者でない場合この方法でコマンドを登録するのが安全です。(パーミッションに設定ミス(誤字など)があったらエラーで止まってくれる)
commands:
permission: パーミッション名
※descriptionやusageなどを設定しても良いですがここでは省略しています。
よくある間違いで、ここのpermissionにopとかtrueとか指定してしまうことがありますが、それだと動作しないので注意!
メインクラスのonCommandメソッドの中ではパーミッションの条件分岐など、なにもしなくてOK!
Permissible->hasPermission(DefaultPermissions::ROOT_OPERATOR)などの条件分岐があったら上手く動作しないので削除しておきましょう。
それで動いているか不安な場合は、実際に動作確認してみると良いです。
コマンドをCommandMapで登録している場合
コンストラクタ(__construct)などに$this->setPermission("パーミッション名");を追加してパーミッションを設定します。
実装によっては$command->setPermission("パーミッション名");となることもあるかもしれません。(要はコマンドのオブジェクトに対してsetPermission()を呼び出せば良い)
このとき、パーミッション名は;区切りで複数指定することができます。(e.g. myplugin.command.hoge;myplugin.foo.bar)複数指定した場合、そのうちのどれか1つでもパーミッションを持っていたらパーミッションを持っている判定になります。(自分は使ったことないけど...)
さらにコマンドの実行時に自分でメソッドを呼び出してパーミッションの確認をする必要があります。
ただし、以下の場合はすでにされているので不要です。
- そのコマンドのクラスが
PluginCommandを継承していて、CommandExecutor(つまりonCommandのこと)を使用している場合 - Commandoライブラリを使用している場合(執筆時点)
- それ以外のライブラリやクラスなどを使用している場合で、実際にコマンドを処理するメソッドより上で
testPermissionメソッドが呼ばれているか、パーミッションがチェックされている場合(多分それをしている人は初心者ではないと思うのでわかると思いますが...)
上記に当てはまらない場合
次のような条件分岐を配置してください。
このコードは早期リターンを使用していますが、普通のifでも良いし、好きな方法で大丈夫です。(testPermissionメソッドで実行者がコマンドを実行するパーミッションを持っているかどうかがboolで返ってきます)
パーミッションを持っていない場合は自動でパーミッションが不足している旨のメッセージが送信されるので、メッセージを別途送信する必要はありません。
public function execute(CommandSender $sender, string $commandLabel, array $args)
{
if (!$this->testPermission($sender)) {
return;
}
//処理
}
※Command->testPermissionSilent()や、Command->setPermissionMessage()などを使って動作をカスタマイズすることができますが、ここでは紹介しません。詳しくはコードを参照してください。
パーミッションをコマンド以外で使用する
任意の場所でPermissible->hasPermission()を呼び出すことで、Permissible(プレイヤーなど)がパーミッションを持っているかを確認することができます。
具体的な例
public function onProtectedAreaBreak(BlockBreakEvent $event): void
{
$player = $event->getPlayer();
if (!$player->hasPermission("myplugin.land_protection.bypass")) {
//保護をバイパスできるパーミッションを持っていない場合はキャンセルする
$event->cancel();
}
}
Permissibleにパーミッションを付与する
Permissible->addAttachment()を呼び出すことでPermissible(プレイヤーなど)にパーミッションを付与することができます。
例
assert(!$player->hasPermission(DefaultPermissions::ROOT_OPERATOR));
//プレイヤーがVIPだったら
if ($player->hasVip()) {
//gamemodeコマンドの使用を許可する
$player->addAttachment($plugin, "pocketmine.command.gamemode", true);
}
逆に、パーミッションを剝奪することもできます。
例
//プレイヤーがやばい人だったら
if ($player->isSpammer()) {
//meコマンドの使用を拒否する
$player->addAttachment($plugin, "pocketmine.command.me", false);
}
※PMMP標準のパーミッションを使う場合はDefaultPermissionNamesの定数を使用したほうが良いです。分かりやすくするために文字列を直接指定しています。
さいごに
この記事をお読み頂きありがとうございます。参考になりましたら是非LGTMをお願いします。
また問題点などありましたらコメントや編集リクエストなどお気軽に送信してください。よろしくお願いします。
ありがとうございました。