PHPackages                             valres/pmtoolbox - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. valres/pmtoolbox

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

valres/pmtoolbox
================

Best utilities libs for PocketMine-MP plugins.

0.1.0(1mo ago)468↓87.5%1MITPHPPHP &gt;=8.1

Since Jun 8Pushed 2w agoCompare

[ Source](https://github.com/Root-Productions/PM-Toolbox)[ Packagist](https://packagist.org/packages/valres/pmtoolbox)[ RSS](/packages/valres-pmtoolbox/feed)WikiDiscussions main Synced 1w ago

READMEChangelogDependencies (2)Versions (5)Used By (0)

PMToolBox
=========

[](#pmtoolbox)

PMToolBox is a small PocketMine-MP toolbox library. It provides utilities for manager-based plugin structure, task helpers and an optional RCON interface.

Setup
-----

[](#setup)

Register the toolbox from your plugin lifecycle:

```
use pocketmine\plugin\PluginBase;
use valres\toolbox\ToolboxLoader;

final class Main extends PluginBase {
    protected function onLoad(): void {
        ToolboxLoader::load($this);
    }

    protected function onEnable(): void {
        ToolboxLoader::enable($this);
    }

    protected function onDisable(): void {
        ToolboxLoader::disable();
    }
}
```

By default, managers are loaded from the `manager` directory under your plugin namespace.

If your managers are elsewhere:

```
ToolboxLoader::load($this, "modules");
ToolboxLoader::enable($this);
```

If you do not want to use the manager system:

```
ToolboxLoader::load($this, loadManagers: false);
ToolboxLoader::enable($this, enableManagers: false);
```

Managers
--------

[](#managers)

Create managers by extending `BaseManager`.

```
namespace myplugin\manager;

use valres\toolbox\manager\BaseManager;
use valres\toolbox\manager\attribute\Manager;
use valres\toolbox\manager\attribute\ManagerPriority;
use valres\toolbox\manager\attribute\ManagerPriorityEnum;

#[Manager(name: "Economy", version: "1.0.0")]
#[ManagerPriority(ManagerPriorityEnum::PRIORITY_HIGH)]
final class EconomyManager extends BaseManager {
    public function onLoad(): void {
        // Light startup work.
    }

    public function init(): void {
        // Enable-time setup.
    }

    public function save(): void {
        // Persist data before shutdown.
    }
}
```

Dependencies
------------

[](#dependencies)

Use `ManagerDependsOn` when a manager must be initialized after another one.

```
use valres\toolbox\manager\attribute\ManagerDependsOn;

#[ManagerDependsOn(["Economy"])]
final class ShopManager extends BaseManager {
    // ...
}
```

The resolver detects duplicate manager names, missing dependencies and circular dependencies.

Auto Register
-------------

[](#auto-register)

Managers can auto-register commands and listeners from folders next to the manager class.

```
use valres\toolbox\manager\attribute\AutoRegister;
use valres\toolbox\manager\attribute\AutoRegisterAll;
use valres\toolbox\manager\attribute\AutoRegisterType;

#[AutoRegister(AutoRegisterType::COMMANDS)]
#[AutoRegister(AutoRegisterType::LISTENERS)]
final class GameplayManager extends BaseManager {
    // ...
}

#[AutoRegisterAll]
final class ProfileManager extends BaseManager {
    // Registers command/ and listener/.
}
```

Expected folder layout:

```
src/myplugin/manager/ProfileManager.php
src/myplugin/manager/command/ProfileCommand.php
src/myplugin/manager/listener/ProfileListener.php

```

Access
------

[](#access)

```
$economy = ToolboxLoader::getManager("Economy");
$shop = ToolboxLoader::getManagerOf(ShopManager::class);

if (ToolboxLoader::hasManager("Economy")) {
    // ...
}
```

You can also access the handler directly:

```
$handler = ToolboxLoader::getManagerHandler();
```

Each manager also behaves like a singleton automatically. You do not need to add a trait in your manager class:

```
$economy = EconomyManager::getInstance();

if (EconomyManager::hasInstance()) {
    EconomyManager::getInstance()->save();
}
```

The singleton instance is registered when the manager is discovered and reset when managers are disabled.

RCON
----

[](#rcon)

RCON is optional and can be started during enable:

```
use valres\toolbox\rcon\RconSettings;

ToolboxLoader::enable($this, new RconSettings(
    address: "0.0.0.0",
    port: 19132,
    password: "secret"
));
```

Or with the helper:

```
ToolboxLoader::enable($this, RconSettings::default("secret", 19132));
```

Camera
------

[](#camera)

Register the camera helper once during enable. PMToolBox will send the vanilla camera presets when a player finishes initializing.

```
use valres\toolbox\camera\Camera;

protected function onEnable(): void {
    if (!Camera::isRegistered()) {
        Camera::register($this);
    }
}
```

Then build and send camera instructions fluently:

```
use pocketmine\math\Vector3;
use pocketmine\network\mcpe\protocol\types\camera\CameraSetInstructionEaseType;
use valres\toolbox\camera\Camera;
use valres\toolbox\camera\CameraPresets;

Camera::set(CameraPresets::free())
    ->ease(1.0, CameraSetInstructionEaseType::OUT_CUBIC)
    ->position(new Vector3(100, 80, 100))
    ->facing($player->getPosition())
    ->send($player);

Camera::fade()
    ->time(0.5, 1.0, 0.5)
    ->rgb(0, 0, 0)
    ->send($player);

Camera::clear()->send($player);
```

Sequences are useful when a plugin wants to group multiple instructions:

```
Camera::sequence()
    ->add(Camera::shake(0.35, 0.75)->rotational())
    ->add(Camera::fov(65)->ease(0.4))
    ->send($player);
```

Data-Driven UI
--------------

[](#data-driven-ui)

PMToolBox includes an experimental DDUI helper inspired by Minecraft Bedrock's Data-Driven UI model and `Joshet18/Data-DrivenUI`. It is registered automatically by `ToolboxLoader::enable()`.

```
use valres\toolbox\form\ddui\DduiManager;
use valres\toolbox\form\ddui\DduiObservable;

$status = DduiObservable::string("Ready");
$enabled = DduiObservable::bool(true, clientWritable: true);

DduiManager::customForm("Settings")
    ->label($status)
    ->toggle("Enabled", $enabled)
    ->button("Refresh", function() use ($status): void {
        $status->set("Updated at " . date("H:i:s"));
    }, closeOnClick: false)
    ->send($player);
```

For simple dialogs:

```
DduiManager::messageBox("Confirm", "Delete this item?")
    ->button1("Delete")
    ->button2("Cancel")
    ->onSelect(function($player, int $selection): void {
        if ($selection === 1) {
            // Delete item.
        }
    })
    ->send($player);
```

Supported `DduiCustomForm` controls are labels, spacers, dividers, text fields, toggles, dropdowns, sliders and buttons. `DduiObservable` values can be updated server-side while the screen is open; client-writable observables are updated when the player changes the matching control.

Packets
-------

[](#packets)

PMToolBox includes a small packet API inspired by LibPacket/SimplePacketHandler: register handlers for specific packet classes instead of writing long `instanceof` chains.

### Monitor

[](#monitor)

Use a monitor when you only want to observe packets. Return values are ignored.

```
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\LoginPacket;
use valres\toolbox\ToolboxLoader;

$monitor = ToolboxLoader::createPacketMonitor();

$monitor->monitorIncoming(function(LoginPacket $packet, NetworkSession $session): void {
    // Debug or inspect the packet.
});
```

### Interceptor

[](#interceptor)

Use an interceptor when you want to cancel or modify packets before normal handling. Return `false` to cancel the packet event.

```
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\AdventureSettingsPacket;
use valres\toolbox\ToolboxLoader;

$interceptor = ToolboxLoader::createPacketInterceptor();

$interceptor->interceptIncoming(function(AdventureSettingsPacket $packet, NetworkSession $session): bool {
    return true; // false cancels the DataPacketReceiveEvent.
});
```

### Handler Classes

[](#handler-classes)

```
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\LoginPacket;
use pocketmine\network\mcpe\protocol\Packet;
use valres\toolbox\packet\PacketHandlerInterface;

final class LoginPacketHandler implements PacketHandlerInterface {
    public function getPacketIds(): array {
        return [LoginPacket::class];
    }

    public function handle(Packet $packet, NetworkSession $session): bool {
        return true;
    }
}

ToolboxLoader::createPacketInterceptor()->registerIncoming(new LoginPacketHandler());
```

### Attributes

[](#attributes)

You can also register public methods with attributes.

```
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\LoginPacket;
use valres\toolbox\packet\attribute\IncomingPacket;
use valres\toolbox\packet\attribute\OutgoingPacket;
use valres\toolbox\packet\attribute\PacketHandler;
use valres\toolbox\packet\PacketDirection;

final class PacketHandlers {
    #[IncomingPacket(LoginPacket::class)]
    public function onLogin(LoginPacket $packet, NetworkSession $session): bool {
        return true;
    }

    #[OutgoingPacket]
    public function onAnyOutgoing(LoginPacket $packet, NetworkSession $session): void {
    }

    #[PacketHandler(PacketDirection::INCOMING, LoginPacket::class)]
    public function onLoginWithGenericAttribute(LoginPacket $packet, NetworkSession $session): bool {
        return true;
    }
}

ToolboxLoader::createPacketInterceptor()->registerAnnotated(new PacketHandlers());
```

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance94

Actively maintained with recent releases

Popularity15

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

4

Last Release

43d ago

PHP version history (2 changes)v1.0.0PHP &gt;=8.4

v1.0.1PHP &gt;=8.1

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/7081098?v=4)[Valerie Respaut](/maintainers/Valres)[@ValRes](https://github.com/ValRes)

---

Top Contributors

[![ValresMC](https://avatars.githubusercontent.com/u/104681026?v=4)](https://github.com/ValresMC "ValresMC (102 commits)")

### Embed Badge

![Health badge](/badges/valres-pmtoolbox/health.svg)

```
[![Health](https://phpackages.com/badges/valres-pmtoolbox/health.svg)](https://phpackages.com/packages/valres-pmtoolbox)
```

###  Alternatives

[facuz/laravel-themes

Theme will help you organize your themes inside Laravel projects easily and maintain its related assets, layouts and partials for the theme in single directory. (Based on teepluss/theme)

13744.0k2](/packages/facuz-laravel-themes)[ackintosh/snidel

A multi-process container. It looks like multi-thread-ish.

1051.2k](/packages/ackintosh-snidel)[infocyph/intermix

A lightweight PHP DI container, invoker, serializer, and utility toolkit.

137.7k3](/packages/infocyph-intermix)[heptacom/heptaconnect-portal-base

HEPTAconnect base dataset that every other portal is based on

1025.3k18](/packages/heptacom-heptaconnect-portal-base)[codespede/simple-multi-threader

122.6k](/packages/codespede-simple-multi-threader)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
