📄 Source: inventory.php
<?php
require_once __DIR__ . '/../auth.php';
require_once __DIR__ . '/../lib/servers.php';
require_once __DIR__ . '/../lib/clientid.php';
require_once __DIR__ . '/../lib/snbt.php';
require_auth_json();
$CFG = $GLOBALS['__CFG'];
$server = $_GET['server'] ?? '';
$player = $_GET['player'] ?? '';
if ($server === '' || strpos($server, '/') !== false || strpos($server, '..') !== false) {
http_response_code(400);
echo json_encode(['ok' => false, 'error' => 'Invalid server name']);
exit;
}
if ($player === '' || strlen($player) > 32) {
http_response_code(400);
echo json_encode(['ok' => false, 'error' => 'Invalid player name']);
exit;
}
$path = server_path($CFG['server_root'], $server);
try {
// Main inventory
$invRaw = clientid_rcon($path, $CFG, "data get entity $player Inventory");
// Optional: ender chest contents
$enderRaw = '';
try {
$enderRaw = clientid_rcon($path, $CFG, "data get entity $player EnderItems");
} catch (Throwable $e) {
// EnderItems may not exist yet — ignore
}
$inventory = snbt_response_to_array($invRaw);
$enderchest = snbt_response_to_array($enderRaw);
$main = is_array($inventory) ? snbt_summarize_inventory($inventory) : ['items' => []];
$ender = is_array($enderchest) ? snbt_summarize_inventory($enderchest) : ['items' => []];
// Also grab a couple of useful stats
$health = null; $xpLevel = null; $food = null;
foreach (['Health' => 'health', 'XpLevel' => 'xp_level', 'foodLevel' => 'food'] as $nbt => $key) {
try {
$r = clientid_rcon($path, $CFG, "data get entity $player $nbt");
if (preg_match('/has the following entity data:\s*(.+)$/m', $r, $m)) {
$val = trim($m[1]);
$val = rtrim($val, 'bslfBSLF');
if (is_numeric($val)) {
$$key = $val + 0;
}
}
} catch (Throwable $e) {}
}
header('Content-Type: application/json');
echo json_encode([
'ok' => true,
'player' => $player,
'inventory' => $main['items'],
'enderchest' => $ender['items'],
'health' => $health,
'xp_level' => $xpLevel,
'food' => $food,
]);
} catch (Throwable $e) {
header('Content-Type: application/json');
echo json_encode(['ok' => false, 'error' => $e->getMessage()]);
}
/**
* RCON "data get entity" responses look like:
* <player> has the following entity data: [ {...}, {...} ]
* We strip the prefix, then parse the SNBT.
*/
function snbt_response_to_array(string $raw): ?array {
if ($raw === '') return null;
$pos = strpos($raw, 'entity data:');
if ($pos === false) return null;
$snbt = trim(substr($raw, $pos + strlen('entity data:')));
if ($snbt === '' || $snbt === '[]') return [];
try {
$v = SnbtParser::parse($snbt);
return is_array($v) ? $v : null;
} catch (Throwable $e) {
return null;
}
}
← Back