package ar.com.companeros.action; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.UUID; import net.minecraft.core.GlobalPos; /** Resultado observado por el servidor, no una afirmación emitida por el modelo. */ public record ToolResult(UUID actionId, Status status, Reason reason, Map inventoryDelta, List actualEffects, List evidenceIds, GlobalPos location, long startedAtUtc, long finishedAtUtc) { // Estados independientes del cuerpo: un bloqueo no es un éxito. public enum Status { RUNNING, WAITING, SUCCEEDED, FAILED, BLOCKED, CANCELLED } public enum Reason { NONE, NO_CHANGE, OUT_OF_REACH, NO_LINE_OF_SIGHT, PATH_BLOCKED, WRONG_TOOL, RESOURCE_EXHAUSTED, INVENTORY_FULL, PERMISSION_DENIED, RECIPE_UNSUPPORTED, CONDITIONS_CHANGED, INVALID_ARGUMENT, UNSUPPORTED, INTERNAL_ERROR, CANCELLED, TIMEOUT } public ToolResult { Objects.requireNonNull(actionId, "actionId"); Objects.requireNonNull(status, "status"); Objects.requireNonNull(reason, "reason"); inventoryDelta = Map.copyOf(inventoryDelta); actualEffects = List.copyOf(actualEffects); evidenceIds = List.copyOf(evidenceIds); if (startedAtUtc < 0 || finishedAtUtc < startedAtUtc) throw new IllegalArgumentException("Fechas de resultado inválidas"); } public boolean succeeded() { return status == Status.SUCCEEDED; } public boolean finished() { return status != Status.RUNNING && status != Status.WAITING; } public static ToolResult immediate(UUID actionId, Status status, Reason reason, GlobalPos location, Map delta, List effects) { long now = System.currentTimeMillis(); return new ToolResult(actionId, status, reason, delta, effects, List.of(), location, now, now); } }