本帖最后由 Snake1999 于 2014-2-6 16:44 编辑

咳咳,大家好,我是二菌。今天我给大家带来的就是我的PM插件制作教程。
PM,全称PocketMine-MP,是PE服务器软件中最流行的一种,用PHP编成,尤其以插件的多样性吸引了大多数PE腐竹的目光。PM发布以来,网上插件层出不穷,包括多世界插件、防作弊插件等等许多种类。PM插件对于菜鸟来说似乎遥不可及,只能瞻仰着各路大神的插件漫天飞舞。但是,制作插件真的真的真的很困难吗?
不是的。PHP我认为是软件中BASIC、E语言以外最简单的语言,多用性、可塑性很强,特别好懂。学习一门像PHP的语言看起来似乎遥不可及,但是你一旦用心,就能和大神们一起创造。学习插件和玩PE一样,创造性强,没有做不到,只有想不到。相信屏幕前谁问你既然有一颗PE的心,那么一定能学好PM插件的。
你想制作一个自己的插件吗?如果是,又不知如何入手,那么让二菌我来引导你 ——
开PM服务器教程网上挺多,可以去翻翻,可以参考下面的教程:
http://www.mcbbs.net/thread-101500-1-1.html
如果真看不懂,让二菌我来教你——
图片来源:https://github.com/PocketMine/PocketMine-MP/wiki/Setting-up-a-Server

第一步,搭建服务器环境
方法1【荐】:
方法2:
ok , 第一步完成
第二步,运行服务器
双击start.bat即可开服。

有同学可能注意到控制台的字是彩色的,如果发现自己的字不是彩色的,说明你的bin/mintty.exe没有找到,可以去下载我的PHP5.4库试一试,在方法1里面。{:10_492:}
服务器的其他指令我这里就不多讲了,可以去网上查一下。
http://www.w3school.com.cn/php/index.asp
http://www.php100.com/html/shipinjiaocheng/
真的看不懂?没事,别忘了这篇帖子是二菌写的...{:10_505:}
1.PHP的基本语法
2.PHP的变量
3.PHP的字符串
4.PHP的运算符
5.PHP的数组
6.PHP的基本语句块【If Switch 和循环语句】
7.PHP函数
8.PHP class类
孩子,你看到这里了,说明你对于PHP玩的差不多了,为制作一个PM插件已经打好了基础,往下看吧。
大家上面看完了吗?(众:看~完~了~)
那好,我们就开始做插件吧。
接下来,我们以SignTp插件作为目标,一步一步完成。
我们的插件要可以:
> 扔一个牌子就能传送到目的地!
> 有自动更新功能!
所以它需要:
> 有一堆命令
> 检测一堆事件
> 读取一堆配置文件
> 等等......
这看起来似乎很难的样子,让我们一步一步制作完毕。
0.一些准备
1.你的第一个PM插件
> 无中生有的第一步
2.给你的插件添加命令
> 键盘敲一敲,服务器嗨起来
================== 坑 线 =================
3.为你的插件检测事件
> 石头:现在你还你敢敲我?
1.PM常见命令
2.PM数据类型
3.PM对象
======================== 坑 线 ==========================
4.PM API解析【已更API11】
来自群组: PocketMine开发&讨论
P o c k e t M i n e - M P 插件制作教程 二 菌 出 品
Now, let's begin.【前言】
咳咳,大家好,我是二菌。今天我给大家带来的就是我的PM插件制作教程。
PM,全称PocketMine-MP,是PE服务器软件中最流行的一种,用PHP编成,尤其以插件的多样性吸引了大多数PE腐竹的目光。PM发布以来,网上插件层出不穷,包括多世界插件、防作弊插件等等许多种类。PM插件对于菜鸟来说似乎遥不可及,只能瞻仰着各路大神的插件漫天飞舞。但是,制作插件真的真的真的很困难吗?
不是的。PHP我认为是软件中BASIC、E语言以外最简单的语言,多用性、可塑性很强,特别好懂。学习一门像PHP的语言看起来似乎遥不可及,但是你一旦用心,就能和大神们一起创造。学习插件和玩PE一样,创造性强,没有做不到,只有想不到。相信屏幕前谁问你既然有一颗PE的心,那么一定能学好PM插件的。
你想制作一个自己的插件吗?如果是,又不知如何入手,那么让二菌我来引导你 ——
【首先,你得会开服务器】
开PM服务器教程网上挺多,可以去翻翻,可以参考下面的教程:
http://www.mcbbs.net/thread-101500-1-1.html
如果真看不懂,让二菌我来教你——
图片来源:https://github.com/PocketMine/PocketMine-MP/wiki/Setting-up-a-Server

第一步,搭建服务器环境
方法1【荐】:
这里我用Windows 2008 Server演示一下
1.先去下载 PHP5.4库
- 原帖下载地址貌似被墙,我这里有一个: 【点我!】
2.然后去下载ZIP的源代码
- 先打开官网 www.pocketmine.net 看到这里
- 然后往下看,点这里下载
- 下载完和刚才的PHP库解压后放在一起
方法2:
直接去首页www.pocketmine.net下载EXE安装包,按照提示安装
不过貌似连接被墙了,大多数时候上不起来
ok , 第一步完成
第二步,运行服务器
双击start.bat即可开服。

有同学可能注意到控制台的字是彩色的,如果发现自己的字不是彩色的,说明你的bin/mintty.exe没有找到,可以去下载我的PHP5.4库试一试,在方法1里面。{:10_492:}
服务器的其他指令我这里就不多讲了,可以去网上查一下。
【其次,你得会玩PHP】其实网上PHP教程也很多,这里有几个可以看看
http://www.w3school.com.cn/php/index.asp
http://www.php100.com/html/shipinjiaocheng/
真的看不懂?没事,别忘了这篇帖子是二菌写的...{:10_505:}
1.PHP的基本语法
> PHP程序格式
作为一个PHP程序,PHP要求每个程序以"<?php"开头,"?>"结尾,即:- PocketMine的插件作为大的PHP程序的一个片段,结尾可以不用输入,你愿意的话输入也可以。
> 给你的程序添加注释
PHP的程序有时候需要用到注释来解释你的程序,毕竟程序是写给人看的{:10_509:}
注释有两种:单行注释//和注释块/*..*/,注释是写起来给人看的,不会在机器里面运行。看这个例子:
这个程序运行后什么都不会发生。{:10_522:}
第一讲完
2.PHP的变量
> 变量的基本特征
PHP的变量和其它语言类似,也可以存储一个数字、字符串或者其它东西,并且可以在设置、赋值后重复调用。
不过,PHP是拜金主义者,它的每个变量调用和设置时都要把$放在变量名字前面(众:LZ你怎么说话的{:10_498:})
我们谈论变量时,一般用变量名字来谈论名字,而用$加上变量名字来代表变量本身。
变量名字必须符合以下规则:
- 变量名字必须以字母或者下划线"_"开头,如"abc""_1a"是可以的,但是"1a""变量a""#123"是不可以的。
- 变量名字必须只含数字、字母或者下划线,所以"a变量""b#%"是不可以的。
- 变量名字不能有空格。
> 设置变量的方法
PHP中设置变量的方法是这样的:var : 变量名字
value : 要设置的值
不要忘了PHP是拜金主义者,变量前面要加上$,漏掉后变量就无效了。
这样就可以设变量:
内容引用自shoghicp 的SimpleAuth:url找不到,抱歉
> 变量的类型
PHP的变量类型是怎么设定的呢?我们看下面:
内容引用自W3SCHOOL:http://www.w3school.com.cn/php/php_variables.asp
但是有时候我们需要把变量类型转换掉,所以我们需要改变变量的类型。怎么改变呢?请使用(变量类型)$变量名字。看下面的例子:这个例子里面,$a和$b是字符串,不能做数学的加减,所以我们需要把它转化为double类型来进行加减,然后转化会string类型输出。所以,它的输出是: 3 。
虽然PHP是一门松散类型的语言,但是变量的转化对它仍然重要。现将PHP中变量类型列表如下:
关于变量类型的其它信息可以参考这里:http://zhidao.baidu.com/link?url=5-7dbhJRiJ1kvICLEDeIt9SKPL-xFhO2NcdfxXX7wfbq6W5VPz5uY1QiE-C8DCNvlzMnAzluVlxSrd2rtQmYN_
PHP变量的定义就这么简单,你学会了吗?
第二讲完
3.PHP的字符串
> 字符串的特征
php中,字符串必须以""开头和结尾,所以在字符串中一些字符的打法有些不同,详见下表:
\n\r\t的详细解释可以参考这里:http://blog.csdn.net/jjmaiz/article/details/8212314
> 字符串变量
php中,字符串变量是一类变量,允许你存储一条字符串。在下面的例子里面,PHP把"PHP Program!"存进$str里面:上面代码的输出 :PHP Program!
现在,我们来试试用代码来处理我们的字符串。
> 并置运算符(Concatenation Operator)
在PHP中,并置运算符只有一个,它就是 —— . 。
别小看这个小圆点,TA可以把两个字符串连接起来!看这儿:上面代码的输出: abc1def。是不是连起来了呢?
再看下面的例子:
内容引用自PocketMine Team的PocketMine-MP/src/ConsoleAPI.php:www.pocketmine.net
红色:字符串1
蓝色:字符串2
红色和蓝色之间的部分: 并置运算符 .
这样"console.command."和$cmd就连接起来了,如果$cmd = "abc"那么连起来的值就是"console.command.abc"
字符串的函数还有很多,可以去看这里:http://www.w3school.com.cn/php/php_ref_string.asp ,二菌就先讲一个:
> strlen() 函数
strlen() 函数用于计算字符串的长度。我们来计算"PHP Program!"的长度:
上面代码的输出: 12
> 其它函数在这里可以找到:http://www.w3school.com.cn/php/php_ref_string.asp
第三讲完
4.PHP的运算符
> 运算符
运算符能对值进行运算。我把PHP完整的运算符列表于此:
- 算数运算符
+-*/小学老师都教过吧,不用说明了。% 就是求余数,小学老师好像也教过的,不过要注意左右两边不可以是小数。
++ 就是自加,让一个变量自加1,-- 类似。
大家都会了吗?{:10_521:}
- 赋值运算符
不用解释了吧= =
- 比较运算符
比较运算符里面需要注意的是大于等于和小于等于,先写><,再写=,别弄反了(众:>_<)
PHP里面还可能用到类型的比较,这时候我们可以用下面含有类型的比较运算符:
- 逻辑运算符
逻辑运算符中和或非的定义可以参照这里:http://baike.baidu.com/view/397415.htm
- instanceof
还有一种运算符叫作instanceof,它能判断一个变量是否属于这个类型。例子:返回值:0,字符串"2"类型是string不是double,所以返回false即0。
PHP的运算符在实际的判断中有很大的应用,将在下面的If中提到。
第四讲完
5.PHP的数组
> 数组是什么?
内容引用自W3SCHOOL:http://www.w3school.com.cn/php/php_variables.asp
所以,我们可以方便地通过数组来规定一系列变量。
> 数组的规定
数组存储的每个元素都带有一 ID 键,ID键可以是数字,也可以是以单引号开头结尾的一串字符(例如'abc')。数组有两种规定方法:
- 直接规定:
这时ID键会自动分配。从上面我们看到,数组每个元素不一定都是一种变量。
ID键自动分配的结果就是会以从0开始给每个元素分配ID键。所以上面的数组可以表示为:
当然,我们在定义时也可以自己规定ID键:
这里要注意的是,=>不要写错成=,逗号不要写错成分号。
也可以在后续的代码里面自己添加ID键:
这里我们看到了调用数组的一个方法:$变量名字[ID键]
当然,调用时ID键可以可以是变量,例如:
程序输出:a 。
当然,嵌套的数组也是OK的,例如:这时我们把嵌套的数组叫做多维数组。
多为数组的调用方法:$数组名字[$ID键][$ID键][$ID键]......
例如:
输出: a
> print_r()函数
print_r($数组名字)可以直接打印出数组,例如:
程序输出:
Array
(
[0] => Array
(
[0] => a
[1] => b
[2] => c
)
[1] => 2
)
于是数组所有的内容都出来了~!神奇吧~{:10_521:}
数组的其它命令可以参考这里:http://www.w3school.com.cn/php/php_ref_array.asp
第五讲完
6.PHP的基本语句块【If Switch 和循环语句】
> If、else和elseif
If、else和elseif这三个指令可以允许你判断,然后为判断的结果做出不同的动作。
- 如果你要在一个条件成立时使用代码,请用If。If的用法:
如果命令为多行,你应该用{}括起来,像这样:
- 如果你要判断一个条件成立或不成立是使用两个不同的代码,请用If和else。这两个东西的用法:
如果命令为多行,你也应该用{}括起来,像这样: - 如果你想要多个条件成立之一时运行不同的代码,请用If、else和elseif。用法:
同样地,我们应该这样设置多行:嗯..讲的太多是不是有些晕呢?(众:{:10_499:})那么我们来看一下例子。请看这儿:
内容引用自shoghicp的WorldEditor:url找不到,抱歉

