Volver al índice

src/main/java/ar/com/companeros/action/ToolResult.java

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<String, Integer> inventoryDelta, List<String> actualEffects,
        List<UUID> 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<String, Integer> delta, List<String> effects) {
        long now = System.currentTimeMillis();
        return new ToolResult(actionId, status, reason, delta, effects, List.of(), location, now, now);
    }
}