📂 File Browser

serversdashboard/serversdashboard/lib
🌙 Dark Mode
🎯 Quick Launch:

📁 Directories

📄 Files

🐘 clientid.php
▶ Open 📄 View Source
🐘 net.php
▶ Open 📄 View Source
🐘 rcon.php
▶ Open 📄 View Source
🐘 servers.php
▶ Open 📄 View Source
🐘 snbt.php
▶ Open 📄 View Source
🐘 tmux.php
▶ Open 📄 View Source
🐘 users.php
▶ Open 📄 View Source

📄 Source: clientid.php

<?php
/**
 * ClientID mod integration.
 *
 * Wraps the /clientid viewmods and /clientid viewpacks commands and parses
 * their two-line RCON responses into arrays.
 *
 *   /clientid viewmods <player>
 *     → "ezyalex700_'s mod list:"
 *     → "appleskin, architectury, balm, ..."
 *
 *   /clientid viewpacks <player>
 *     → "ezyalex700_'s pack list:"
 *     → "Default, Fabric Mod \"AppleSkin\", Fabric Mod \"Balm\", ..."
 */

require_once __DIR__ . '/rcon.php';

/**
 * Run an RCON command and return the raw response text.
 */
function clientid_rcon(string $serverDir, array $cfg, string $command): string {
    $rcon = rcon_from_properties($serverDir, $cfg['rcon']);
    if (empty($rcon['password'])) {
        throw new RuntimeException('RCON not configured in server.properties');
    }
    $r = new Rcon($rcon['host'], (int)$rcon['port'], $rcon['password'], (int)$rcon['timeout']);
    try {
        return $r->command($command);
    } finally {
        $r->close();
    }
}

/**
 * Parse the "viewmods" response. Returns a lowercase list of mod IDs.
 */
function clientid_parse_mods(string $raw): array {
    // The response is two lines. First line ends with "'s mod list:".
    // Second line is the comma-separated list (may be empty).
    $lines = preg_split('/\r?\n/', trim($raw));
    $list = [];
    $foundHeader = false;

    foreach ($lines as $line) {
        if (stripos($line, "mod list") !== false) {
            $foundHeader = true;
            continue;
        }
        if ($foundHeader) {
            foreach (explode(',', $line) as $piece) {
                $piece = trim($piece);
                if ($piece !== '') $list[] = strtolower($piece);
            }
        }
    }

    // Deduplicate, keep order
    return array_values(array_unique($list));
}

/**
 * Parse the "viewpacks" response. Returns the list of pack names as-is.
 * Fabric mod resources come through as: Fabric Mod "Name"
 */
function clientid_parse_packs(string $raw): array {
    $lines = preg_split('/\r?\n/', trim($raw));
    $list = [];
    $foundHeader = false;

    foreach ($lines as $line) {
        if (stripos($line, "pack list") !== false) {
            $foundHeader = true;
            continue;
        }
        if ($foundHeader) {
            // Split on ", " but respect quotes inside Fabric Mod "Name"
            // Simple approach: split on commas that are followed by "Fabric Mod" or "Default" or a bare word
            $parts = preg_split('/,\s*(?=Fabric Mod |Default|[^,]*$)/', $line);
            foreach ($parts as $piece) {
                $piece = trim($piece, " \t\n\r\0\x0B");
                if ($piece !== '') $list[] = $piece;
            }
        }
    }

    return array_values(array_unique($list));
}

/**
 * Filter a mod list against a baseline (case-insensitive).
 */
function clientid_filter_mods(array $playerMods, array $baseline): array {
    $base = array_map('strtolower', $baseline);
    $baseSet = array_flip($base);
    $extra = [];
    foreach ($playerMods as $m) {
        $m = strtolower($m);
        if (!isset($baseSet[$m])) $extra[] = $m;
    }
    sort($extra);
    return $extra;
}

/**
 * Filter a pack list against a baseline (case-insensitive).
 */
function clientid_filter_packs(array $playerPacks, array $baseline): array {
    $baseSet = [];
    foreach ($baseline as $b) $baseSet[strtolower(trim($b))] = true;

    $extra = [];
    foreach ($playerPacks as $p) {
        $p = trim($p);
        if (!isset($baseSet[strtolower($p)])) $extra[] = $p;
    }
    sort($extra);
    return $extra;
}

/**
 * ClientID reports every Fabric mod's bundled resources as a "pack".
 * Those aren't player-installed packs — they're noise. Strip them out.
 */
function clientid_strip_mod_packs(array $packs): array {
    $out = [];
    foreach ($packs as $p) {
        // Skip "Fabric Mod \"...\"" entries
        if (preg_match('/^Fabric Mod\s+"/i', $p)) continue;
        // Keep "Default" out too — every vanilla client has it
        if (strcasecmp(trim($p), 'Default') === 0) continue;
        $out[] = $p;
    }
    return $out;
}
← Back