トラップタワーの作り方やSEEDなど、MinecraftPEを楽しむための情報や、最新のアップデート情報を載せていきます

ここでは、マルチプレイ用ソフト「Pockemtine-MP」用のプラグインの作り方について少し説明していきます。

はじめに

PC表示で見てください。
自分自身、プラグイン作成に関してはまだまだ初心者です。いわゆる「汚い」コードも平気で書いてしまいます。
今回は鯖運営者の方々がもしかして作りたいと思っているんじゃないか?ということで、少しばかりの知識ですが書いていきます。
それ故に以下の記述に間違いがあるかもしれませんが、そのときは優しく教えていただければ幸いに思います。
自分はおまっちゃお氏とSUNexus氏に分からない部分を教えていただきました。ありがとうございます。
以下自分が参考にしたページです。

おまっちゃおの備忘録-プラグインサンプル集
http://mattyaphone.blog.fc2.com/blog-entry-107.htm...

おまっちゃおの備忘録-PocketMine-MP用プラグインの作り方
http://mattyaphone.blog.fc2.com/blog-entry-103.htm...

プラグインとは?

1章 チュートリアル

今回のテーマ

記事を書き上げることが先だと思ったので、簡単な構造のものを解説します。基本中の基本って感じです。
/ip <プレイヤー名>と入力すると、その人のIPアドレスを表示させるプラグインを作りましょう。

仕組みを少しずつ解説しつつ、プラグインを完成させていく、という感じで進めていこうと思います。

なお、ここではphpなどの基礎の基礎にしか触れません。
めんどくさいところは省きますので、分からない部分があっても「ああ、こういうものなんだな」と割り切るのがいいかと思います。
ここではプラグインを完成させることのみを目的として進めていきます。

用意するもの

  • Pockemtine-MP本体
  • テキストエディタもしくは専用のエディタ
    (自分はeclipseというエディタで編集しています。このソフトの使い方についてはご自身でお調べになってください。)

基本形・テンプレート

<?php
 
/*
__PocketMine Plugin__
name=ExamplePlugin
version=0.0.1
author=shoghicp
class=ExamplePlugin
apiversion=10
*/
 
class ExamplePlugin implements Plugin{
private $api;
public function __construct(ServerAPI $api, $server = false){
$this->api = $api;
}

public function init(){
}

public function __destruct(){
}
 
}

まずこれをコピペしエディタに貼り付けます。これがいわゆる「型」となるものです。
どんなプラグインもここから作っていきます。
一応これだけでも動きますが、まだ何もない状態です。


おおなかに分けるとこんな感じです。
赤い部分でプラグインの説明
オレンジの部分でクラス宣言をし、
緑部分は、プラグイン読み込み時に動作させる部分となり、
青部分はまだ何もないですがこれから追加していきます、ここがプラグインの「一番中心となる重要な部分」です。
紫部分は鯖が閉じるときに行うことを書くらしいですが自分は使ったことがありません。

さて、上から順に編集していきましょう

プラグイン情報の編集


/*
__PocketMine Plugin__
name=ExamplePlugin
version=0.0.1
author=shoghicp
class=ExamplePlugin
apiversion=10
*/
まずはこの部分を編集していきましょう。
ここには、このプラグインの情報を書いていきます。
ここは型がもう決まっているので楽勝です。
  • name=ExamplePlugin
このプラグインのなまえは「ExamplePlugin」だよー
ExamplePluginの部分を自分の好きなプラグイン名にする
  • version=0.0.1
このプラグインのバージョンは「0.0.1」だよー
0.0.1の部分を編集。別に変えなくても動くので良い。
  • author=shoghicp
開発者は「shoghicp」だよー
自分の名前を入れておこう。
  • class=ExamplePlugin
クラス名は「ExamplePlugin」だよー
ここはプラグイン名と同じにしておきましょう。
  • apiversion=10
対応しているAPIバージョンは10だよー
2/15現在プラグインのAPIは12が最新ですので12にしましょう。

編集できました、こうなりました。
/*
__PocketMine Plugin__
name=IPplugin
version=0.1.0
author=Gonbe34
class=IPPlugin
apiversion=12
*/