这是一个简单的if else判断句。
红色:判断条件
蓝色:红色为true时的执行语句
绿色:红色是false时的执行语句
也就是说,如果$totalCount > 524288,那么$send = false;如果!($totalCount > 524288),那么$send = true.
再看这儿:
内容引用自Snake1999的SignTp:http://www.mcbbs.net/thread-226762-1-1.html
红色:判断条件
蓝色:红色为true时的执行语句
粉色:判断条件2
黑色:粉色为true时执行的语句
灰色:判断条件全都是false时执行的语句
也就是说,如果(double)$ver1e[1]<(double)$ver2e[1],那么返回值就是"2";如果....;如果(double)$ver1e[3]=(double)$ver2e[3],那么返回"0";如果全都是false,那么返回"1"。
现在懂了吗?{:10_496:}
> ... ? ... : ... 语句块
还有一种..?..:..语句块,方法与单行if..else类似:例子:
返回:1+1不等于3
不知大家发现了没,如果用elseif重复判断一个值是否为另一个值,会让代码过于麻烦,这时用搜寻语句块switch即可解决问题。{:10_525:}
> Switch
如果你希望有选择地执行若干代码块之一,可以使用 Switch 语句,这样可以避免冗长的if..elseif..else代码块。
- Switch 的工作原理
内容引用自 w3schoool:http://www.w3school.com.cn/php/php_switch.asp
所以,正确的 Switch 应该是这样的:
如果我们希望在表达式和两个值分别相等时都执行相同的代码,我们可以这样做:这样就方便多喽~{:10_492:}我们看这里:
内容引用自Snake1999的SignTp:http://www.mcbbs.net/thread-226762-1-1.html
这样我们可以看到,输入/st help [命令名字] 里面命令名字不同时,会返回不同的帮助文字,而且命令名不是下面列出的就会返回总的命令帮助。如果用if..else那会有多麻烦!{:10_499:}
还好PHP的发明者给我们带来了switch{:10_512:}
> 循环语句
PHP中循环语句有4种:while、do..while、for、foreach。喝杯茶,我们继续 ——
> while 和 do..while
- while 和 do..while 的用法
- while 和 do..while 的区别
while 和 do..while 都会在表达式成立的情况下重复执行代码,但是不同的是:
while 先判断表达式,后执行代码,再重复;
do..while 先执行代码,后判断表达式,再重复。
联想着判断语句的位置就会很好记。
> for
已经确定了代码块的重复执行次数时,可以使用 for 语句。
- for语句的原理:
1.先执行定义来定义循环所需变量和初始值,
2.然后执行一次代码,
3.再然后判断条件,如果为false则跳出循环
4.最后执行一次增量来增加变量。
- for语句的用法:
有点难懂?我们来看下面的例子:
这个代码先会定义i=0,然后echo i;,然后判断i是否小于3,最后执行i++;。所以它的输出是:012
懂了吗?那我继续讲{:10_508:}
> foreach
foreach 语句用于循环遍历数组。用法有两种:
比较好懂,是吗?
我们先看例子:
内容引用自ljyloo 的 TpMultiWorld:http://www.mcbbs.net/thread-148950-1-2.html
在这里foreach可以遍历$this->worlds数组,每个元素存储到$w中,然后达到列出所有世界的效果。
呼~终于讲完了{:10_508:}你懂了吗?
第六讲完
7.PHP函数
> 函数
函数是一种可以在任何被需要的时候执行的代码块。每个函数需要有一个名字来区分,名字的命名规则同变量名字的命名规则(忘了?返回去看看)。简单的函数创建需要以下几个步骤:
内容引用自W3SCHOOL:http://www.w3school.com.cn/php/php_functions.asp
也就是说,一个简单的函数应该是这样的:函数怎么调用呢?下面是一个例子:
从这里可以看到,我创建了一个名为pr的函数,可以输出abc然后换行,我可以直接用pr();来调用函数输出。于是上面的程序输出是:
PHP Program!
PHP Program!
懂了吗?{:10_505:}
> 带有参数的函数
我们例子里面的函数只是是一个非常简单的函数。它只能输出一个静态的字符串{:10_506:}。
加上参数后会让函数变得多姿多彩{:10_508:}。
通过可以添加参数,我们向函数添加更多的功能。参数类似一个变量。
你可能注意到了,函数名称后面有一个括号,比如 pr()。参数就是在括号中规定的。就像这样,我们就可以更改输出的字符:
这里函数的参数是$str,在使用函数时输入参数,就可以实现特定的功能。比如上面的程序输出是:
PHP Program!
Not a C Program!
如果要求用户没有输入某个参数是也能实现特定的功能,我们要规定参数的默认值,就像这样:这里可以看到第一个调用没有输入第一个参数,但是pr的定义里面规定了第一个参数的默认值,所以第一个参数就编程了"PHP",于是程序的输出是:
PHP Program!
Not a C Program!
第二个调用没有输入最后一个参数,这时候可以省略前面的逗号。
函数的参数我们学到这里。懂了吗?{:10_525:}
> 返回值
函数大家初中都学过,带入不同的x值会有不同的y值,为什么PHP的函数不能有函数值呢?于是,PHP的返回值就出现了{:10_500:}
返回值应该怎么设置和调用呢?看这儿:可以看出,return 值; 是返回值得一个关键。返回了一个值,就可以对它进行运算,甚至调用到其它函数里面,你可以像变量一样折腾一个函数的返回值,一样可以用echo打印输出。所以这个程序的输出是: 3
我们来看下面的例子:
内容引用自PocketMine Team的PocketMine-MP/src/ConsoleAPI,部分折叠:www.pocketmine.net

