package id.dartokloning.lobbysystems; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import java.io.Reader; import java.io.Writer; import java.lang.reflect.Type; import java.nio.file.Files; /** * Shared persistent player database. Auth and last-position data intentionally * live in one file while remaining separate logical sections, so either * subsystem can update its own data without overwriting the other. */ public final class PlayerDataStore { private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); private static final Object LOCK = new Object(); private static final String AUTH = "auth"; private static final String POSITIONS = "positions"; private PlayerDataStore() {} public static T loadAuth(Type type, T fallback) { return loadSection(AUTH, type, fallback); } public static T loadPositions(Type type, T fallback) { return loadSection(POSITIONS, type, fallback); } public static void saveAuth(Object value, Type type) { saveSection(AUTH, value, type); } public static void savePositions(Object value, Type type) { saveSection(POSITIONS, value, type); } private static T loadSection(String name, Type type, T fallback) { synchronized (LOCK) { try { JsonObject root = readRoot(); JsonElement section = root.get(name); if (section == null || section.isJsonNull()) return fallback; T loaded = GSON.fromJson(section, type); return loaded == null ? fallback : loaded; } catch (Exception e) { LobbySystemsMod.LOGGER.error("Failed to load '{}' from {}", name, ConfigPaths.PLAYER, e); return fallback; } } } private static void saveSection(String name, Object value, Type type) { synchronized (LOCK) { try { JsonObject root = readRoot(); root.add(name, GSON.toJsonTree(value, type)); Files.createDirectories(ConfigPaths.PLAYER.getParent()); try (Writer writer = Files.newBufferedWriter(ConfigPaths.PLAYER)) { GSON.toJson(root, writer); } } catch (Exception e) { LobbySystemsMod.LOGGER.error("Failed to save '{}' to {}", name, ConfigPaths.PLAYER, e); } } } private static JsonObject readRoot() throws Exception { if (!Files.exists(ConfigPaths.PLAYER)) return new JsonObject(); try (Reader reader = Files.newBufferedReader(ConfigPaths.PLAYER)) { JsonElement parsed = JsonParser.parseReader(reader); if (parsed == null || parsed.isJsonNull()) return new JsonObject(); if (!parsed.isJsonObject()) throw new IllegalArgumentException("player.json root must be a JSON object"); return parsed.getAsJsonObject(); } } }