import type { RconFailure } from '$ui/stores/servers.js'; export interface DecodedRconError { reason: RconFailure; detail: string; } const KNOWN: RconFailure[] = [ 'no-config', 'no-port', 'send-error', 'timeout', 'bad-reply', 'no-players' ]; /** * Decode the ":" string the worker persists into * `servers.last_error`. Returns null for empty/legacy strings so the UI can * fall back to a generic message. */ export function decodeRconError(raw: string | null | undefined): DecodedRconError | null { if (!raw) return null; const idx = raw.indexOf(':'); if (idx <= 0) return null; const reason = raw.slice(0, idx); if (!KNOWN.includes(reason as RconFailure)) return null; return { reason: reason as RconFailure, detail: raw.slice(idx + 1).trim() }; } /** * Human-facing hint about how to fix each RCON failure. Kept short — the * detail already carries the specifics (host, port, byte counts, etc.). */ export function rconFixHint(reason: RconFailure): string { switch (reason) { case 'no-config': return 'Set RCON_PASSWORD in the container env and restart.'; case 'no-port': return 'Check the host agent and the game port assigned to this server.'; case 'send-error': return 'DNS or route problem — check the RCON host is reachable from this container.'; case 'timeout': return 'Plutonium is not replying on the resolved UDP port. Verify the server is running and the port matches.'; case 'bad-reply': return 'Something is listening but not speaking Plutonium RCON. Check the port and password.'; case 'no-players': return 'Reply parsed but no player table was found — likely a server-side dialect mismatch.'; } }