Volver al índice
src/main/java/ar/com/companeros/runtime/AgentJournal.java
package ar.com.companeros.runtime;
import java.util.*;
import net.minecraft.nbt.*;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.saveddata.SavedData;
/** Checkpoints de objetivos. Un reinicio conserva contexto y exige volver a observar antes de actuar. */
public final class AgentJournal extends SavedData {
public record Entry(String goal, String outcome, int consecutiveFailures, boolean interrupted, long updatedAtUtc) { }
private final Map<UUID, Entry> entries = new HashMap<>();
public static AgentJournal get(MinecraftServer server) {
if (!server.isSameThread()) throw new IllegalStateException("El diario exige el hilo del servidor");
return server.overworld().getDataStorage().computeIfAbsent(AgentJournal::load, AgentJournal::new, "companeros_objetivos");
}
public Entry entry(UUID id) { return entries.getOrDefault(id, new Entry("Sobrevivir y evaluar el entorno", "", 0, false, 0)); }
public void checkpoint(UUID id, String goal, String outcome, int failures, boolean interrupted) {
if (entries.size() >= 256 && !entries.containsKey(id)) throw new IllegalStateException("Diario lleno");
entries.put(id, new Entry(limit(goal, 512), limit(outcome, 512), Math.max(0, Math.min(100, failures)), interrupted, System.currentTimeMillis()));
setDirty();
}
@Override public CompoundTag save(CompoundTag root) {
root.putInt("Schema", 1); ListTag list = new ListTag();
for (var item : entries.entrySet()) {
CompoundTag tag = new CompoundTag(); Entry e = item.getValue();
tag.putUUID("Id", item.getKey()); tag.putString("Goal", e.goal()); tag.putString("Outcome", e.outcome());
tag.putInt("Failures", e.consecutiveFailures()); tag.putBoolean("Interrupted", e.interrupted()); tag.putLong("Updated", e.updatedAtUtc()); list.add(tag);
}
root.put("Entries", list); return root;
}
public static AgentJournal load(CompoundTag root) {
if (root.getInt("Schema") > 1) throw new IllegalStateException("Diario de una versión posterior");
AgentJournal data = new AgentJournal(); ListTag list = root.getList("Entries", 10);
if (list.size() > 256) throw new IllegalStateException("Diario fuera de límite");
for (int i = 0; i < list.size(); i++) {
CompoundTag tag = list.getCompound(i); UUID id = tag.getUUID("Id");
if (data.entries.containsKey(id)) throw new IllegalStateException("Entrada duplicada");
data.entries.put(id, new Entry(limit(tag.getString("Goal"), 512), limit(tag.getString("Outcome"), 512),
Math.max(0, Math.min(100, tag.getInt("Failures"))), tag.getBoolean("Interrupted"), Math.max(0, tag.getLong("Updated"))));
}
return data;
}
private static String limit(String value, int count) { return value.length() > count ? value.substring(0, count) : value; }
}