aiptu / libplaceholder
A flexible placeholder library for PocketMine-MP plugins, allowing dynamic insertion of player and global data into messages.
Installs: 852
Dependents: 1
Suggesters: 0
Security: 0
Stars: 1
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/aiptu/libplaceholder
Requires
- php: ^8.3
- pocketmine/pocketmine-mp: ^5.0
This package is auto-updated.
Last update: 2025-11-30 10:13:24 UTC
README
A flexible placeholder library for PocketMine-MP plugins, allowing dynamic insertion of player and global data into messages.
β¨ Features
- π 3.75x Faster: Optimized regex caching, fast-path checks, and match expressions
- π Immutable Context: Thread-safe design prevents accidental state mutations
- π¨ Color Support: Automatic TextFormat colorization with opt-out
- π¦ Extensible: Register custom placeholder handlers with namespaced groups
- π‘οΈ Production-Ready: Input validation, exception handling, comprehensive tests
- β‘ Zero-Allocation Parsing: Minimal memory overhead per parse operation
π Performance
βββββββββββββββββββββββββ¬ββββββββββ¬ββββββββββ¬ββββββββββββββ
β Scenario β Before β After β Improvement β
βββββββββββββββββββββββββΌββββββββββΌββββββββββΌββββββββββββββ€
β Parse 10 placeholders β 45Β΅s β 12Β΅s β 3.75x β
β Parse plain text β 5Β΅s β 2Β΅s β 2.5x β
β Memory (1000 parses) β 2.4MB β 2.1MB β -12% β
βββββββββββββββββββββββββ΄ββββββββββ΄ββββββββββ΄ββββββββββββββ
π¦ Installation
Composer (Recommended)
composer require aiptu/libplaceholder
π Quick Start
Basic Usage
use aiptu\libplaceholder\PlaceholderManager; use aiptu\libplaceholder\PlaceholderContext; // Initialize once in onEnable() PlaceholderManager::getInstance()->init(); // Create context with player $context = new PlaceholderContext($player); // Parse message $message = "Hello {player:name}! Health: {player:health}/{player:max_health}"; $parsed = PlaceholderManager::getInstance()->parsePlaceholders($message, $context); // Result: "Hello Steve! Health: 18.50/20"
Custom Data Context
$context = new PlaceholderContext($player); $context = $context->withData('guild', 'Warriors') ->withData('rank', 'Leader') ->withData('coins', 1500); $message = "Welcome {player:name} of {guild}!{line}Rank: {rank}{line}Coins: {coins}"; $parsed = PlaceholderManager::getInstance()->parsePlaceholders($message, $context);
Performance Tip: Raw Parsing
// Skip TextFormat colorization for better performance $parsed = PlaceholderManager::getInstance()->parsePlaceholdersRaw($message, $context);
π§ Creating Custom Handlers
use aiptu\libplaceholder\PlaceholderHandler; use aiptu\libplaceholder\PlaceholderContext; final class EconomyPlaceholderHandler implements PlaceholderHandler { public function __construct( private EconomyAPI $economy ) {} public function handle(string $placeholder, PlaceholderContext $context, string ...$args): string { $player = $context->getPlayer(); if ($player === null) { return 'N/A'; } return match($placeholder) { 'money' => number_format($this->economy->myMoney($player), 2), 'currency' => $this->economy->getCurrencySymbol(), 'rank' => $this->economy->getRank($player), 'top' => $this->getTopPlayer((int) ($args[0] ?? 1)), default => '{' . $placeholder . '}' }; } private function getTopPlayer(int $position): string { // Your implementation return "Player#{$position}"; } } // Register the handler PlaceholderManager::getInstance()->registerHandler( 'economy', new EconomyPlaceholderHandler(EconomyAPI::getInstance()) ); // Usage $msg = "Balance: {economy:currency}{economy:money}{line}Top Player: {economy:top:1}";
π Placeholder Syntax
{group:placeholder:arg1,arg2|fallback}
Components:
group- Handler namespace (e.g.,player,economy)placeholder- Specific value identifier (e.g.,name,health)args- Comma-separated arguments (optional)fallback- Default value if resolution fails (optional)
Special Placeholders:
{line}- Inserts newline character (\n)
Examples:
"{player:name}" // Simple placeholder "{player:health:2}" // With precision argument "{economy:money|0.00}" // With fallback "{guild:name|No Guild}" // Fallback for missing data "{player:x}, {player:y}, {player:z}" // Multiple placeholders
π Built-in Player Placeholders
Basic Information
| Placeholder | Description | Example |
|---|---|---|
{player:name} |
Username | Steve |
{player:display_name} |
Display name with formatting | Β§aSteve |
{player:ip} |
IP address | 127.0.0.1 |
{player:port} |
Connection port | 19132 |
{player:ping} |
Network latency (ms) | 45 |
Health & Food
| Placeholder | Description | Example |
|---|---|---|
{player:health} |
Current health (2 decimals) | 18.50 |
{player:max_health} |
Maximum health | 20 |
{player:health_percentage} |
Health as percentage | 92.5 |
{player:food} |
Food level | 18 |
{player:max_food} |
Maximum food level | 20 |
{player:saturation} |
Saturation level | 5.60 |
Position & World
| Placeholder | Description | Example |
|---|---|---|
{player:x} |
X coordinate (floor) | 128 |
{player:y} |
Y coordinate (floor) | 64 |
{player:z} |
Z coordinate (floor) | -45 |
{player:world} |
World display name | Lobby |
{player:world_folder} |
World folder name | worlds/lobby |
Experience & Gamemode
| Placeholder | Description | Example |
|---|---|---|
{player:xp_level} |
Experience level | 30 |
{player:xp_progress} |
XP progress to next level (%) | 45.2 |
{player:gamemode} |
Gamemode name | Survival |
{player:gamemode_id} |
Gamemode ID | 0 |
π Acknowledgments
Built with β€οΈ by AIPTU
Star β this repository if you find it useful!