红色:参数定义
蓝色:返回命令
从这里看到,run这个函数定义了几个参数,都设定了默认值,又加了return来返回值,是一个比较复杂的函数了。
关于函数,就讲到这里。你懂了吗?{:10_531:}
第七讲完
8.PHP class类
没错,你看到这里的时候,没看的PHP的教程只有一节了。加油,把它看完!
> class类
PHP中,有时候需要把零散的代码分成几个部分,于是,类的概念就诞生了。每个class,或者说类,由以下几个部分组成:
内容引用自kv516 的 PocketEssentials:http://www.mcbbs.net/thread-196684-1-1.html
红色:声明这是一个class
蓝色:class的名字
绿色:接口,右边的Plugin是接口名字(下面会讲),省略即为一般class
黑色:声明{}里面是class的内容。
粉色:class的内容
于是,这样一个class就声明好了。
> 调用方法
在class内,我们用$this来代表class本身,所以:
- class内定义变量(非函数内定义)的调用方法为:$this->变量
- class内定义函数的调用方法为:$this->函数名字(参数)
但是函数内定义变量调用方法仍为$变量。看下面:
这个例子里面$isb是函数内定义变量,调用方法仍为$isb,而class内定义变量$a、$b则需要用$this->a和$this->b来调用。
> 跨class调用方法
我们在玩PHP的时候可能会用到调用另外一个class的变量或者函数,这时候我们需要这样做:
- 另外一个class的名字::变量
- 另外一个class的名字::函数(参数)
请看下面的例子:
这个例子里面在class a里面定义了get这个函数,如果我们运行class b的init函数,就会调用class a返回a::b的值,然后输出。所以这个程序的输出是:This is b
懂了吗?{:10_505:}
> 使用范围
声明玩一个class后,一个问题出来了:class里面有些函数和变量仅适合class内部使用或者不希望公开,其它的一些希望公开,那该怎么办呢?我们可以使用public和private。
怎么理解呢?在定义函数和变量时前面加上public,就可以允许其它class用::来调用,private则不允许。我们看这里:内容引用自Snake1999 的 SignTp:http://www.mcbbs.net/thread-226762-1-1.html
这里不同的function都用颜色标出来了,但是里面一些变量不希望外面调用,所以是private。
> class接口
【WARNING:前方高能,请无关人员迅速撤离!{:10_542:}】
什么是接口?接口允许你创建一类相似的class,以便调用。
class定义时接上这个接口,意味着需要含有接口规定的一切函数和变量。例如上面的Plugin就是一个接口,定义了一类相似的class。我们看这里:
内容引用自PocketMine Team的PocketMine-MP/src/PluginAPI:www.pocketmine.net
上面的例子规定了一个叫做Plugin的接口,然后创建了一个叫做DummyPlugin的类,这个DummyPlugin就是一个标准的Plugin,拥有接口规定的所有函数(含参数)和变量。如果缺少任何一个,就不是这个接口对应的class。
现在懂了吗?
第八讲完
孩子,你看到这里了,说明你对于PHP玩的差不多了,为制作一个PM插件已经打好了基础,往下看吧。
【最后,再想着做插件】
大家上面看完了吗?(众:看~完~了~)
那好,我们就开始做插件吧。
接下来,我们以SignTp插件作为目标,一步一步完成。
我们的插件要可以:
> 扔一个牌子就能传送到目的地!
> 有自动更新功能!
所以它需要:
> 有一堆命令
> 检测一堆事件
> 读取一堆配置文件
> 等等......
这看起来似乎很难的样子,让我们一步一步制作完毕。
0.一些准备
文本部分来自 http://www.mcbbs.net/thread-204040-1-1.html ,原帖为JS,其实PHP和JS编辑器是基本一样的。
> 首先你需要装了PM服务端的电脑一台,用作开服务器(技术宅可以用安卓手机,详情右转【此处】)
> 然后你需要文本编辑器一只,这个种类繁多,下面我来推荐几个:
> 其次是装了MCPE手机或平板一台,用作调试
1.你的第一个PM插件
> 无中生有的第一步
> 首先,你需要打开你的服务端然后关闭,我们会发现多了一些文件夹,我们的插件就要放在/plugins里面。

> 然后,我们在/plugins里面创建一个php文件,名字可以最好能表现插件的名字等等。
这里我们以SignTp为例子,创建一个SignTp.php

> 在编辑器里打开,没错,空的。
还记得上面PHP教程怎么说的?(众:php文件一定要以"<?php"开头)好的,我们加上。
> 作为一个PM的插件,我们需要用Plugin这个接口。看这儿:内容引用自PocketMine Team的PocketMine-MP/src/PluginAPI:www.pocketmine.net

这个接口说明了一个Plugin必备的三个函数,所以一般的PM插件格式是这样的:
内容引用自Snake1999 的 SignTp:http://www.mcbbs.net/thread-226762-1-1.html

天蓝:PM插件必备的注释部分。请看这里:
/*
__PocketMine Plugin__
name=PluginXXX <<插件名字,会在控制台插件加载时显示
description= <<插件说明,貌似没用
version=0.0.1 <<插件版本,会在控制台插件加载时显示
author=XXX <<插件作者,会在控制台插件加载时显示,也能说明版权
class=PluginXXX <<插件主类名字,和下面的class PluginXXX ....名字应该一样
apiversion=11 <<插件兼容API版本,用逗号隔开(以后会讲)
*/
紫红:插件的主类。里面塞着插件大部分的内容。
深蓝:预处理插件时触发的function。这里需要定义api这个变量作为插件与服务器沟通的桥梁。
绿色:卸载时触发的function。<<Tip:这里的卸载是加载的反义词,不是删除!!
红色:插件加载时促发的function。
所以,一个空的插件应该是这样的:保存,打开Start.bat,我们会看到:

没错,你的插件被加载了!{:10_509:} 虽然没什么用。{:10_494:}
赶紧放到SignTp里面,于是我们的代码是这样的:第一讲完
2.给你的插件添加命令
> 键盘敲一敲,服务器嗨起来
> 命令的用法命令能干啥?很多插件都需要命令。命令允许玩家在游戏中玩转插件,那么该怎么添加命令呢?
我们先看这里:
内容引用自kv516 的 PocketEssentials:http://www.mcbbs.net/thread-196684-1-1.html

红色:从api提供的方法注册一个命令
蓝色:命令的名字
粉色:命令在 " /help 名字 " 里面显示出的帮助文字
青色:激活命令后触发的function所在的类,一般用$this
棕色:激活命令后触发的function名字,下面要相同
那么如果我们需要让命令实现同样的功能,或者能让一般玩家可以用,该怎么办呢?
我们先看这里:
内容引用自ljyloo 的 TpMultiWorld:http://www.mcbbs.net/thread-148950-1-2.html

红2:注册一个相同的命令,即/w 和/tpw 有相同的作用,在下面command只需要规定/tpw即可。
粉2:要注册相同指令的目标指令,即未规定但要与元指令相同指令。
绿2:要注册相同指令的原指令,即规定要与目标指令相同的指令。
蓝2:注册一个一般玩家可以能用的指令
黑2:要注册一般玩家可以能用的指令命令的名字
于是,我们注册了一个命令,接下来要定义它的作用。我们继续看上面的图:
红1:要和注册指令右边的红圈相同,是激活命令后触发的function名字。
黑1:$cmd : 激活的命令名称,比如"tpw" "listw"等
蓝1:$params : 激活的子命令的名称
紫1:$issuer : 该玩家的Player对象
绿1:$alias : 这个命令的相同的指令,如"tpw" 的alias 是"w",多个就是数组
其实这里$cmd等等名字改掉是可以的,但是$cmd这几个大家都习惯了,所以建议保留,详细看下面。
请看这里的例子:
如果一个玩家输入了/tpw 123 456 789
那么返回的$cmd = "tpw"
$params[0] = "123"
$params[1] = "456"
$params[2] = "789"
$issuer = 该玩家的Player对象(以后会讲)
$alias = "w"
然后,加上一个switch,就可以让命令有作用喽~
就像这样:
内容引用自MinecrafterJPN 的 PocketMoney:http://forums.pocketmine.net/plugins/pocketmoney.63/

