Writing plugins
A plugin is a class, a manifest and a folder. Start from there.
A plugin is a directory with a plugin.yml manifest and a src/ tree of PHP classes. The server
loads the main class, calls onEnable(), and from then on your code runs inside the server
process.
Layout
The manifest
name: Greeter
main: altay\greeter\Main
version: 1.0.0
api: [5.0.0]api is the API version your plugin targets. The server refuses to load a plugin that declares an
incompatible one, which is deliberate: loading it anyway would fail later, in the middle of a game,
with a worse error. Every field is listed in the
plugin.yml reference.
The main class
<?php
namespace altay\greeter;
use pocketmine\event\Listener;
use pocketmine\event\player\PlayerJoinEvent;
use pocketmine\plugin\PluginBase;
class Main extends PluginBase implements Listener{
protected function onEnable() : void{
$this->getServer()->getPluginManager()->registerEvents($this, $this);
}
public function onJoin(PlayerJoinEvent $event) : void{
$player = $event->getPlayer();
$player->sendMessage("Welcome back, " . $player->getName() . ".");
}
}Any public method that takes a single event parameter becomes a handler once the class is registered. Method names do not matter; the parameter type is what the server dispatches on. Priorities and cancellation are covered in Events.
Events
Events are the main extension point. Some are cancellable, and cancelling is how you stop the default behaviour rather than trying to undo it afterwards:
use pocketmine\event\block\BlockBreakEvent;
public function onBreak(BlockBreakEvent $event) : void{
if(!$event->getPlayer()->hasPermission("greeter.build")){
$event->cancel();
}
}The full event list lives in the API documentation under
pocketmine\event.
Commands
Declare the command in plugin.yml, then handle it:
commands:
greet:
description: Greets someone
permission: greeter.commanduse pocketmine\command\Command;
use pocketmine\command\CommandSender;
public function onCommand(CommandSender $sender, Command $command, string $label, array $args) : bool{
if($command->getName() === "greet"){
$sender->sendMessage("Hello.");
return true;
}
return false;
}Returning false makes the server print the command's usage message, so use it for bad arguments
instead of writing your own.
Developing without rebuilding
Install DevTools. With it loaded, the server reads plugins from
plain source folders in plugins/, so you edit a file and restart rather than packaging a phar
every time. When you are ready to ship, DevTools packages the folder for you.
Things that will bite you
The server is single threaded for game logic
A blocking HTTP request or a slow database query in an event handler freezes every player. Use the async task API for that work.
Do not hold player objects
A player who disconnects leaves you with a stale reference. Store names or UUIDs and look the player up when you need them.
Save on disable
onDisable() is your last chance to write state to disk.