Vol2 - PEMapModder/PocketMine-Plugin-Tutorials GitHub Wiki

Volume 2

This is a place for public contribution. Everyone can edit this wiki, but please keep in mind while editing that the wiki should be purely informative and neutral.

Introduction

Before we go on, I would like to ask a question.

What can a plugin do? What is it for?

This is a tricky question. Everyone knows that plugins add things to PocketMine, but few can classify their main uses. Plugins can basically do anything, but three main components are commands, event handling and scheduled tasks. We are going to discuss about them one by one in this volume.

Registering commands

We are going to register a command called /greet.

It is very easy to register a command. You don't even need to write PHP code. Remember our old plugin.yml? Time to open it again. The last time we saved it, it should be like this:

name: MyPlugin
version: 1.0.0
author: YourName
api: 1.12.0
main: yourname\myplugin\MyPlugin

The next part is going to be about commands, so add a new line commands:

name: MyPlugin
version: 1.0.0
author: YourName
api: 1.12.0
main: yourname\myplugin\MyPlugin
commands:

To add a command, write down its name greet, description (as shown in /help) Send back a message and usage message /greet <usage here>:

name: MyPlugin
version: 1.0.0
author: YourName
api: 1.12.0
main: yourname\myplugin\MyPlugin
commands:
  greet:
    description: Send back a message
    usage: /greet <usage here>

It is pretty straightforward. You would understand what this thing means even if I didn't teach you.

You can add multiple commands:

name: MyPlugin
version: 1.0.0
author: YourName
api: 1.12.0
main: yourname\myplugin\MyPlugin
commands:
  greet:
    description: Send back a message
    usage: /greet <usage here>
  another-command:
    description: This is another command
    usage: /another-command <argument> <another argument>

Hmm, typing /greet every time seems to be too troublesome. What about adding aliases? In this way, typing /hey or /hi would be converted into /greet automatically.

name: MyPlugin
version: 1.0.0
author: YourName
api: 1.12.0
main: yourname\myplugin\MyPlugin
commands:
  hi:
    description: Send back a message
    usage: /greet <usage here>
    aliases: [hey, hi]
  another-command:
    description: This is another command
    usage: /another-command <argument> <another argument>

Note that it must be called aliases not alias. Use a pair of square braces ([]) to contain the aliases, and separate the aliases by commas (,).