就这样搜寻以后/money指令就起作用了,赶紧拿来试试!保存,运行
在粉色部分,我们看到我们的插件被加载了,输入/st以后,console返回了123;在/? st里面也有了相应的解释。说明我们的命令起作用喽~
在命令执行的部分,我们可以使用return来返回一个值让使用者知道,所以上面代码可以改为:
这样console返回就是 [CMD] 123 了。同样地,玩家也能使用/st来返回123。
> 添加功能
我们玩过的插件命令功能绝没有输出123那么简单,这时候我们就需要发挥想象力,参考下面的附录可以看你能干啥,然后搭配好代码,就能让你的命令多姿多彩。
第二讲完
================== 坑 线 =================
3.为你的插件检测事件
> 石头:现在你还你敢敲我?
第三讲完
【附录】
1.PM常见命令
> console
console命令用于在控制台输出一条带现在时间的信息。
用法:console($message, $EOL = true, $log = true, $level = 1)
$message:信息的文本。
$EOL:决定是否在信息末尾加上PHP_EOL(换行)。默认true为加上。
$log:决定是否记录在console.log内。默认true。
$level:这个我也不知道= =谁来告诉我
- $message含下面的内容将会设置输出文字的颜色,下面是常用的颜色:
所有的颜色可以在/src/utils/TextFormat.php里面查看。
添加颜色的方法:把内容用 . 连接到字符串里,如:输出:[CMD] REDBLACK
> API11的常见命令就这么一个= =待添加第一讲完
2.PM数据类型
> Vector3
在PM插件制作时,很多时候会用到三轴坐标,于是Vector3就诞生了。{:10_525:}
- 定义方法
这里new这个单词能告诉PHP要创建一个新Vector3类型的变量;xyz参数告诉PHP这个三轴坐标的位置。
- Vector3类型的常用方法
假如$var(1.4, -2, 3.6)是一个vector3对象,你可以......
* 相邻坐标的定义见下:如果坐标方向按MC的定义且x轴向右z轴向前,即
那么:
有点乱是吗?(众:{:10_499:})其实Vector3还有很多方法,可以看/src/math/Vector3.php,这里只列出常用的一部分。有了Vector3,就可以方便地表示坐标了{:10_525:}> PM API11常用的数据类型貌似就这一个了= =
第二讲完
3.PM对象
> 对象是什么
对象(object)是一种变量类型,允许你调用程序内部特定的内容。比如,一个世界就是一个level对象,你的插件可以通过更改level对象来改变世界的信息。
> Position对象
- 源文件位置(忘记指令之类的可以去翻源文件,接下来不再提示):/src/world/Position.php
- 特性
Position对象用于表达一个事物的坐标,包括xyz坐标和世界。
Position对象源文件的开头有这样一句话:
也就是说:Position其实就是一个Vector3对象,接口了Vector3{:10_496:},于是Vector3的方法和Position的方法是相似滴~
- 方法
如果$pos是一个Position对象,那么你除了可以用Vector3的方法,还可以——
这样子表示位置是不是方便多了呢~
> Level对象
- 源文件位置:/src/world/Level.php
- 方法
如果$lev是一个level对象,那么你可以——
======================== 坑线 ==========================
第三讲完
======================== 坑线 ==========================
4.PM API解析【已更API11】
第四讲完

P o c k e t M i n e - M P
插 件 制 作 教 程
二 菌 出 品
Now, let's begin.
【前言】
咳咳,大家好,我是二菌。今天我给大家带来的就是我的PM插件制作教程。
PM,全称PocketMine-MP,是PE服务器软件中最流行的一种,用PHP编成,尤其以插件的多样性吸引了大多数PE腐竹的目光。PM发布以来,网上插件层出不穷,包括多世界插件、防作弊插件等等许多种类。PM插件对于菜鸟来说似乎遥不可及,只能瞻仰着各路大神的插件漫天飞舞。但是,制作插件真的真的真的很困难吗?
不是的。PHP我认为是软件中BASIC、E语言以外最简单的语言,多用性、可塑性很强,特别好懂。学习一门像PHP的语言看起来似乎遥不可及,但是你一旦用心,就能和大神们一起创造。学习插件和玩PE一样,创造性强,没有做不到,只有想不到。相信屏幕前谁问你既然有一颗PE的心,那么一定能学好PM插件的。
你想制作一个自己的插件吗?如果是,又不知如何入手,那么让二菌我来引导你 ——
【首先,你得会开服务器】
开PM服务器教程网上挺多,可以去翻翻,可以参考下面的教程:
http://www.mcbbs.net/thread-101500-1-1.html
如果真看不懂,让二菌我来教你——
图片来源:https://github.com/PocketMine/PocketMine-MP/wiki/Setting-up-a-Server

第一步,搭建服务器环境
方法1【荐】:
方法2:
ok , 第一步完成
第二步,运行服务器
双击start.bat即可开服。

有同学可能注意到控制台的字是彩色的,如果发现自己的字不是彩色的,说明你的bin/mintty.exe没有找到,可以去下载我的PHP5.4库试一试,在方法1里面。{:10_492:}
服务器的其他指令我这里就不多讲了,可以去网上查一下。
【其次,你得会玩PHP】
其实网上PHP教程也很多,这里有几个可以看看http://www.w3school.com.cn/php/index.asp
http://www.php100.com/html/shipinjiaocheng/
真的看不懂?没事,别忘了这篇帖子是二菌写的...{:10_505:}
1.PHP的基本语法
2.PHP的变量
3.PHP的字符串
4.PHP的运算符
5.PHP的数组
6.PHP的基本语句块【If Switch 和循环语句】
7.PHP函数
8.PHP class类
孩子,你看到这里了,说明你对于PHP玩的差不多了,为制作一个PM插件已经打好了基础,往下看吧。
【最后,再想着做插件】
大家上面看完了吗?(众:看~完~了~)
那好,我们就开始做插件吧。
接下来,我们以SignTp插件作为目标,一步一步完成。
我们的插件要可以:
> 扔一个牌子就能传送到目的地!
> 有自动更新功能!
所以它需要:
> 有一堆命令
> 检测一堆事件
> 读取一堆配置文件
> 等等......
这看起来似乎很难的样子,让我们一步一步制作完毕。
0.一些准备
1.你的第一个PM插件
> 无中生有的第一步
2.给你的插件添加命令
> 键盘敲一敲,服务器嗨起来
================== 坑 线 =================
3.为你的插件检测事件
> 石头:现在你还你敢敲我?
【附录】
1.PM常见命令
2.PM数据类型
3.PM对象
======================== 坑 线 ==========================
4.PM API解析【已更API11】
来自群组: PocketMine开发&讨论
2021.12 数据,可能有更多内容

Now, let's begin.【前言】
咳咳,大家好,我是二菌。今天我给大家带来的就是我的PM插件制作教程。
PM,全称PocketMine-MP,是PE服务器软件中最流行的一种,用PHP编成,尤其以插件的多样性吸引了大多数PE腐竹的目光。PM发布以来,网上插件层出不穷,包括多世界插件、防作弊插件等等许多种类。PM插件对于菜鸟来说似乎遥不可及,只能瞻仰着各路大神的插件漫天飞舞。但是,制作插件真的真的真的很困难吗?
不是的。PHP我认为是软件中BASIC、E语言以外最简单的语言,多用性、可塑性很强,特别好懂。学习一门像PHP的语言看起来似乎遥不可及,但是你一旦用心,就能和大神们一起创造。学习插件和玩PE一样,创造性强,没有做不到,只有想不到。相信屏幕前谁问你既然有一颗PE的心,那么一定能学好PM插件的。
你想制作一个自己的插件吗?如果是,又不知如何入手,那么让二菌我来引导你 ——
【首先,你得会开服务器】
开PM服务器教程网上挺多,可以去翻翻,可以参考下面的教程:
http://www.mcbbs.net/thread-101500-1-1.html
如果真看不懂,让二菌我来教你——
图片来源:https://github.com/PocketMine/PocketMine-MP/wiki/Setting-up-a-Server

第一步,搭建服务器环境
方法1【荐】:
这里我用Windows 2008 Server演示一下
1.先去下载 PHP5.4库
- 原帖下载地址貌似被墙,我这里有一个: 【点我!】
2.然后去下载ZIP的源代码
- 先打开官网 www.pocketmine.net 看到这里

- 然后往下看,点这里下载

- 下载完和刚才的PHP库解压后放在一起

方法2:
直接去首页www.pocketmine.net下载EXE安装包,按照提示安装
不过貌似连接被墙了,大多数时候上不起来

ok , 第一步完成
第二步,运行服务器
双击start.bat即可开服。

有同学可能注意到控制台的字是彩色的,如果发现自己的字不是彩色的,说明你的bin/mintty.exe没有找到,可以去下载我的PHP5.4库试一试,在方法1里面。{:10_492:}
服务器的其他指令我这里就不多讲了,可以去网上查一下。
【其次,你得会玩PHP】其实网上PHP教程也很多,这里有几个可以看看
http://www.w3school.com.cn/php/index.asp
http://www.php100.com/html/shipinjiaocheng/
真的看不懂?没事,别忘了这篇帖子是二菌写的...{:10_505:}
1.PHP的基本语法
> PHP程序格式
作为一个PHP程序,PHP要求每个程序以"<?php"开头,"?>"结尾,即:
代码:
- <?php
- ?>
> 给你的程序添加注释
PHP的程序有时候需要用到注释来解释你的程序,毕竟程序是写给人看的{:10_509:}
注释有两种:单行注释//和注释块/*..*/,注释是写起来给人看的,不会在机器里面运行。看这个例子:
代码:
- <?php
- /* 注释块!!!
- 这里不会被运行!
- */
- //我是单行注释
- ?>
第一讲完
2.PHP的变量
> 变量的基本特征
PHP的变量和其它语言类似,也可以存储一个数字、字符串或者其它东西,并且可以在设置、赋值后重复调用。
不过,PHP是拜金主义者,它的每个变量调用和设置时都要把$放在变量名字前面(众:LZ你怎么说话的{:10_498:})
我们谈论变量时,一般用变量名字来谈论名字,而用$加上变量名字来代表变量本身。
变量名字必须符合以下规则:
- 变量名字必须以字母或者下划线"_"开头,如"abc""_1a"是可以的,但是"1a""变量a""#123"是不可以的。
- 变量名字必须只含数字、字母或者下划线,所以"a变量""b#%"是不可以的。
- 变量名字不能有空格。
> 设置变量的方法
PHP中设置变量的方法是这样的:
代码:
- $var = value;
value : 要设置的值
不要忘了PHP是拜金主义者,变量前面要加上$,漏掉后变量就无效了。
这样就可以设变量:
内容引用自shoghicp 的SimpleAuth:url找不到,抱歉

