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

XFEServerManager

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

公开
关注 0 Fork 0 Star 0
UTF-8
package com.xfestudio.xfeservermanager.api.policy;

import com.xfestudio.xfeservermanager.api.command.CommandSourceKind;
import com.xfestudio.xfeservermanager.api.util.ApiChecks;
import java.util.Set;
import java.util.UUID;

/** Subject predicates are combined with logical AND; values inside a set use OR. */
public record SubjectMatcher(
        Set<UUID> actorIds,
        Set<String> roles,
        Integer minimumOpLevel,
        Integer maximumOpLevel,
        Set<CommandSourceKind> sources,
        Boolean onlineMode
) {
    public SubjectMatcher {
        actorIds = ApiChecks.immutableSet(actorIds, "actorIds");
        roles = ApiChecks.immutableLowercaseSet(roles, "roles");
        sources = ApiChecks.immutableSet(sources, "sources");
        validateOpLevel(minimumOpLevel, "minimumOpLevel");
        validateOpLevel(maximumOpLevel, "maximumOpLevel");
        if (minimumOpLevel != null && maximumOpLevel != null && minimumOpLevel > maximumOpLevel) {
            throw new IllegalArgumentException("minimumOpLevel must not exceed maximumOpLevel");
        }
    }

    public static SubjectMatcher any() {
        return new SubjectMatcher(Set.of(), Set.of(), null, null, Set.of(), null);
    }

    public boolean matches(ActorContext actor) {
        if (!actorIds.isEmpty() && (actor.actorId() == null || !actorIds.contains(actor.actorId()))) {
            return false;
        }
        if (!roles.isEmpty() && roles.stream().noneMatch(actor.roles()::contains)) {
            return false;
        }
        if (minimumOpLevel != null && actor.opLevel() < minimumOpLevel) {
            return false;
        }
        if (maximumOpLevel != null && actor.opLevel() > maximumOpLevel) {
            return false;
        }
        if (!sources.isEmpty() && !sources.contains(actor.source())) {
            return false;
        }
        return onlineMode == null || onlineMode == actor.onlineMode();
    }

    public int specificity() {
        int result = 0;
        result += actorIds.isEmpty() ? 0 : 10_000 - Math.min(actorIds.size(), 9_999);
        result += roles.isEmpty() ? 0 : 1_000 - Math.min(roles.size(), 999);
        result += minimumOpLevel == null ? 0 : 40;
        result += maximumOpLevel == null ? 0 : 40;
        result += sources.isEmpty() ? 0 : 20 - Math.min(sources.size(), 19);
        result += onlineMode == null ? 0 : 1;
        return result;
    }

    public int matchingRoleWeight(ActorContext actor) {
        return roles.stream().filter(actor.roles()::contains).mapToInt(actor::weightOf).max().orElse(0);
    }

    private static void validateOpLevel(Integer value, String name) {
        if (value != null && (value < 0 || value > 4)) {
            throw new IllegalArgumentException(name + " must be between 0 and 4");
        }
    }
}