Files
craftdock/src/services/bedrockIdentityBridge.js
T
Lucas RayanandClaude Sonnet 5.5 640e52c0c9 Initial commit: CraftDock as of 2026-11-01
The previous GitHub history was lost with the account (the local .git was missing
its refs and most objects), so this repository starts from the existing code.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 22:44:39 -03:00

63 lines
2.0 KiB
JavaScript

import fsp from 'node:fs/promises';
import path from 'node:path';
// Persistent bridge between a Bedrock player's identity (numeric XUID + gamertag,
// known only from the log directory) and their LevelDB record (keyed by a
// self-signed UUID that never references the XUID). Learned while a player is
// online by matching the live entity `uniqueId` (from querytarget) to a LevelDB
// player's `UniqueID`; persisted so offline reads work forever afterwards.
//
// File: <dataRoot>/craftdock_bedrock_ids.json
// { "<xuid>": { name, leveldbUuid, uniqueId, boundAt } }
const FILE = 'craftdock_bedrock_ids.json';
export function createBedrockIdentityBridge({ dataRoot, fileAdapter }) {
const filePath = path.join(dataRoot, FILE);
async function readMap() {
try {
const data = JSON.parse(await fsp.readFile(filePath, 'utf8'));
return data && typeof data === 'object' && !Array.isArray(data) ? data : {};
} catch {
return {};
}
}
async function writeMap(map) {
try {
await fsp.writeFile(filePath, JSON.stringify(map, null, 2), 'utf8');
} catch { /* best-effort */ }
}
// Bind xuid → LevelDB uuid using the live uniqueId or fallbackUuid.
async function learn({ xuid, name, uniqueId, fallbackUuid }) {
if (!xuid) return null;
let targetUuid = fallbackUuid;
if (!targetUuid && uniqueId != null) {
const hit = await fileAdapter.findByUniqueId(String(uniqueId));
if (hit) targetUuid = hit.uuid;
}
if (!targetUuid) return null;
const map = await readMap();
const binding = {
name: name ?? map[xuid]?.name ?? null,
leveldbUuid: targetUuid,
uniqueId: uniqueId ? String(uniqueId) : (map[xuid]?.uniqueId || null),
boundAt: new Date().toISOString(),
};
map[xuid] = binding;
await writeMap(map);
return binding;
}
async function resolveLeveldbUuid(xuid) {
const map = await readMap();
return map[xuid]?.leveldbUuid || null;
}
return { learn, resolveLeveldbUuid };
}