> 变量的类型
PHP的变量类型是怎么设定的呢?我们看下面:
内容引用自W3SCHOOL:http://www.w3school.com.cn/php/php_variables.asp
PHP 是一门松散类型的语言(Loosely Typed Language)
在 PHP 中,不需要在设置变量之前声明该变量。
在上面的例子中,您看到了,不必向 PHP 声明该变量的数据类型。
根据变量被设置的方式,PHP 会自动地把变量转换为正确的数据类型。
在强类型的编程语言中,您必须在使用前声明变量的类型和名称。
在 PHP 中,变量会在使用时被自动声明。
在 PHP 中,不需要在设置变量之前声明该变量。
在上面的例子中,您看到了,不必向 PHP 声明该变量的数据类型。
根据变量被设置的方式,PHP 会自动地把变量转换为正确的数据类型。
在强类型的编程语言中,您必须在使用前声明变量的类型和名称。
在 PHP 中,变量会在使用时被自动声明。
但是有时候我们需要把变量类型转换掉,所以我们需要改变变量的类型。怎么改变呢?请使用(变量类型)$变量名字。看下面的例子:
代码:
- $a = "1";
- $b = "2";
- $c = (string)((double)$a + (double)$b);
虽然PHP是一门松散类型的语言,但是变量的转化对它仍然重要。现将PHP中变量类型列表如下:
类型名字 |
存贮类型 |
例子 |
string |
字符串 |
"PHP Program!" |
boolean |
布尔值 |
true |
double |
双精度数字(精度很高,±1.7E-308~±1.7E+308,含0) |
1.23456 |
integer |
整数(-2147483648~+2147483647) |
123 |
array |
数组(下面会讲) |
array(123,456) |
object |
对象(可理解为class类等) |
ServerAPI |
PHP变量的定义就这么简单,你学会了吗?
第二讲完
3.PHP的字符串
> 字符串的特征
php中,字符串必须以""开头和结尾,所以在字符串中一些字符的打法有些不同,详见下表:
字符 |
字符串中打法 |
" |
\" |
\ |
\\ |
换行 |
\n |
送出CR |
\r |
tab跳位 |
\t |
> 字符串变量
php中,字符串变量是一类变量,允许你存储一条字符串。在下面的例子里面,PHP把"PHP Program!"存进$str里面:
代码:
- <?php
- $str = "PHP Program!";
- echo $str;
- ?>
现在,我们来试试用代码来处理我们的字符串。
> 并置运算符(Concatenation Operator)
在PHP中,并置运算符只有一个,它就是 —— . 。
别小看这个小圆点,TA可以把两个字符串连接起来!看这儿:
代码:
- <?php
- $a = "1";
- $str = "abc".$a."def";
- echo str;
- ?>
再看下面的例子:
内容引用自PocketMine Team的PocketMine-MP/src/ConsoleAPI.php:www.pocketmine.net

