A dependency-light common utility library for PocketMine-MP plugins and EasyLibrary packages. LibCommons provides focused helpers for arrays, Minecraft text, numbers, math, durations, validation, safe data handling, small diagnostics, and tiny filesystem tasks without requiring a runtime service or a plugin lifecycle.
LibCommons exists to keep the EasyLibrary core lean. Helpers that are useful for many plugins, but are not part of the core loader/package manager/module runtime, belong here instead of living permanently inside EasyLibrary/src/imperazim/components/utils.
- Array helpers: dot-notation reads/writes, key flattening,
pluck,groupBy,sortBy,first,last,uniqueBy, and safe chunks. - Minecraft text helpers: whitespace normalization, wrapping, truncation, case conversion, slugs, filename sanitizing, legacy color conversion, color stripping, rainbow text, legacy-gradient approximation, centering, progress bars, tables, and bullet lists.
- Number helpers: clamp, range checks, currency formatting, percentages, compact notation, zero padding, averages, min/max helpers, random integers, random floats, ratio, and range mapping.
- Math helpers: easing, interpolation, remapping, distance checks, vector normalization, AABB value objects, simple shape point generation, and weighted random selection.
- Time helpers: immutable clock access, formatted date/time helpers, weekend/leap-year checks, wildcard pattern matching, duration parsing/formatting, stopwatches, and key-based cooldowns.
- Validation helpers: email, URL, IP, number/integer, Minecraft username, identifiers, namespaced identifiers, semantic versions, filenames, path segments, blank string, string length, regex, and enum-like value checks.
- Result/data helpers:
Result,Option, safe exception capture, nullable conversion, value mapping, safe JSON encode/decode, Base64 helpers, SHA-256 helpers, and checksum lines. - Diagnostics/filesystem helpers: tiny report/table/list renderers, path joining, lexical path normalization, path containment checks, atomic writes, temp paths, directory creation, and byte-size formatting.
- Package-ready layout: ships as a standalone PMMP plugin and as an EasyLibrary classpath package.
- PocketMine-MP API 5.0.0+
- PHP 8.2+
- No required EasyLibrary package dependencies
Download the LibCommons-<version>.phar release and place it in your server plugins/ directory.
Download LibCommons-<version>.easylib.zip and install it through the EasyLibrary package manager:
/easylibrary packages install libcommons development confirm
For a full local package-backed stack during EasyLibrary 3.0-dev smoke tests, use:
/easylibrary packages bootstrap confirm
LibCommons is a classpath package, so it does not need an enable/disable lifecycle. Once loaded, its classes are available to other packages and plugins.
{
"autoload": {
"psr-4": {
"imperazim\\commons\\": "src/imperazim/commons"
}
}
}use imperazim\commons\collection\Arr;
use imperazim\commons\math\Easing;
use imperazim\commons\number\Number;
use imperazim\commons\text\Text;
use imperazim\commons\time\Duration;
use imperazim\commons\validation\Validator;
$name = Arr::get($config, 'server.display-name', 'My Server');
$slug = Text::slug($name);
$money = Number::currency(12500);
$bar = Text::progressBar(Easing::easeOutCubic(0.65));
$cooldown = Duration::formatShort(Duration::minutes(5));
if (!Validator::minecraftUsername($playerName)) {
throw new InvalidArgumentException('Invalid Minecraft username.');
}examples/README.mdcollects short usage snippets by topic.examples/plugin_settings_summary.phpshows a realistic plugin-settings summary built fromArr,DataFile,Path,Report,Text,Number,DurationandValidator.
The PHP examples are included in the repository lint step so they stay syntactically valid as the API evolves.
Array helpers for nested data, configuration-like structures, and small in-memory collections.
use imperazim\commons\collection\Arr;
$data = [];
Arr::set($data, 'server.motd', 'Welcome');
echo Arr::get($data, 'server.motd'); // Welcome
$players = [
['name' => 'Steve', 'team' => 'red', 'coins' => 1500],
['name' => 'Alex', 'team' => 'blue', 'coins' => 250],
];
$flat = Arr::flattenWithKeys(['server' => ['motd' => 'Welcome']]);
$names = Arr::pluck($players, 'name');
$byTeam = Arr::groupBy($players, 'team');
$richestFirst = Arr::sortBy($players, 'coins', descending: true);
$firstRed = Arr::first($players, static fn(array $player): bool => $player['team'] === 'red');LibCommons intentionally does not port the old pseudo-SQL array query helpers from EasyLibrary. If you need real query behavior, use LibDB; if you need collection pipelines, prefer explicit PHP callbacks or a future typed collection layer.
String helpers for player-facing messages, config keys, slugs, and Minecraft color formatting.
use imperazim\commons\text\Text;
$clean = Text::normalizeSpaces(" Hello world\n");
$short = Text::truncate('A very long server message', 12);
$slug = Text::slug('Crystal Lobby #1');
$colored = Text::colorize('&aOnline');
$plain = Text::stripMinecraftColors($colored);
$bar = Text::progressBar(0.75, segments: 20);
$title = Text::center(Text::rainbow('SkyBlock'));
$table = Text::table([['Steve', 1500], ['Alex', 250]], ['Player', 'Coins']);Text::legacyGradient() intentionally approximates RGB gradients using real Bedrock legacy color codes. It does not pretend Bedrock supports Java-style hex RGB chat formatting where it does not.
Numeric helpers for UI values, economy text, limits, random IDs, and compact displays.
use imperazim\commons\number\Number;
$health = Number::clamp($health, 0, 20);
$coins = Number::currency(12500); // 12.500
$compact = Number::compact(1500); // 1.5K
$percent = Number::percent(0.875); // 87.50%
$mapped = Number::mapRange(5, 0, 10, 0, 100); // 50.0Pure math helpers extracted from the old LibMath idea without depending on Player, World, particles, or server lifecycle.
use imperazim\commons\math\Aabb;
use imperazim\commons\math\Easing;
use imperazim\commons\math\Geometry;
use imperazim\commons\math\Interpolation;
use imperazim\commons\math\Shape;
use imperazim\commons\math\WeightedRandom;
$alpha = Easing::easeOutCubic($progress);
$height = Interpolation::remap($level, 0, 100, 0, 256);
$near = Geometry::within3D($x, $y, $z, $targetX, $targetY, $targetZ, 8);
$box = Aabb::fromPoints(0, 0, 0, 16, 8, 16);
$sphereOffsets = Shape::sphere(radius: 3, hollow: true);
$reward = WeightedRandom::pick(['common' => 80, 'rare' => 18, 'epic' => 2]);Time helpers that avoid scattering date(), timestamp math, and hand-written duration formatting across plugins.
use imperazim\commons\time\Clock;
use imperazim\commons\time\Duration;
use imperazim\commons\time\KeyCooldown;
use imperazim\commons\time\Stopwatch;
$now = Clock::time();
$isEventMinute = Clock::matchesPattern($now, '##:30:##');
$cooldownText = Duration::formatShort(Duration::minutes(10));
$seconds = Duration::parse('1h30m');
$timer = Stopwatch::start();
// ...work...
$elapsedMs = $timer->elapsedMilliseconds();
$cooldowns = new KeyCooldown();
$cooldowns->start('player-name', Duration::minutes(5));Small validation helpers for config, commands, forms, and API inputs.
use imperazim\commons\validation\Validator;
if (!Validator::url($webhookUrl)) {
throw new InvalidArgumentException('Invalid webhook URL.');
}
if (!Validator::minecraftUsername($name)) {
$sender->sendMessage('Use a valid Minecraft username.');
}
if (!Validator::namespacedIdentifier('minecraft:stone')) {
throw new InvalidArgumentException('Invalid namespaced identifier.');
}
if (!Validator::semver('3.0.0-dev')) {
throw new InvalidArgumentException('Invalid package version.');
}Small Result and Option value objects for APIs that should return explicit success/failure or present/missing states without exceptions everywhere.
use imperazim\commons\result\Option;
use imperazim\commons\result\Result;
function findName(array $data): Option {
return Option::fromNullable($data['name'] ?? null)
->filter(static fn(string $name): bool => $name !== '');
}
function saveConfig(array $data): Result {
return $data === [] ? Result::error('Config is empty.') : Result::ok($data);
}
$display = findName($data)
->map(static fn(string $name): string => ucfirst($name))
->toResult('Missing display name.');
$saved = Result::capture(static function() use ($path): void {
if (file_put_contents($path, 'ok') === false) {
throw new RuntimeException('file_put_contents returned false');
}
})
->mapError(static fn(string $error): string => 'Write failed: ' . $error);Safe, tiny data helpers for JSON, Base64, SHA-256 and release/checksum style output.
use imperazim\commons\data\Base64;
use imperazim\commons\data\Hash;
use imperazim\commons\data\Json;
$json = Json::encode(['ok' => true]);
$data = Json::tryDecodeArray($json);
$token = Base64::urlEncode('payload');
$checksum = Hash::checksumLine($path);Small renderers for command output and doctor-style reports. They do not require LibCommand.
use imperazim\commons\diagnostics\Report;
use imperazim\commons\diagnostics\Table;
$report = Report::create('Package Doctor')
->item('Problems', 0)
->item('Packages', '14/14 active')
->toString();
$table = Table::render([['libcommons', 'active']], ['Package', 'Status']);Filesystem helpers for plugin-owned files and small structured data files. In
EasyLibrary 3.x, this namespace is the public replacement direction for the old
core imperazim\components\filesystem\File/Path toolkit. The EasyLibrary core
keeps only private bootstrap filesystem code for package-manager recovery.
use imperazim\commons\filesystem\DataFile;
use imperazim\commons\filesystem\FileSystem;
use imperazim\commons\filesystem\Path;
$path = Path::normalize(Path::join($plugin->getDataFolder(), 'cache', '..', 'cache', 'index.json'));
FileSystem::atomicWrite($path, Json::encode($data));
$settings = DataFile::at(Path::join($plugin->getDataFolder(), 'settings.json'));
$settings->ensure([
'enabled' => true,
'server' => ['motd' => 'Easy'],
]);
$settings->set('server.motd', 'Welcome');
if (!Path::isWithin($plugin->getDataFolder(), $settings->path())) {
throw new RuntimeException('Refusing to write outside plugin data.');
}See docs/migration-from-easylibrary-core.md for a focused migration map from the old EasyLibrary core helpers to LibCommons.
LibCommons is planned as the destination for generic utility code that should not be maintained inside the EasyLibrary core forever.
The EasyLibrary core should keep:
- package loading and package diagnostics
- module runtime and provider resolution
- command bridge/fallback infrastructure
- config migration/repair infrastructure
- private bootstrap filesystem primitives required to start and repair itself
- small runtime-only cache service
LibCommons should own:
- generic array/text/number/math/time/validation helpers
- result/data/diagnostic/filesystem helpers
- dependency-light developer convenience APIs
- future small value objects that are useful across multiple official libraries
LibCommons should not own:
- HTTP clients, retries, downloads, or webhooks; those belong in
LibHttp - resource pack packaging/deployment; that belongs in
LibAssets - database/query abstractions; those belong in
LibDB - serialization of PMMP objects; that belongs in
LibSerializer
Install dependencies:
composer installRun quality checks:
composer run qualityBuild release artifacts:
php -d phar.readonly=0 .github/scripts/build-phar.php
php .github/scripts/build-easylib-package.phpLibCommons is licensed under the MIT License. See LICENSE.