クラス宣言・API

class ExamplePlugin implements Plugin{
private $api;
public function __construct(ServerAPI $api, $server = false){
$this->api = $api;
}
  • class ExamplePlugin implements Plugin{
    class名がExamplePluginというプラグインってことを宣言するよ
Examplepluginの部分を、必ずプラグイン情報のところで書いた「class=」の部分と同じにしておきましょう。

それ以外の部分は放って置きましょう。
ServerAPIの使用をリクエストしたりする場合は追記したりする必要がありますが今回はそうではないので必要ありません。
というか筆者自身理解していません。すいません。

こんな感じですね。
class IPPlugin implements Plugin{
private $api;
public function __construct(ServerAPI $api, $server = false){
$this->api = $api;
}

これでおおまかなプラグイン情報の編集は終わりました。

プラグイン読み込み時

いまさらですが、このプラグインはPHPというプログラミング言語で書かれているので、そのルールにのっとってコードの編集を行わなくてはなりません。一行の終わりは必ず「;」「:」「{」「}」になります。使われるのはだいたい「;」です。これがphpを書く上でのルールです。
そもそもこれらが行の終わりにない場合、仕組みがおかしいなどの以前に起動時にエラーを吐かれます。
英文で言うところの「.(ピリオド)」の付け忘れ、でしょうか。小さなミスですがしっかりかかないと動きませんので注意です。

プログラムは「{」と「}」の間に書いていきます。自分で「{」を付け足したときは、その部分の後ろに「}」も付け足さなければなりません。作文を書くときのルールの「かぎかっこでくくったら会話の終わりはかぎかっこで終われ」みたいなもんです。

public function init(){
ここに書いていく
}
このPublic function init()内は一番最初鯖が開く前に読み込まれます。
ここでは、コマンドの登録を行います。
サーバーで/ipコマンドを使えるように、pocketmineに登録するということです。

$this->api->console->register("コマンド名", "コマンドの説明", array($this, "メソッド"));
コマンド名…/tp、/stopなどの「tp」「stop」の部分
コマンドの説明…/helpを使ったときに表示させる文章、説明
メソッド名…この「コマンド」が実行されたときに、実行させるメソッドの名前
※メソッドとは、後ほど青色の部分に追加するものです。このコマンドが実行されたとき、そのメソッドの処理に移ります。メソッド名は赤部分で行ったクラス名のように、自分で決めることができます。

public function init(){
	$this->api->console->register("ip", "<player> see player's IP", array($this, "commandH"));
}
こんな感じですね。問題は次からです。

コマンド処理部分

さて、コマンドが実行されたとき行う処理を記述する部分です。ここが核となります。
長くなるので先に書いておきます。
public function ip($cmd, $params, $issuer, $alias) {
	$user = strtolower($params[0]);
	$player = $this->api->player->get($user);
	if ($player instanceof Player) { //Playerオブジェクトかどうか
			$pip=$player->ip;
			return $user."'s IP :".$pip;
	}else{
		return "Player doesn't exist"
	}
}
順々に説明しておきます。

まずはメソッドを追加しましょう。
public function メソッド(引数1,引数2,…) {
}
メソッド…緑部分で決めた「メソッド」です。
引数…この「メソッド内」で使用したい(正確に言えば本体から取得したい)「変数」を記述します。変数にはいろいろなものがあります。プラグインとPocketmine本体は様々なデータのやり取りをします。
※変数…数学で言うところの「x」や「y」など、この中に何か数字が代入されるものです。なお、プログラムは数学ではないので、「数字」だけでなく関数の中は「文字」や「データ」にもなります。phpの「変数」には、必ず先頭に「$」が付いています。例えば数学で「y=ax+b」という式がありますね。これをphpで記述させようと思うと、「$y == $a * $x + $b」としないと認識しません。プログラム側からすれば、「x」と書かれただけではそれが「文字」だか「関数」だか分からなくなるため、差別化させるためです。どうして「=」ではなく「==」とするのか、また「*」とはなんなのかなどは後ほど説明します。

引数には様々ありますが、今回使うのは$cmd, $params, $issuer, $aliasです。
軽く説明しておきます。
$cmd…ここには、実行されたコマンドの文字列が代入されます。たとえば「/tp Gonbe34 Jin113」とした場合、$cmdの中身は「tp」になります。
$params…ここにはコマンドの後ろに付いた「パラメータ」が代入されます。たとえば「/tp Gonbe34 Jin113」とした場合、$paramsの中身は「Gonbe34 Jin113」となります(正確には違うかもしれません)。【重要】ここで$paramsから文字列を取り出す(取得する)、例えば「Gonbe34」という文字列だけを取り出したい場合には「$params[0]」とすると出すことができます。勘のいい人は分かるかも知れませんが、「$params[1]」は「Jin113」です。
$issuer…このコマンドを実行したプレイヤーのデータが代入されます。
$alias…よくわかりませんがどんなプラグインにも書いてありますので一応入れておきましょう。わかってなくてもプラグインは作れます、多分。
他によく使われるものは「$event」や「$data」ですかね。ここでは使いませんので説明は省きます。

public function commandH($cmd, $params, $issuer, $alias) {
}
こんな感じになりますね。まだまだです。


人に説明するというのは難しいですね。構成を考えるのに時間がかかりました。
大まかな構造についてです。

このコマンドは、始めに説明したように、「/ip <プレイヤー名>」と打つことで使えるようにしますよね。
たとえばGonbe34さんのIPを表示させたい場合、/ip Gonbe34と使えば出るようにしたいわけです。
そしてその指定したユーザーに関するデータを取得し、そのデータの中からIPアドレスのデータを抜き取り、表示させるというわけです。

順番で言うと、
  • 1、コマンドで指定されたユーザーを探す
  • 2、そのユーザーに関するデータを取得
  • 3、データの中からIPアドレスのデータを抜き取る
  • 4、表示
とこんな具合です。


まず「ユーザー名のデータ」を格納するための関数を作りましょう。
$usernameとしましょうか。
先ほどの例を使って言うならば、/ip Gonbe34としたときの、「Gonbe34」という文字を保持させるための変数です。
もうちょっと簡単にいうならば、とりあえずいろんなプレイヤーのユーザー名が入る関数を作るんだな、と思えばいいかもです。
$username = params[0];
こうすると、/ip Gonbe34としたときには$usernameの中にGonbe34が入ります。


ユーザーネームを保存したら、今度はそのユーザーに関するデータを入手しなくてはいけません。
それには、
$player = $this->api->player->get(ユーザー名);
これを使います。$playerもPocketmineとやり取りする変数のうちのひとつです。
ユーザー名は、先ほど$username変数を作ったので
$username = params[0];
$player = $this->api->player->get($username);
こうすればいいですね。
これで、現在$playerの中には指定されたユーザーに関する様々なデータが入っていることになります。


$player->ip;
を使うと、そのプレイヤーのIPが取得できます。
これもわかりやすくプレイヤーのIPを格納するための変数を作っておきましょう。
$pipとします。

$username = params[0];
$player = $this->api->player->get($username);
$pip = $player->ip;


IPが取得できたら今度は表示させましょう。
表示させるのには「return 文字列が代入された変数」とすればokです。
ここでは「return $pip」でOKですね。
$username = params[0];
$player = $this->api->player->get($username);
$pip = $player->ip;
return $pip

表示させるといっても、ただ単に数字が出るだけではつまらないですね。

ここで「文字の足し算」について少し解説します。
まず大体どんなプログラム言語でも、文字列というのは「""」で囲まれます。
「return あいす」と打っても、「あいす」とは表示されません。
ただしくは「return "あいす"」です。
「""」は、この中に囲われたものは文字列である、と認識させるためです。

$a = "あ"
$b = "い"
$c = "す"
とします。ここで、この関数を使って「あいす」と表示させるためにはどうすればいいか?
「return $a + $b + $c」ではだめですよ、これは数字ではないですからね。
「$a.$b.$c」とすれば「あいす」となり、OKです。
文字列と混ぜる場合、たとえば
「$a."き".$c」とすると「あきす」となります。
「$a."き".$c."こ".$b」とすれば「あきすこい」になります。

話を戻しましょう。
「IP: 000.000.000.00」と表示させたい場合、「"IP:".$pip」とすればOK。
それだけでもひねりはありますが、「Gonbe34's IP : 000.000.000.00」となるともうちょっと面白くなりますよね。
こうする場合、ユーザーネームは$usernameを既に指定してあるので
「$username."'s IP :".$pip;」とすればOK。ここの部分は正直どうでもいいとは思いますが。
どうでもいいことに時間をかけてこそのプログラミングだと、勝手に思っています。


さて、コードはこうなりました。
$username = params[0];
$player = $this->api->player->get($username);
$pip = $player->ip;
return $username."'s IP :".$pip;
これで動くか?いえ、動きません。
動かないというのは違いますね。正確に言えば、動かなくもないですがエラーが出る可能性があります。

まず、pocketmineではユーザーネームは「大文字はなく全て小文字か数字」で格納されています。
(PMMP本体の中の「players」フォルダを見てみると、プレイヤー名は全て小文字なのが分かりますね。)
つまり最初の方で例に挙げた「/ip Gonbe34」では、「G」が大文字なので正しくプレイヤーデータが取得できません。
「/ip gonbe34」とすれば、大丈夫なのですが・・・
「じゃあ大文字は絶対使わず小文字で打てばいいんだね!」
…まあそういうことですが、誰かが大文字を打ってしまうたびにエラーが出るのではたまったもんじゃないですよね。

ここでいいものがあります。
$username = strtolower(params[0]);
こうすることで、「指定部分の大文字は全て小文字にしてくれる」んです。
素晴らしいですね。まあ普通といえば普通ですが。
「/ip Gonbe34」と打った場合も、本体側、格納される$username変数の中身は「gonbe34」になります。
「/ip gONbE34」でも同じです。


他の場合も考えて見ます。
まず、もしサーバー内に「Gonbe34」さんが居なかったらどうなってしまうのか。
居ないプレイヤーのデータを取得するわけですから、$playerの中が空になります。
ここまではエラーが起きませんが、おそらく$player->usernameをすると死にます。

プレイヤーの場合実行させ、そうでない場合は実行させないためにはif文を使います。
if文とは、条件式と呼ばれ、たとえば「$a=1なら実行」とか、「$a=1以外なら実行そうでないならそこで終了」と
ある条件を満たしたときだけ、動作させることができるわけです。
if(条件式){
実行する部分
}
これがif文の基本です。これを使います。
プレイヤーオブジェクトであるかどうか判断させるためには
if ($player instanceof Player) {
を使えばいいわけです。
こうします。
$user = strtolower($params[0]);
$player = $this->api->player->get($user);
if ($player instanceof Player) {
	$pip=$player->ip;
	return $user."'s IP :".$pip;
}
こうすることで$pip=…の部分とreturn…の部分は、$playerがプレイヤーオブジェクトの場合(プレイヤーデータが入っているとき)のみ実行するようになります。
これでもいいのですが、これでは間違ったプレイヤー名を打った場合何も出ません。
少し悲しいので、「そうでない場合、プレイヤーオブジェクトでなかった場合実行する部分」を追加します。

$user = strtolower($params[0]);
$player = $this->api->player->get($user);
if ($player instanceof Player) {
	$pip=$player->ip;
	return $user."'s IP :".$pip;
}else{
	そうでない場合実行される
}
elseで囲まれた部分は、上の条件に当てはまらなかった場合、実行される部分になります。
return "Player doesn't exist"としましょう。
(この英文の意味は、「プレイヤーが存在していません」という意味になります)
$user = strtolower($params[0]);
$player = $this->api->player->get($user);
if ($player instanceof Player) {
	$pip=$player->ip;
	return $user."'s IP :".$pip;
}else{
	return "player doesn't exist";
}


さて、紫部分のdestructの部分には用はないので、これで完成ですね。
<?php

/*
__PocketMine Plugin__
name=IPplugin
version=0.1.0
author=Gonbe34
class=IPPlugin
apiversion=12
*/

class IPPlugin implements Plugin{
private $api;
public function __construct(ServerAPI $api, $server = false){
$this->api = $api;
}

public function init(){
	$this->api->console->register("ip", "<player> see player's IP", array($this, "commandH"));
}

public function commandH($cmd, $params, $issuer, $alias) {
	$user = strtolower($params[0]);
	$player = $this->api->player->get($user);
	if ($player instanceof Player) {
		$pip=$player->ip;
		return $user."'s IP :".$pip;
	}else{
		return "player doesn't exist";
	}
}

public function __destruct(){
}
 
}
長々と付き合ってくださって有難うございました。
自分が答えれる範囲でなら質問に答えますので、疑問などありましたらコメント欄でよろしくお願いいたします。

2章 イベント

ここからは、katsuo_say_yesが編集します。僕自身もまだまだプラグイン開発の点では未熟です。
Gonbeさんの書いたコードに比べて汚かったり、何か問題が発生するかもしれません。
その場合、コメント欄などで指摘してくださると幸いです。
※イベント…プレイヤーが鯖に入った、ブロックを設置したなどの動作のこと。

今回のテーマ

今回は、誰かがサーバーに入ってきた時、入ってきた人に「このサーバーの名前は(サーバー名)です」と言うプラグインを作ってみましょう。
サーバーの設定をいじることでプラグインを使わずとも可能ですが、あくまで練習と言うことでやってみましょう。

基本形

前回と同じテンプレートを使用します。

<?php
 
/*
__PocketMine Plugin__
name=ExamplePlugin
version=0.0.1
author=shoghicp
class=ExamplePlugin
apiversion=10
*/
 
class ExamplePlugin implements Plugin{
private $api;
public function __construct(ServerAPI $api, $server = false){
$this->api = $api;
}

public function init(){
}

public function __destruct(){
}
 
}

プラグイン情報

/*
__PocketMine Plugin__
name=ExamplePlugin
version=0.0.1
author=shoghicp
class=ExamplePlugin
apiversion=10
*/
前回と同じく、この部分を編集しましょう。
  • name=ExamplePlugin
このプラグインのなまえは「ExamplePlugin」だよー
この部分を自分の好きな名前にする、今回は例として「JoinMSG」
  • version=0.0.1
このプラグインのバージョンは「0.0.1」だよー
0.0.1の部分を編集。別に変えなくても動くので良い。
  • author=shoghicp
開発者は「shoghicp」だよー
自分の名前を入れておこう。
  • class=ExamplePlugin
クラス名は「ExamplePlugin」だよー
ここはプラグイン名と同じにしておきましょう。
  • apiversion=10
対応しているAPIバージョンは10だよー
2/15現在プラグインのAPIは12が最新ですので12にしましょう。
編集が終わったら次へ進みます。

クラス宣言・API

class ExamplePlugin implements Plugin{
private $api;
public function __construct(ServerAPI $api, $server = false){
$this->api = $api;
}
  • class ExamplePlugin implements Plugin{
    class名がExamplePluginというプラグインってことを宣言するよ
Examplepluginの部分を、必ずプラグイン情報のところで書いた「class=」の部分と同じにしておきましょう。
前回と同じく、それ以外の部分は触らないで下さい。

プラグイン読み込み時

public function init(){
ここに書いていく
}
このPublic function init()内は一番最初鯖が開く前に読み込まれます。
ここでは、前回と違いイベントの登録をします。

$this->api->addHandler('イベント名', array($this, 'メソッド名'),100);
イベント名…ブロックの設置、鯖への出入りなどのイベントの名前
メソッド名…この「コマンド」が実行されたときに、実行させるメソッドの名前
※メソッドとは、後ほど青色の部分に追加するものです。イベントが発生したとき、そのメソッドの処理に移ります。メソッド名は赤部分で行ったクラス名のように、自分で決めることができます。

public function init(){
$this->api->addHandler('player.spawn', array($this, 'eventH'));
}
次から中身を追加していきましょう。

イベント発生時

全体のコード
一番大事なところです。先に全体を書いておきます。
public function eventH($event, $data) {
$player = $data->username;
$this->api->chat->sendTo(false, "このサーバーは(サーバー名)というサーバーです。", $player);
}
構成
このプラグインは、はっきり言って非常に単純です。
ただ単純に、サーバーに入ったプレイヤーの名前を取得し、メッセージを送っているだけです。

まずはメソッドを追加しましょう。
public function メソッド(引数1,引数2,…) {
}
メソッド…プラグイン読み込み時に決めた「メソッド」です。
引数…この「メソッド内」で使用したい(正確に言えば本体から取得したい)「変数」を記述します。変数にはいろいろなものがあります。プラグインとPocketmine本体は様々なデータのやり取りをします。
引数には様々ありますが、今回使うのは$event, $dataです。
軽く説明しておきます。
$event…ここには、発生したイベントの内容が入力されます。ブロック破壊ならplayer.block.breakとなります。あまり気にしないで下さい。
$data…ここには、イベントにまつわる様々な情報が入力されます。今回は、この引数からプレイヤー名を取り出します。

public function eventH($data) {
}
こんな感じですね。先は長いです。

次に、「(イベントを発生させた)プレイヤー名」を取得します。
イベントを発生させたプレイヤー名は、$data の中のplayerに格納されています。
プレイヤー名を取得します。
public function eventH($event, $data) {
$player = $data->username;
}
このコードでは、$player という変数にプレイヤー名を格納しています。
書式を間違えると上手く動作しないので、気を付けてくださいね。

次に、サーバーに入ったプレイヤーにメッセージを送りましょう。
メッセージを送るには、次のようなコードを使います。
$this->api->chat->sendTo(false, "メッセージ", array("プレイヤー名"));
このコードでは、"メッセージ"を"プレイヤー名"に送信しています。
これを組み込んで、
public function eventH($event, $data) {
$player = $data->username;
$this->api->chat->sendTo(false, "このサーバーは(サーバー名)というサーバーです。", $player);
}
||=
となります。(サーバー名)の中には、自分のサーバーの名前を入れておいてください。
そして、プレイヤー名のところには、先ほど取得した名前を使用しています。

さて、これでプラグインは完成ですね。
最終的に、この様な感じになりました。
<?php
 
/*
__PocketMine Plugin__
name=JoinMSG
version=0.0.1
author=katsuo_say_yes
class=JoinMSG
apiversion=12
*/
 
class JoinMSG implements Plugin{
private $api;
public function __construct(ServerAPI $api, $server = false){
$this->api = $api;
}

public function init(){
$this->api->addHandler('player.spawn', array($this, 'eventH'));
}

public function eventH($data){
$player = $data->username;
$this->api->chat->sendTo(false, "このサーバーは(サーバー名)というサーバーです。", $player);
}

public function __destruct(){

}

}

最後に、保存する際はエンコードに気を付けてください。
日本語を使用しているため、Pocketmine側の仕様で「UTF-8」というエンコードで保存する必要があります。
エンコードって何?と言う方はGoogle先生辺りが教えてくれるかもしれません。

だらだらとした文章に付き合っていただきありがとうございました。
分かりにくい説明だったかもしれません。また何かあればお知らせください。
ありがとうございました。

エラーの中身を見る

上手くプログラムが動かずエラーが出る場合があります。
そのエラー内容を見ることで解決につながります。

例えば「Line 26」などと出た場合26行目に問題があるということです。
その行を見直しましょう。たとえば「;」がついていなかったり「""」で文字が囲われていなかったりしませんか?

まずロード時に問題が起きる場合、一番下の「}」が抜けていたりしませんか?

スポンサードリンク

Menu

メニュー

アップデート情報
次回のアップデート情報をお届け








トラップタワー
敵を殺しアイテムを得るためだけの装置




【メニュー編集】

Twitter公式アカウント

Twitterでも更新情報をお届けしております!
是非ともフォローお願いします!



Wikiをはじめる

マイページ