package ar.com.companeros.horror; import com.google.gson.*; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.*; import java.util.Set; /** Tiempos del operador; un día corresponde a 24 000 ticks guardados del mundo. */ public record HorrorConfig(boolean enabled, long meteorDelayTicks, long infectionDelayTicks, long stageDurationTicks, int finalStage, int safeRadius) { private static final Set KEYS = Set.of("schemaVersion", "enabled", "meteorAfterDays", "infectionAfterMeteorDays", "daysPerStage", "finalStage", "safeRadius"); public HorrorConfig { if (meteorDelayTicks < 0 || infectionDelayTicks < 0 || stageDurationTicks < 20 || finalStage != 4 || safeRadius < 32 || safeRadius > 256) throw new IllegalArgumentException("Tiempos o límites del parásito inválidos"); } public static HorrorConfig defaults() { return new HorrorConfig(true, 72_000, 48_000, 24_000, 4, 64); } public static HorrorConfig load(Path root) throws IOException { Files.createDirectories(root); Path file = root.resolve("parasite.json"); if (!Files.exists(file)) { JsonObject data = new JsonObject(); data.addProperty("schemaVersion", 1); data.addProperty("enabled", true); data.addProperty("meteorAfterDays", 3); data.addProperty("infectionAfterMeteorDays", 2); data.addProperty("daysPerStage", 1); data.addProperty("finalStage", 4); data.addProperty("safeRadius", 64); Files.writeString(file, new GsonBuilder().setPrettyPrinting().create().toJson(data), StandardCharsets.UTF_8, StandardOpenOption.CREATE_NEW); } if (Files.isSymbolicLink(file) || Files.size(file) > 8192) throw new IOException("parasite.json fuera de límite"); try { JsonObject data = JsonParser.parseString(Files.readString(file, StandardCharsets.UTF_8)).getAsJsonObject(); if (!KEYS.containsAll(data.keySet()) || data.get("schemaVersion").getAsInt() != 1) throw new IllegalArgumentException("Formato de parásito desconocido"); return new HorrorConfig(data.get("enabled").getAsBoolean(), days(data, "meteorAfterDays"), days(data, "infectionAfterMeteorDays"), days(data, "daysPerStage"), data.get("finalStage").getAsInt(), data.get("safeRadius").getAsInt()); } catch (RuntimeException failure) { throw new IOException("No se pudo leer parasite.json; se conserva el archivo", failure); } } private static long days(JsonObject data, String key) { double value = data.get(key).getAsDouble(); if (!Double.isFinite(value) || value < 0 || value > 3650) throw new IllegalArgumentException("Días inválidos"); return Math.round(value * 24_000); } }