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

XFEServerManager

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

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

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

/** Structural and budget validation for Trigger Program V2. */
public final class TriggerProgramValidator {
    public static final int MAX_NODES = 4_096;
    public static final int MAX_NESTING_DEPTH = 32;
    public static final int MAX_CALL_DEPTH = 16;
    public static final int MAX_LOOP_ITERATIONS = 10_000;
    public static final int MAX_INSTRUCTIONS = 100_000;

    private TriggerProgramValidator() { }

    public static void validate(TriggerProgramV2 program) {
        validate(program.events(), program.declarations(), program.functions(), program.statements());
    }

    static void validate(
            List<TriggerProgramV2.EventBinding> events,
            List<TriggerProgramV2.VariableDeclaration> declarations,
            List<TriggerProgramV2.FunctionDeclaration> functionDeclarations,
            List<TriggerProgramV2.Statement> rootStatements) {
        Counter counter = new Counter();
        Set<UUID> ids = new HashSet<>();
        Set<String> names = new HashSet<>();
        for (TriggerProgramV2.EventBinding event : events) add(event.nodeId(), ids, counter);
        for (TriggerProgramV2.VariableDeclaration declaration : declarations) {
            add(declaration.nodeId(), ids, counter);
            if (!names.add(declaration.name())) {
                throw new IllegalArgumentException("duplicate declaration: " + declaration.name());
            }
            expression(declaration.initialValue(), 1, ids, counter);
        }
        Set<String> functions = new HashSet<>();
        for (TriggerProgramV2.FunctionDeclaration function : functionDeclarations) {
            add(function.nodeId(), ids, counter);
            if (!functions.add(function.name())) {
                throw new IllegalArgumentException("duplicate function: " + function.name());
            }
            Set<String> parameters = new HashSet<>();
            function.parameters().forEach(parameter -> {
                if (!parameters.add(parameter.name())) {
                    throw new IllegalArgumentException("duplicate parameter in " + function.name() + ": " + parameter.name());
                }
            });
            for (TriggerProgramV2.VariableDeclaration local : function.locals()) {
                add(local.nodeId(), ids, counter);
                expression(local.initialValue(), 1, ids, counter);
            }
            statements(function.statements(), 1, ids, counter);
        }
        statements(rootStatements, 1, ids, counter);
        TriggerProgramTypeChecker.validate(declarations, functionDeclarations, rootStatements);
    }

    private static void statements(
            List<TriggerProgramV2.Statement> statements, int depth, Set<UUID> ids, Counter counter) {
        if (depth > MAX_NESTING_DEPTH) {
            throw new IllegalArgumentException("trigger nesting exceeds " + MAX_NESTING_DEPTH);
        }
        for (TriggerProgramV2.Statement statement : statements) {
            add(statement.nodeId(), ids, counter);
            expression(statement.expression(), depth, ids, counter);
            statement.inputs().values().forEach(value -> expression(value, depth, ids, counter));
            statements(statement.statements(), depth + 1, ids, counter);
            statements(statement.elseStatements(), depth + 1, ids, counter);
            for (TriggerProgramV2.SwitchCase branch : statement.cases()) {
                add(branch.nodeId(), ids, counter);
                expression(branch.match(), depth + 1, ids, counter);
                statements(branch.statements(), depth + 1, ids, counter);
            }
        }
    }

    private static void expression(
            TriggerExpression expression, int depth, Set<UUID> ids, Counter counter) {
        if (expression == null) return;
        if (depth > MAX_NESTING_DEPTH) {
            throw new IllegalArgumentException("expression nesting exceeds " + MAX_NESTING_DEPTH);
        }
        add(expression.nodeId(), ids, counter);
        for (TriggerExpression argument : expression.arguments()) {
            expression(argument, depth + 1, ids, counter);
        }
    }

    private static void add(UUID id, Set<UUID> ids, Counter counter) {
        if (!ids.add(id)) throw new IllegalArgumentException("duplicate trigger nodeId: " + id);
        if (++counter.value > MAX_NODES) {
            throw new IllegalArgumentException("trigger program exceeds " + MAX_NODES + " nodes");
        }
    }

    private static final class Counter { private int value; }
}