红色:字符串1
蓝色:字符串2
红色和蓝色之间的部分: 并置运算符 .
这样"console.command."和$cmd就连接起来了,如果$cmd = "abc"那么连起来的值就是"console.command.abc"
字符串的函数还有很多,可以去看这里:http://www.w3school.com.cn/php/php_ref_string.asp ,二菌就先讲一个:
> strlen() 函数
strlen() 函数用于计算字符串的长度。我们来计算"PHP Program!"的长度:
代码:
- <?php
- echo strlen("PHP Program!");
- ?>
上面代码的输出: 12
> 其它函数在这里可以找到:http://www.w3school.com.cn/php/php_ref_string.asp
第三讲完
4.PHP的运算符
> 运算符
运算符能对值进行运算。我把PHP完整的运算符列表于此:
- 算数运算符
运算符 |
说明 |
例子 |
返回 |
+ |
求两个值的和 |
x=1+1; |
x=2 |
- |
求两个值的差 |
x=2-1; |
x=1 |
* |
求两个值的积 |
x=2*2; |
x=4 |
/ |
求两个值相除的商 |
x=6/3; |
x=2 |
% |
求两个值相除的余数 |
x=7%3; y=9%3; |
x=1 y=0 |
++ |
让一个值自加1 |
x=1;x++; |
x=2 |
-- |
让一个值自减1 |
x=3;x--; |
x=2 |
++ 就是自加,让一个变量自加1,-- 类似。
大家都会了吗?{:10_521:}
- 赋值运算符
运算符 |
说明 |
例子 |
返回 |
= |
赋值(貌似说过) |
x=2; |
x=2 |
+= |
自添加 |
x=3;x+=4; |
x=3+4=7 |
-= |
自减去 |
x=5;x-=3; |
x=5-3=2 |
*= |
自乘 |
x=2;x*=3; |
x=2*3=6 |
/= |
自除以 |
x=6;x/=3; |
x=6/3=2 |
%= |
得到余数 |
x=7;x%=3; |
x=7%3=1 |
.= |
在末尾加上 |
x="1";x.="2" |
x="1"."2"="12" |
- 比较运算符
运算符 |
说明 |
例子 |
返回 |
== |
是否相等 |
1+1==3 |
false |
!= |
是否不等 |
1+1!=3 |
true |
>= |
是否大于等于 |
2>=3 |
false |
<= |
是否小于等于 |
2<=3 |
true |
> |
是否大于 |
1>2 |
false |
< |
是否小于 |
1<2 |
true |
PHP里面还可能用到类型的比较,这时候我们可以用下面含有类型的比较运算符:
运算符 |
返回true条件 |
例子 |
返回 |
=== |
类型相等 值相等 |
2==="2" 2===2 |
false true |
!== |
类型不等 值相等 |
2!=="2" 2!==2 |
true false |
- 逻辑运算符
运算符 |
说明 |
例子 |
返回 |
&& |
和 |
(1==1)&&(2==2) |
true |
|| |
或 |
(1>2)||(3<2) |
false |
! |
非 |
!(1>2) |
true |
- instanceof
还有一种运算符叫作instanceof,它能判断一个变量是否属于这个类型。例子:
代码:
- echo (string)("2" instanceof double)
PHP的运算符在实际的判断中有很大的应用,将在下面的If中提到。
第四讲完
5.PHP的数组
> 数组是什么?
内容引用自W3SCHOOL:http://www.w3school.com.cn/php/php_variables.asp
在使用 PHP 进行开发的过程中,你可能需要创建许多相似的变量。无需很多相似的变量,你可以把数据作为元素存储在数组中。
数组中的元素都有自己的 ID,因此可以方便地访问它们。
数组中的元素都有自己的 ID,因此可以方便地访问它们。
所以,我们可以方便地通过数组来规定一系列变量。
> 数组的规定
数组存储的每个元素都带有一 ID 键,ID键可以是数字,也可以是以单引号开头结尾的一串字符(例如'abc')。数组有两种规定方法:
- 直接规定:
代码:
- $arr = array("a",1,true);
ID键自动分配的结果就是会以从0开始给每个元素分配ID键。所以上面的数组可以表示为:
ID键 |
值 |
0 |
"a" |
1 |
1 |
2 |
true |
当然,我们在定义时也可以自己规定ID键:
代码:
- $arr = array(
- "str" => "a",
- 0 => 1,
- "bool" => true,
- );
也可以在后续的代码里面自己添加ID键:
代码:
- $arr['str'] = "a";
- $arr[0] = 1;
- $arr['bool'] = true;
当然,调用时ID键可以可以是变量,例如:
代码:
- $arr = array(
- "str" => "a",
- 0 => 1,
- "bool" => true,
- );
当然,嵌套的数组也是OK的,例如:
代码:
- $a = array(
- 0 => array(
- "x" => "a",
- ),
- 1 => 2,
- );
多为数组的调用方法:$数组名字[$ID键][$ID键][$ID键]......
例如:
代码:
- $a = array(
- 0 => array(
- "x" => "a",
- ),
- 1 => 2,
- );
- echo $a[0]['x'];
> print_r()函数
print_r($数组名字)可以直接打印出数组,例如:
代码:
- $a = array(
- 0 => array(
- "a",
Array
(
[0] => Array
(
[0] => a
[1] => b
[2] => c
)
[1] => 2
)
于是数组所有的内容都出来了~!神奇吧~{:10_521:}
数组的其它命令可以参考这里:http://www.w3school.com.cn/php/php_ref_array.asp
第五讲完
6.PHP的基本语句块【If Switch 和循环语句】
> If、else和elseif
If、else和elseif这三个指令可以允许你判断,然后为判断的结果做出不同的动作。
- 如果你要在一个条件成立时使用代码,请用If。If的用法:
代码:
- if(判断条件) 命令;
代码:
- if(判断条件){
- 命令;
- }
- 如果你要判断一个条件成立或不成立是使用两个不同的代码,请用If和else。这两个东西的用法:
代码:
- if(判断条件) 为true时执行命令;
- else 为false时执行命令;
代码:
- if(判断条件) {
- 为true时执行命令;
- }else{
- 为false时执行命令;
- }
代码:
- if(判断条件1) 判断条件1为true时命令;
- elseif(判断条件2) 判断条件2为true时命令;
- elseif(判断条件3) 判断条件3为true时命令;
- .......
代码:
- if(判断条件1) {
- 判断条件1为true时命令;
- }elseif(判断条件2){
- 判断条件2为true时命令;
- }elseif(判断条件3){
- 判断条件3为true时命令;
- .......
- }else{
- 判断条件全部为false时命令;
- }
内容引用自shoghicp的WorldEditor:url找不到,抱歉

这是一个简单的if else判断句。
红色:判断条件
蓝色:红色为true时的执行语句
绿色:红色是false时的执行语句
也就是说,如果$totalCount > 524288,那么$send = false;如果!($totalCount > 524288),那么$send = true.
再看这儿:
内容引用自Snake1999的SignTp:http://www.mcbbs.net/thread-226762-1-1.html

红色:判断条件
蓝色:红色为true时的执行语句
粉色:判断条件2
黑色:粉色为true时执行的语句
灰色:判断条件全都是false时执行的语句
也就是说,如果(double)$ver1e[1]<(double)$ver2e[1],那么返回值就是"2";如果....;如果(double)$ver1e[3]=(double)$ver2e[3],那么返回"0";如果全都是false,那么返回"1"。
现在懂了吗?{:10_496:}
> ... ? ... : ... 语句块
还有一种..?..:..语句块,方法与单行if..else类似:
代码:
- $变量 = (判断条件)?为true是返回值 : 为false时返回值 ;
代码:
- echo (1+1==3)?"1+1竟然等于3":"1+1不等于3";
不知大家发现了没,如果用elseif重复判断一个值是否为另一个值,会让代码过于麻烦,这时用搜寻语句块switch即可解决问题。{:10_525:}
> Switch
如果你希望有选择地执行若干代码块之一,可以使用 Switch 语句,这样可以避免冗长的if..elseif..else代码块。
- Switch 的工作原理
内容引用自 w3schoool:http://www.w3school.com.cn/php/php_switch.asp
1.对表达式(通常是变量)进行一次计算
2.把表达式的值与结构中 case 的值进行比较
3.如果存在匹配,则执行与 case 关联的代码
4.代码执行后,break 语句阻止代码跳入下一个 case 中继续执行
5.如果没有 case 为真,则使用 default 语句
2.把表达式的值与结构中 case 的值进行比较
3.如果存在匹配,则执行与 case 关联的代码
4.代码执行后,break 语句阻止代码跳入下一个 case 中继续执行
5.如果没有 case 为真,则使用 default 语句
所以,正确的 Switch 应该是这样的:
代码:
- switch(表达式){
- case 值1:
- 表达式=值1时执行的代码;
- break;
- case 值2:
- 表达式=值2时执行的代码;
- break;
- default:
- 表达式都不等时执行的代码;
- break;
- }
代码:
- switch(表达式){
- case 值1:
- case 值2:
- 表达式=值1或值2时执行的代码;
- break;
- default:
- 表达式都不等时执行的代码;
- break;
- }
内容引用自Snake1999的SignTp:http://www.mcbbs.net/thread-226762-1-1.html

这样我们可以看到,输入/st help [命令名字] 里面命令名字不同时,会返回不同的帮助文字,而且命令名不是下面列出的就会返回总的命令帮助。如果用if..else那会有多麻烦!{:10_499:}
还好PHP的发明者给我们带来了switch{:10_512:}
> 循环语句
PHP中循环语句有4种:while、do..while、for、foreach。喝杯茶,我们继续 ——
> while 和 do..while
- while 和 do..while 的用法
代码:
- while(表达式) 执行的代码;
- while(表达式){
- 执行的代码;
- }
- do{
- 执行的代码;
- }
- while(表达式);
- while 和 do..while 的区别
while 和 do..while 都会在表达式成立的情况下重复执行代码,但是不同的是:
while 先判断表达式,后执行代码,再重复;
do..while 先执行代码,后判断表达式,再重复。
联想着判断语句的位置就会很好记。
> for
已经确定了代码块的重复执行次数时,可以使用 for 语句。
- for语句的原理:
1.先执行定义来定义循环所需变量和初始值,
2.然后执行一次代码,
3.再然后判断条件,如果为false则跳出循环
4.最后执行一次增量来增加变量。
- for语句的用法:
代码:
- for(定义;条件;增量){
- 代码;
- }
代码:
- for(i=0;i<3;i++){
- echo i;
- }
懂了吗?那我继续讲{:10_508:}
> foreach
foreach 语句用于循环遍历数组。用法有两种:
代码:
- foreach($数组名字 as $数组元素){
- 代码;
- }
- foreach($数组名字 as $数组ID键 => $数组元素){
- 代码;
- }
我们先看例子:
内容引用自ljyloo 的 TpMultiWorld:http://www.mcbbs.net/thread-148950-1-2.html

在这里foreach可以遍历$this->worlds数组,每个元素存储到$w中,然后达到列出所有世界的效果。
呼~终于讲完了{:10_508:}你懂了吗?
第六讲完
7.PHP函数
> 函数
函数是一种可以在任何被需要的时候执行的代码块。每个函数需要有一个名字来区分,名字的命名规则同变量名字的命名规则(忘了?返回去看看)。简单的函数创建需要以下几个步骤:
内容引用自W3SCHOOL:http://www.w3school.com.cn/php/php_functions.asp
1.所有的函数都使用关键词 "function()" 来开始
2.命名函数 - 函数的名称应该提示出它的功能。函数名称以字母或下划线开头。
3.添加 "{" - 开口的花括号之后的部分是函数的代码。
4.插入函数代码
5.添加一个 "}" - 函数通过关闭花括号来结束。
2.命名函数 - 函数的名称应该提示出它的功能。函数名称以字母或下划线开头。
3.添加 "{" - 开口的花括号之后的部分是函数的代码。
4.插入函数代码
5.添加一个 "}" - 函数通过关闭花括号来结束。
也就是说,一个简单的函数应该是这样的:
代码:
- function 函数名字(){
- 代码;
- }
代码:
- function pr(){
- echo "PHP Program!\n";
- }
- pr();
- pr();
PHP Program!
PHP Program!
懂了吗?{:10_505:}
> 带有参数的函数
我们例子里面的函数只是是一个非常简单的函数。它只能输出一个静态的字符串{:10_506:}。
加上参数后会让函数变得多姿多彩{:10_508:}。
通过可以添加参数,我们向函数添加更多的功能。参数类似一个变量。
你可能注意到了,函数名称后面有一个括号,比如 pr()。参数就是在括号中规定的。就像这样,我们就可以更改输出的字符:
代码:
- function pr($str){
- echo $str." Program!\n";
- }
- pr("PHP");
- pr("Not a C");
PHP Program!
Not a C Program!
如果要求用户没有输入某个参数是也能实现特定的功能,我们要规定参数的默认值,就像这样:
代码:
- function pr($str = "PHP",$str2 = " Program!"){
- echo $str.$str2."\n";
- }
- pr(,"Program!");
- pr("Not a C");
PHP Program!
Not a C Program!
第二个调用没有输入最后一个参数,这时候可以省略前面的逗号。
函数的参数我们学到这里。懂了吗?{:10_525:}
> 返回值
函数大家初中都学过,带入不同的x值会有不同的y值,为什么PHP的函数不能有函数值呢?于是,PHP的返回值就出现了{:10_500:}
返回值应该怎么设置和调用呢?看这儿:
代码:
- function add($a,$b){
- return $a+$b;
- }
- echo add(1,2);
我们来看下面的例子:
内容引用自PocketMine Team的PocketMine-MP/src/ConsoleAPI,部分折叠:www.pocketmine.net

红色:参数定义
蓝色:返回命令
从这里看到,run这个函数定义了几个参数,都设定了默认值,又加了return来返回值,是一个比较复杂的函数了。
关于函数,就讲到这里。你懂了吗?{:10_531:}
第七讲完
8.PHP class类
没错,你看到这里的时候,没看的PHP的教程只有一节了。加油,把它看完!
> class类
PHP中,有时候需要把零散的代码分成几个部分,于是,类的概念就诞生了。每个class,或者说类,由以下几个部分组成:
内容引用自kv516 的 PocketEssentials:http://www.mcbbs.net/thread-196684-1-1.html

红色:声明这是一个class
蓝色:class的名字
绿色:接口,右边的Plugin是接口名字(下面会讲),省略即为一般class
黑色:声明{}里面是class的内容。
粉色:class的内容
于是,这样一个class就声明好了。
> 调用方法
在class内,我们用$this来代表class本身,所以:
- class内定义变量(非函数内定义)的调用方法为:$this->变量
- class内定义函数的调用方法为:$this->函数名字(参数)
但是函数内定义变量调用方法仍为$变量。看下面:
代码:
- class a{
- public $a = "a",$b = "This is b";
- public function get($isb){
- if($isb){
- return $this->b;
- }else{
- return $this->a;
- }
- }
- }
> 跨class调用方法
我们在玩PHP的时候可能会用到调用另外一个class的变量或者函数,这时候我们需要这样做:
- 另外一个class的名字::变量
- 另外一个class的名字::函数(参数)
请看下面的例子:
代码:
- class a{
- public $a = "a",$b = "This is b";
- public function get($isb){
- if($isb){
- return $this->b;
- }else{
- return $this->a;
- }
- }
- }
- class b{
- public function init(){
- echo a::get(true);
- }
- }
懂了吗?{:10_505:}
> 使用范围
声明玩一个class后,一个问题出来了:class里面有些函数和变量仅适合class内部使用或者不希望公开,其它的一些希望公开,那该怎么办呢?我们可以使用public和private。
使用范围 |
说明 |
例子 |
public |
公用(class以外可以调用) |
public function init(){} |
private |
私有(仅class内可以使用) |
private $api; |

这里不同的function都用颜色标出来了,但是里面一些变量不希望外面调用,所以是private。
> class接口
【WARNING:前方高能,请无关人员迅速撤离!{:10_542:}】
什么是接口?接口允许你创建一类相似的class,以便调用。
class定义时接上这个接口,意味着需要含有接口规定的一切函数和变量。例如上面的Plugin就是一个接口,定义了一类相似的class。我们看这里:
内容引用自PocketMine Team的PocketMine-MP/src/PluginAPI:www.pocketmine.net

上面的例子规定了一个叫做Plugin的接口,然后创建了一个叫做DummyPlugin的类,这个DummyPlugin就是一个标准的Plugin,拥有接口规定的所有函数(含参数)和变量。如果缺少任何一个,就不是这个接口对应的class。
现在懂了吗?
第八讲完
孩子,你看到这里了,说明你对于PHP玩的差不多了,为制作一个PM插件已经打好了基础,往下看吧。
【最后,再想着做插件】
大家上面看完了吗?(众:看~完~了~)
那好,我们就开始做插件吧。
接下来,我们以SignTp插件作为目标,一步一步完成。
我们的插件要可以:
> 扔一个牌子就能传送到目的地!
> 有自动更新功能!
所以它需要:
> 有一堆命令
> 检测一堆事件
> 读取一堆配置文件
> 等等......
这看起来似乎很难的样子,让我们一步一步制作完毕。
0.一些准备
文本部分来自 http://www.mcbbs.net/thread-204040-1-1.html ,原帖为JS,其实PHP和JS编辑器是基本一样的。
> 首先你需要装了PM服务端的电脑一台,用作开服务器(技术宅可以用安卓手机,详情右转【此处】)
> 然后你需要文本编辑器一只,这个种类繁多,下面我来推荐几个:
系统 |
软件 |
windows |
notepad++,ultraedit(用Notepad的请受小神一拜) |
linux |
gvim |
android |
920文本编辑器,rootexplorer自带的文本编辑器 |
iOS |
这个真没有= = |
1.你的第一个PM插件
> 无中生有的第一步
> 首先,你需要打开你的服务端然后关闭,我们会发现多了一些文件夹,我们的插件就要放在/plugins里面。

> 然后,我们在/plugins里面创建一个php文件,名字可以最好能表现插件的名字等等。
这里我们以SignTp为例子,创建一个SignTp.php

> 在编辑器里打开,没错,空的。
还记得上面PHP教程怎么说的?(众:php文件一定要以"<?php"开头)好的,我们加上。
> 作为一个PM的插件,我们需要用Plugin这个接口。看这儿:内容引用自PocketMine Team的PocketMine-MP/src/PluginAPI:www.pocketmine.net

这个接口说明了一个Plugin必备的三个函数,所以一般的PM插件格式是这样的:
内容引用自Snake1999 的 SignTp:http://www.mcbbs.net/thread-226762-1-1.html

天蓝:PM插件必备的注释部分。请看这里:
/*
__PocketMine Plugin__
name=PluginXXX <<插件名字,会在控制台插件加载时显示
description= <<插件说明,貌似没用
version=0.0.1 <<插件版本,会在控制台插件加载时显示
author=XXX <<插件作者,会在控制台插件加载时显示,也能说明版权
class=PluginXXX <<插件主类名字,和下面的class PluginXXX ....名字应该一样
apiversion=11 <<插件兼容API版本,用逗号隔开(以后会讲)
*/
紫红:插件的主类。里面塞着插件大部分的内容。
深蓝:预处理插件时触发的function。这里需要定义api这个变量作为插件与服务器沟通的桥梁。
绿色:卸载时触发的function。<<Tip:这里的卸载是加载的反义词,不是删除!!
红色:插件加载时促发的function。
所以,一个空的插件应该是这样的:
代码:
- <?php
-
- /*
- __PocketMine Plugin__
- name=PluginXXX
- description=
- version=0.0.1
- author=XXX
- class=PluginXXX
- apiversion=11
- */
-
- class PluginXXX implements Plugin{
- private $api;
- public function __construct(ServerAPI $api, $server = false){
- $this->api = $api;
- }
- public function __destruct(){}
- public function init(){}
- }

没错,你的插件被加载了!{:10_509:} 虽然没什么用。{:10_494:}
赶紧放到SignTp里面,于是我们的代码是这样的:
代码:
- <?php
-
- /*
- __PocketMine Plugin__
- name=SignTp
- description=
- version=0.0.1
- author=DreamWork Studio
- class=SignTp
- apiversion=11
- */
-
- class SignTp implements Plugin{
- private $api;
- public function __construct(ServerAPI $api, $server = false){
- $this->api = $api;
- }
- public function __destruct(){}
- public function init(){}
- }
2.给你的插件添加命令
> 键盘敲一敲,服务器嗨起来
> 命令的用法命令能干啥?很多插件都需要命令。命令允许玩家在游戏中玩转插件,那么该怎么添加命令呢?
我们先看这里:
内容引用自kv516 的 PocketEssentials:http://www.mcbbs.net/thread-196684-1-1.html

红色:从api提供的方法注册一个命令
蓝色:命令的名字
粉色:命令在 " /help 名字 " 里面显示出的帮助文字
青色:激活命令后触发的function所在的类,一般用$this
棕色:激活命令后触发的function名字,下面要相同
那么如果我们需要让命令实现同样的功能,或者能让一般玩家可以用,该怎么办呢?
我们先看这里:
内容引用自ljyloo 的 TpMultiWorld:http://www.mcbbs.net/thread-148950-1-2.html

红2:注册一个相同的命令,即/w 和/tpw 有相同的作用,在下面command只需要规定/tpw即可。
粉2:要注册相同指令的目标指令,即未规定但要与元指令相同指令。
绿2:要注册相同指令的原指令,即规定要与目标指令相同的指令。
蓝2:注册一个一般玩家可以能用的指令
黑2:要注册一般玩家可以能用的指令命令的名字
于是,我们注册了一个命令,接下来要定义它的作用。我们继续看上面的图:
红1:要和注册指令右边的红圈相同,是激活命令后触发的function名字。
黑1:$cmd : 激活的命令名称,比如"tpw" "listw"等
蓝1:$params : 激活的子命令的名称
紫1:$issuer : 该玩家的Player对象
绿1:$alias : 这个命令的相同的指令,如"tpw" 的alias 是"w",多个就是数组
其实这里$cmd等等名字改掉是可以的,但是$cmd这几个大家都习惯了,所以建议保留,详细看下面。
请看这里的例子:
如果一个玩家输入了/tpw 123 456 789
那么返回的$cmd = "tpw"
$params[0] = "123"
$params[1] = "456"
$params[2] = "789"
$issuer = 该玩家的Player对象(以后会讲)
$alias = "w"
然后,加上一个switch,就可以让命令有作用喽~
就像这样:
内容引用自MinecrafterJPN 的 PocketMoney:http://forums.pocketmine.net/plugins/pocketmoney.63/

就这样搜寻以后/money指令就起作用了,赶紧拿来试试!
代码:
- <?php
-
- /*
- __PocketMine Plugin__
- name=SignTp
- description=
- version=0.0.1
- author=DreamWork Studio
- class=SignTp
- apiversion=11
- */
-
- class SignTp implements Plugin{
- private $api;
- public function __construct(ServerAPI $api, $server = false){
- $this->api = $api;
- }
- public function __destruct(){}
- public function init(){
- $this->api->console->register("st", " : SignTp command.", array($this, "command"));
- }
- public function command($cmd, $params, $issuer, $alias){
- switch($cmd){
- case "st":
- console("123");
- break;
- }
- }
- }

在粉色部分,我们看到我们的插件被加载了,输入/st以后,console返回了123;在/? st里面也有了相应的解释。说明我们的命令起作用喽~
在命令执行的部分,我们可以使用return来返回一个值让使用者知道,所以上面代码可以改为:
代码:
- <?php
-
- /*
- __PocketMine Plugin__
- name=SignTp
- description=
- version=0.0.1
- author=DreamWork Studio
- class=SignTp
- apiversion=11
- */
-
- class SignTp implements Plugin{
- private $api;
- public function __construct(ServerAPI $api, $server = false){
- $this->api = $api;
- }
- public function __destruct(){}
- public function init(){
- $this->api->console->register("st", " : SignTp command.", array($this, "command"));
- }
- public function command($cmd, $params, $issuer, $alias){
- switch($cmd){
- case "st":
- return "123";
- break;
- }
- }
- }
> 添加功能
我们玩过的插件命令功能绝没有输出123那么简单,这时候我们就需要发挥想象力,参考下面的附录可以看你能干啥,然后搭配好代码,就能让你的命令多姿多彩。
第二讲完
================== 坑 线 =================
3.为你的插件检测事件
> 石头:现在你还你敢敲我?
第三讲完
【附录】
1.PM常见命令
> console
console命令用于在控制台输出一条带现在时间的信息。
用法:console($message, $EOL = true, $log = true, $level = 1)
$message:信息的文本。
$EOL:决定是否在信息末尾加上PHP_EOL(换行)。默认true为加上。
$log:决定是否记录在console.log内。默认true。
$level:这个我也不知道= =谁来告诉我
- $message含下面的内容将会设置输出文字的颜色,下面是常用的颜色:
内容 |
颜色 |
FORMAT_AQUA |
浅绿色 |
FORMAT_RED |
红色 |
FORMAT_GRAY |
灰色 |
FORMAT_YELLOW |
黄色 |
FORMAT_RESET |
黑色 |
添加颜色的方法:把内容用 . 连接到字符串里,如:
代码:
- console(FORMAT_RED . "RED" . FORMAT_RESET . "BLACK");
> API11的常见命令就这么一个= =待添加第一讲完
2.PM数据类型
> Vector3
在PM插件制作时,很多时候会用到三轴坐标,于是Vector3就诞生了。{:10_525:}
- 定义方法
代码:
- $变量名字 = new Vector3(x,y,z);
这里new这个单词能告诉PHP要创建一个新Vector3类型的变量;xyz参数告诉PHP这个三轴坐标的位置。
- Vector3类型的常用方法
假如$var(1.4, -2, 3.6)是一个vector3对象,你可以......
使用方法 |
返回 |
作用 |
例子 |
返回值 |
$var |
string |
得到$var的三轴坐标 |
$var |
"Vector3(x=1.4,y=2,z=3.6)" |
$var->getX() $var->getRight() $var->getSouth() |
variant |
得到$var的x轴坐标 |
$var->getX() |
1.4 |
$var->getY() $var->getUp() |
variant |
得到$var的y轴坐标 |
$var->getY() |
-2 |
$var->getZ() $var->getForward() $var->getWest() |
variant |
得到$var的z轴坐标 |
$var->getZ() |
3.6 |
$var->getFloorX() |
integer |
得到$var的x轴坐标并取整 |
$var->getFloorX() |
1 |
$var->getFloorY() |
integer |
得到$var的y轴坐标并取整 |
$var->getFloorY() |
-2 |
$var->getFloorZ() |
integer |
得到$var的z轴坐标并取整 |
$var->getFloorZ() |
3 |
$var->add ($x, $y, $z) |
Vector3 |
将$var的三轴坐标加上对应值后返回 |
$var->add(1, -2, 3) |
Vector3(2.4, -4, 6.6) |
$var->add (Vector3 $x) |
Vector3 |
将$var的三轴坐标加上$x的对应值后返回 |
$var2 = new Vector3(1, -2, 3); $var->add($var2) |
Vector3(2.4, -4, 6.6) |
$var->subtract ($x, $y, $z) |
Vector3 |
将$var的三轴坐标减去对应值后返回 |
$var->subtract(-1, 2,- 3) |
Vector3(2.4, -4, 6.6) |
$var->subtract (Vector3 $x) |
Vector3 |
将$var的三轴坐标减去$x的对应值后返回 |
$var2 = new Vector3(-1, 2, -3); $var->add($var2) |
Vector3(2.4, -4, 6.6) |
$var->multiply ($number) |
Vector3 |
将$var的三轴坐标都乘$number并返回 |
$var->multiply(2) |
Vector3(2.8, -4, 7.2) |
$var->divide($number) |
Vector3 |
将$var的三轴坐标都除以$number并返回 |
$var->divide(2) |
Vector3(0.7, -1, 1.8) |
$var->celi() |
Vector3 |
将$var的三轴坐标都+1且取整后返回 |
$var->celi() |
Vector3(2, -1, 4) |
$var->floor() |
Vector3 |
将$var的三轴坐标取整后返回 |
$var->floor() |
Vector3(1, -2, 3) |
$var->round() |
Vector3 |
将$var的三轴坐标四舍五入后返回 |
$var->round() |
Vector3(1, -2, 4) |
$var->abs() |
Vector3 |
将$var的三轴坐标取绝对值后返回 |
$var->abs() |
Vector3(1.4, 2, 3.6) |
$var->getSide($side) |
Vector3 |
得到与$var相邻的一个坐标 * |
$var->getSide(0) |
Vector3(1.4, -3, 3.6) |
$var-> distance ($x=0,$y=0,$z=0) |
double |
得到$var与Vector3($x,$y,$z)的距离 |
$var->distance(0, 2, 3) |
4.2801869118065 |
$var-> distance (Vecrot3 $x) |
double |
得到$var与$x的距离 |
$var2 = new Vector3(0, 2, 3); $var->distance($var2) |
4.2801869118065 |
$var-> distanceSquared ($x=0,$y=0,$z=0) |
double |
得到$var与Vector3($x,$y,$z) 的距离的平方 |
$var->distanceSquared (0, 2, 3) |
18.32 |
$var-> distanceSquared (Vecrot3 $x) |
double |
得到$var与$x的距离的平方 |
$var2 = new Vector3(0, 2, 3); $var->distanceSquared($var2) |
18.32 |
$var->dot (Vecrot3 $x) |
double |
得到$var与$x点乘的结果 点乘是什么?【左转这里】 |
$var2 = new Vector3(0, 2, 3); $var->dot($var2) |
6.8 |
$var->cross (Vecrot3 $x) |
Vector3 |
得到$var与$x叉乘的结果 叉乘又是啥?【右转这里】 |
$var2 = new Vector3(0, 2, 3); $var->cross($var2) |
Vector3(-13.2, -4.2, 2.8) |

那么:
$side值 |
表示XYZ坐标变化 |
相当于 |
0 |
x不变,y减一,z不变 |
下面 |
1 |
x不变,y加一,z不变 |
上面 |
2 |
x不变,y不变,z减一 |
后面 |
3 |
x不变,y不变,z加一 |
前面 |
4 |
x减一,y不变,z不变 |
左面 |
5 |
x加一,y不变,z不变 |
右面 |
第二讲完
3.PM对象
> 对象是什么
对象(object)是一种变量类型,允许你调用程序内部特定的内容。比如,一个世界就是一个level对象,你的插件可以通过更改level对象来改变世界的信息。
> Position对象
- 源文件位置(忘记指令之类的可以去翻源文件,接下来不再提示):/src/world/Position.php
- 特性
Position对象用于表达一个事物的坐标,包括xyz坐标和世界。
Position对象源文件的开头有这样一句话:
代码:
- class Position extends Vector3{
- 方法
如果$pos是一个Position对象,那么你除了可以用Vector3的方法,还可以——
方法 |
类型 |
作用 |
$pos |
string |
返回这个点的三轴坐标 "Position(level=xxx,x=x,y=y,z=z)" |
$pos->x $pos->y $pos->z |
variant |
返回这个点某个轴的坐标 |
$pos->level |
Level |
返回Position所在的世界 |
$pos->getSide($side) |
Position |
同Vector3的getSide |
$pos->distance(同Vector3) |
double |
同Vector3的distance |
> Level对象
- 源文件位置:/src/world/Level.php
- 方法
如果$lev是一个level对象,那么你可以——
======================== 坑线 ==========================
第三讲完
======================== 坑线 ==========================
4.PM API解析【已更API11】
第四讲完
本帖最后由 Snake1999 于 2014-1-30 10:38 编辑
本楼备用!!
本楼备用!!
不是金锭我不收
大哥说了多少遍了=。=能都发一楼么
话说我怎么感觉发错地方了=。=
.
有更新了啊=。=
在【其次,你得会玩PHP】里面有及部分引用PM内部代码的部分路径不对,如PocketMine-MP/src/ConsoleAPI这个应该是PocketMine-MP/src/API/ConsoleAPI.php,希望能改正一下
好,涨姿势了{:10_505:}
怎么监视文件...
还有,php怎么读取txt内容。。
还有,php怎么读取txt内容。。
uuuu1 发表于 2014-2-7 14:31
怎么监视文件...
还有,php怎么读取txt内容。。
这个你去看W3SCHOOL的教程,我这里限于篇幅不多讲
赞
那啥。。为什么我在上面写了中文回复是乱码?
lz你好牛!智商好高!赞一个!然后·······我的脑子炸了(我一小学生懂个毛函数啊啊······)
二菌快更啊= =还有我编写了一端插件,档读取木牌文本的时候pm的使用内存暴增,然后崩溃了。。。肿么破
楼主好人 我要开始学习了
哎呀受教了,嘿嘿,顶起→_→
太吊了,我还以为和PC的bukkit插件差不多,看了别人的源码-_-||
PHP有点像C语言和Java。。。
话说,我怎么越到后面越听不懂
楼主加qq1766355378 我需要您的帮助 多少钱都可以接受的, 我最近开服
楼主在? 给你钱来我的服务器定制插件吧。都是同类人 我只不过是pc的1.7.9API弄罢了被pm限制了 求楼主加qq1766355378
毛线,e才简单QwQ
这。。。。。。看完我还是不会啊
路过帮顶
教程完全比java还难
可以的~!支持一下楼主 楼主加油好好干=-=
火起来~~~
火起来~~~
顶顶顶顶顶顶顶顶顶顶顶顶顶顶
蟹蟹楼主!!
谢谢楼主分享,教程很棒很有用