XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEServerManager

【Java】我的世界XFE服务器管理器

公开
关注 0 Fork 0 Star 0
UTF-8
package com.xfestudio.xfeservermanager.core.governance.claim;

import java.util.EnumSet;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;

public record Claim(
        UUID claimId,
        UUID ownerId,
        String name,
        Set<ChunkKey> chunks,
        Map<UUID, ClaimRole> assignments,
        Set<ClaimFlag> publicFlags,
        long revision
) {
    public Claim {
        Objects.requireNonNull(claimId, "claimId");
        Objects.requireNonNull(ownerId, "ownerId");
        if (name == null || name.isBlank()) throw new IllegalArgumentException("name must not be blank");
        name = name.trim();
        Objects.requireNonNull(chunks, "chunks");
        chunks = Set.copyOf(chunks);
        if (chunks.isEmpty()) throw new IllegalArgumentException("claim must contain at least one chunk");
        String dimension = chunks.iterator().next().dimensionId();
        if (chunks.stream().anyMatch(chunk -> !chunk.dimensionId().equals(dimension))) {
            throw new IllegalArgumentException("one claim cannot span dimensions");
        }
        if (!isContiguous(chunks)) throw new IllegalArgumentException("claim chunks must be cardinally contiguous");
        Objects.requireNonNull(assignments, "assignments");
        var normalized = new java.util.HashMap<>(assignments);
        if (normalized.containsValue(ClaimRole.OWNER)
                && !ClaimRole.OWNER.equals(normalized.get(ownerId))) {
            throw new IllegalArgumentException("only ownerId can hold the owner role");
        }
        normalized.entrySet().removeIf(entry -> entry.getValue() == null);
        if (normalized.entrySet().stream().anyMatch(entry -> entry.getValue() == ClaimRole.OWNER
                && !entry.getKey().equals(ownerId))) {
            throw new IllegalArgumentException("only ownerId can hold the owner role");
        }
        normalized.put(ownerId, ClaimRole.OWNER);
        assignments = Map.copyOf(normalized);
        Objects.requireNonNull(publicFlags, "publicFlags");
        publicFlags = publicFlags.isEmpty() ? Set.of() : Set.copyOf(EnumSet.copyOf(publicFlags));
        if (revision < 0) throw new IllegalArgumentException("revision must be non-negative");
    }

    public String dimensionId() {
        return chunks.iterator().next().dimensionId();
    }

    public ClaimRole roleOf(UUID playerId) {
        return assignments.get(playerId);
    }

    public Claim withChunks(Set<ChunkKey> next) {
        return new Claim(claimId, ownerId, name, next, assignments, publicFlags, revision + 1);
    }

    public Claim withAssignment(UUID playerId, ClaimRole role) {
        Objects.requireNonNull(playerId, "playerId");
        Objects.requireNonNull(role, "role");
        if (playerId.equals(ownerId) && role != ClaimRole.OWNER) {
            throw new IllegalArgumentException("owner role cannot be changed");
        }
        if (role == ClaimRole.OWNER && !playerId.equals(ownerId)) {
            throw new IllegalArgumentException("ownership requires the transfer workflow");
        }
        var next = new java.util.HashMap<>(assignments);
        next.put(playerId, role);
        return new Claim(claimId, ownerId, name, chunks, next, publicFlags, revision + 1);
    }

    public Claim withoutAssignment(UUID playerId) {
        Objects.requireNonNull(playerId, "playerId");
        if (playerId.equals(ownerId)) throw new IllegalArgumentException("owner cannot be removed");
        var next = new java.util.HashMap<>(assignments);
        next.remove(playerId);
        return new Claim(claimId, ownerId, name, chunks, next, publicFlags, revision + 1);
    }

    public Claim withFlags(Set<ClaimFlag> flags) {
        return new Claim(claimId, ownerId, name, chunks, assignments, flags, revision + 1);
    }

    public Claim transferTo(UUID newOwner) {
        Objects.requireNonNull(newOwner, "newOwner");
        if (newOwner.equals(ownerId)) throw new IllegalArgumentException("new owner must differ from current owner");
        var next = new java.util.HashMap<>(assignments);
        next.put(ownerId, ClaimRole.MANAGER);
        next.put(newOwner, ClaimRole.OWNER);
        return new Claim(claimId, newOwner, name, chunks, next, publicFlags, revision + 1);
    }

    private static boolean isContiguous(Set<ChunkKey> chunks) {
        var reached = new java.util.HashSet<ChunkKey>();
        var queue = new java.util.ArrayDeque<ChunkKey>();
        queue.add(chunks.iterator().next());
        while (!queue.isEmpty()) {
            ChunkKey current = queue.remove();
            if (!reached.add(current)) continue;
            for (ChunkKey candidate : chunks) {
                if (!reached.contains(candidate) && current.cardinallyAdjacent(candidate)) queue.add(candidate);
            }
        }
        return reached.size() == chunks.size();
    }
}