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; }
}