Note: commands must not contain colons (:) or spaces. This is because colons are used to specify the owner of a command (you don't need to care about this as it rarely happens), and spaces are used to separate the command name and the arguments behind it.

Anyway, we have registered the command, but we haven't yet added the function to handle the command. Now, we are heading to our first PHP function. We are going to write real code, where we are seeing infinite possibilities.

Handling commands

We handle commands in a function in your main class called onCommand.

Before doing anything else, again, look at this code and copy it into your main class's class body, i.e. between the class ... PluginBase{ line and the } line.

  public function onCommand(CommandSender $sender, Command $command, $label, array $args) : bool{
    $commandName = $command->getName();
    if($commandName === "greet"){
      $sender->sendMessage("Hi!");
      return true;
    }
    return false;
  }

Also, in the use statements at the beginning, use the following classes:

use pocketmine\command\Command;
use pocketmine\command\ComamndSender;

Don't read below yet. Read the code above. How much do you understand?

Now let's see if you are correct.

Functions

Functions originate from mathematics. A common notation for a mathematical function is f(x). For example, f(x) = 3x + 2, which means that writing f(x) is equivalent to writing 3x + 2, and writing f(12) is equivalent to 3 * 12 + 2, which is 38.

In PHP, we write f(x) = 3x + 2 like this:

function f($x){
  return 3 * $x + 2;
}
  • On the first line, function means you are defining a function.
  • The next word, f, is the function name.
  • The things inside the parentheses () are known as parameters or arguments. $x is an example of a parameter. All parameters must start with $, followed by a parameter name. The rules for a parameter name is same as that of a class name (A-Z a-z 0-9 _), except that the convention for variables is to start with a lowercase word (like thisIsName instead of ThisIsName). $x represents the value passed in. For example, if someone uses f(12), $x will represent the 12.
  • If there is more than one parameter, separate them with commas ,.
  • The content between the { and the } is called the function body. When someone uses the function, the code inside the function body is run.

The two spaces before return is just for visual effect. Unless the spaces are in quotes "", PHP only cares whether the spaces separate two alphabetical/number/underscore characters (e.g. the spaces in public function onCommand are important, but other spaces are ignored, and how many spaces between public and function is not important)

In this function, the function body is return 3 * $x + 2;. return means that the expression between return and ; will be set as the function's result, a.k.a. function return value in PHP. In this case, the function's return value is 3 * $x + 2. If $x represents 12, the function's return value will become 3 * 12 + 2, and hence the return value is 38.

The return line is known as the return statement. As you can guess, there are other types of statements apart from a return statement.

Actually, a function body can contain a theoretically infinite number of statements. Each statement is delimited (i.e. marked as ended) by a semicolon ;. Basically, a statement executes an operation. For a return statement, it sets the function's return value to something and stops the function from executing (i.e. the code after the return statement will not be executed).

When a function executes, it executes the statements from the first one to the last one. This seems obvious, right? But it is very important. It is just like remembering the obvious rule x = 1 * x in mathematics helps people solve x + x = 1 * x + 1 * x = (1 + 1) * x = 2 * x. It is the basic principle of many tricks in programming.

There is one special thing about parameters to note. I mentioned that there can be as many parameters as possible. I also mentioned that a parameter can have any names. Say, if you define a function function pyth($a, $b){ something here; }, and someone calls pyth(3, 4), how would you know which, between 3 and 4, is $a, and which is $b? The answer is, the order. If the first parameter defined is $a and the first parameter given is 3, 3 will become $a.

More about variables

Actually, a parameter (e.g. $x in the above example) is a special kind of variables. A variable is something like $varName, where $ identifies that it is a variable and varName is the name for your variable.

A variable can actually represent/hold/store many things (or basically anything that is a thing 😜). In the above example, $x is expected to store an int (integer) like 12. Here, int is the type of the value 12. There are several common types:

  • string (a sequence of characters, also commonly known as a "text")
  • int (an integer number, positive or negative)
  • float/double (a floating point number, i.e. a decimal number (e.g. 3.14) or a very big number that is represented exponentially (e.g. 3e+11)
  • boolean (true or false)
  • array (a list of values, indexed using ints or strings)
  • null (this is a special type that means nothing, often returned by functions that have nothing to return)
  • resource (special system things like internet sockets, which you can simply ignore them because we rarely come across with them, much less to remember that it is a resource)
  • object (objects are similar to arrays, which can store a structure of values inside themselves; objects are often used to represent abstract things that cannot be represented by other types, like a Player who connects to a server, or a Command used by a player that is something more than a name)

You don't need to understand all of the above. You just need to remember:

  • a string is a text
  • an int or float is a number
  • a boolean is true or false
  • an array is a group or structure of values (I will explain how to get the array values later)
  • an object is a structure of values (defining non-parameter objects are more advanced, so I will not explain so soon)
  • null means that the variable holds nothing, but the variable is still "defined" (this is as important as having a zero digit at the end of 10, because if you don't define a variable as null, PHP will think something is missing and you will find errors under your bed)

The syntax (format) to define a command:

$varName = expression;

Replace expression with an expression of the value you want to set to. For example, to express a string abc is "abc". To express a boolean false is false. To express a null value is null. You can also express the value of a variable $var1 as $var1. Therefore, this is how you define a variable called $var2 that holds the same value as $var1:

$var2 = $var1;

Small quiz

We have two variables, $a and $b. Write a few statements that swap the values between $a and $b.

Solution:
$c = $a;
$a = $b;
$b = $c;

Explanation:

The difficult part in the question is that when you set the value of $a into the value of $b, the value of $a is overwritten and doing $b = $a; afterwards will just set $b to the new value of $a, which is just the value of $b.

To solve this problem, we first store the value of $a in a new variable called $c, as is the first line. Then we can set $a's value into $b. Now you can set the value of $b into the old value of $a using the stored value in $c.

This is tricky. If you have any questions, don't hesitate to ask a human on the IRC channel in the link in Volume 1.

Back to our command

Let's look at the code for the command again:

  public function onCommand(CommandSender $sender, Command $command, $label, array $args) : bool{
    $commandName = $command->getName();
    if($commandName === "greet"){
      $sender->sendMessage("Hi!");
      return true;
    }
    return false;
  }

😮 😕 Hmm, there is something new that we don't know. Obviously there are many new things inside the method body, but wait, did you notice something weird in the function parameters?

Remember the correct syntax for parameters? It should be like ($sender, $command, $label, $args). So you would ask, what are those words before the parameter names, like CommandSender, Command and array?

array is the hint. Remember what array is? It is a type of variables/parameters. array $args means that $args must be an array when someone calls the onCommand function. If the person (it is PocketMine in this case) who calls the function doesn't give an array for the fourth parameter, red errors will pop out from your console.

Therefore, the word before the parameter name is the type of the parameter (known as type hint technically). However, currently, only array and object are allowed for type hints.

So you would be wondering: CommandSender and Command are not types that are mentioned. I haven't even mentioned it anywhere. Where are they from?

This refers back to our definition of objects. Every object is "an instance of a class". A class is like a sub-type. There are different types of variables, and some are objects. And there are different types of objects, and a class is a type of object. (In the future, you will learn that variables that are "instance of a class" can be "instance of different subclasses") Classes are complicated. At the moment, you just need to know that a class classifies objects into smaller types.

And so, the type name of $sender is CommandSender? No, you have fallen into this trap. 😈 Remember the use statements? use pocketmine\command\CommandSender;. The use statements define aliases for class names. Therefore, the type name of $sender is pocketmine\command\CommandSender.

The above explains the parameters. And in the next chapter, we are going to study the function body line by line, learning some of the secrets of the wondrous programming.

Investigating the gist of the API from source code

  public function onCommand(CommandSender $sender, Command $command, $label, array $args) : bool{
    $commandName = $command->getName();
    if($commandName === "greet"){
      $sender->sendMessage("Hi!");
      return true;
    }
    return false;
  }

You should be able to guess what the first line is. It is a variable assignment statement. It defines the variable $commandName, and gives it the value $command->getName(). Now the question is, what is meant by $command->getName()?

We have already mentioned that $command, in this function, is a Command object. Now, let's look at what we can do with a Command object. You can go to http://lgpe.co/psrc to see the PocketMine source.

We know that Command stands for pocketmine\command\Command. (Because of the use statement in the beginning, remember?) Therefore, we are going to look at the source code for pocketmine/command/Command.php.

The source file contains a lot of code that you don't understand. Actually, anything that has a private tag (modifier) is not part of the API, and you can simply ignore them. 😏 PocketMine offers most of the API in functions. Therefore, you can search the word public function from the source code using the search button in your browser (not the seasrch bar at the top of the page! You aren't searching the whole PocketMine source!).

If you are using Linux and you downloaded and extracted the source code, it is a good idea to run the command grep "public function" < Command.php.

Now we get these lines extracted:

public function __construct($name, $description = "", $usageMessage = null, array $aliases = []){
public function getName(){
public function getPermission(){
public function setPermission($permission){
public function testPermission(CommandSender $target){
public function testPermissionSilent(CommandSender $target){
public function getLabel(){
public function setLabel($name){
public function register(CommandMap $commandMap){
public function unregister(CommandMap $commandMap){
public function isRegistered(){
public function getAliases(){
public function getPermissionMessage(){
public function getDescription(){
public function getUsage(){
public function setAliases(array $aliases){
public function setDescription($description){
public function setPermissionMessage($permissionMessage){
public function setUsage($usage){
public function __toString(){

A note is that functions starting with __, like __construct and __toString, are special functions in PHP (a.k.a. magic functions). You won't want to use them directly. We'll look more about them later.

Now, guess what? Everything you see here are expected to be used by you! Though, some functions like register and unregister actually aren't what they sound to mean.

Functions starting with get are usually for getting a value about the object. As you can guess, getName() returns the name of the command, which is actually the name of the command (not the plugin!) you typed in plugin.yml.

If you want to use a function upon an object, as you already saw, it is $object->functionName($parameters). So, we have $command->getName(), which returns the command name. We store the value in a variable called $commandName.

Actually, if you find reading source code annoying, you can use the Doxygen-generated PocketMine docs. However, it has a disadvantage - you can't conveniently see the code in it. Hence, you may be unable to identify the functionality of a function directly. When you get more advanced, you get to understand what the code inside does. When that time comes, you are able to understand why PocketMine is doing that, hence how and when to use that.

unfinished page

⚠️ **GitHub.com Fallback** ⚠️