package net.minecraft.commands.execution.tasks; import com.google.common.annotations.VisibleForTesting; import com.mojang.brigadier.RedirectModifier; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.ContextChain; import com.mojang.brigadier.context.ContextChain.Stage; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.util.Collection; import java.util.List; import java.util.function.Supplier; import net.minecraft.commands.CommandResultCallback; import net.minecraft.commands.ExecutionCommandSource; import net.minecraft.commands.execution.ChainModifiers; import net.minecraft.commands.execution.CommandQueueEntry; import net.minecraft.commands.execution.CustomCommandExecutor; import net.minecraft.commands.execution.CustomModifierExecutor; import net.minecraft.commands.execution.EntryAction; import net.minecraft.commands.execution.ExecutionContext; import net.minecraft.commands.execution.ExecutionControl; import net.minecraft.commands.execution.Frame; import net.minecraft.commands.execution.TraceCallbacks; import net.minecraft.commands.execution.UnboundEntryAction; import net.minecraft.network.chat.Component; public class BuildContexts> { @VisibleForTesting public static final DynamicCommandExceptionType ERROR_FORK_LIMIT_REACHED = new DynamicCommandExceptionType( object -> Component.translatableEscape("command.forkLimit", object) ); private final String commandInput; private final ContextChain command; public BuildContexts(String commandInput, ContextChain command) { this.commandInput = commandInput; this.command = command; } protected void execute(T originalSource, List sources, ExecutionContext context, Frame frame, ChainModifiers chainModifiers) { ContextChain contextChain = this.command; ChainModifiers chainModifiers2 = chainModifiers; List list = sources; if (contextChain.getStage() != Stage.EXECUTE) { context.profiler().push((Supplier)(() -> "prepare " + this.commandInput)); try { for (int i = context.forkLimit(); contextChain.getStage() != Stage.EXECUTE; contextChain = contextChain.nextStage()) { CommandContext commandContext = contextChain.getTopContext(); if (commandContext.isForked()) { chainModifiers2 = chainModifiers2.setForked(); } RedirectModifier redirectModifier = commandContext.getRedirectModifier(); if (redirectModifier instanceof CustomModifierExecutor customModifierExecutor) { customModifierExecutor.apply(originalSource, list, contextChain, chainModifiers2, ExecutionControl.create(context, frame)); return; } if (redirectModifier != null) { context.incrementCost(); boolean bl = chainModifiers2.isForked(); List list2 = new ObjectArrayList<>(); for (T executionCommandSource : list) { try { Collection collection = ContextChain.runModifier(commandContext, executionCommandSource, (commandContextx, blx, ix) -> {}, bl); if (list2.size() + collection.size() >= i) { originalSource.handleError(ERROR_FORK_LIMIT_REACHED.create(i), bl, context.tracer()); return; } list2.addAll(collection); } catch (CommandSyntaxException var20) { executionCommandSource.handleError(var20, bl, context.tracer()); if (!bl) { return; } } } list = list2; } } } finally { context.profiler().pop(); } } if (list.isEmpty()) { if (chainModifiers2.isReturn()) { context.queueNext(new CommandQueueEntry<>(frame, FallthroughTask.instance())); } } else { CommandContext commandContext2 = contextChain.getTopContext(); if (commandContext2.getCommand() instanceof CustomCommandExecutor customCommandExecutor) { ExecutionControl executionControl = ExecutionControl.create(context, frame); for (T executionCommandSource2 : list) { customCommandExecutor.run(executionCommandSource2, contextChain, chainModifiers2, executionControl); } } else { if (chainModifiers2.isReturn()) { T executionCommandSource3 = (T)list.get(0); executionCommandSource3 = executionCommandSource3.withCallback( CommandResultCallback.chain(executionCommandSource3.callback(), frame.returnValueConsumer()) ); list = List.of(executionCommandSource3); } ExecuteCommand executeCommand = new ExecuteCommand<>(this.commandInput, chainModifiers2, commandContext2); ContinuationTask.schedule( context, frame, list, (framex, executionCommandSourcex) -> new CommandQueueEntry<>(framex, executeCommand.bind((T)executionCommandSourcex)) ); } } } protected void traceCommandStart(ExecutionContext executionContext, Frame frame) { TraceCallbacks traceCallbacks = executionContext.tracer(); if (traceCallbacks != null) { traceCallbacks.onCommand(frame.depth(), this.commandInput); } } public String toString() { return this.commandInput; } public static class Continuation> extends BuildContexts implements EntryAction { private final ChainModifiers modifiers; private final T originalSource; private final List sources; public Continuation(String commandInput, ContextChain command, ChainModifiers modifiers, T originalSource, List sources) { super(commandInput, command); this.originalSource = originalSource; this.sources = sources; this.modifiers = modifiers; } @Override public void execute(ExecutionContext executionContext, Frame frame) { this.execute(this.originalSource, this.sources, executionContext, frame, this.modifiers); } } public static class TopLevel> extends BuildContexts implements EntryAction { private final T source; public TopLevel(String commandInput, ContextChain command, T source) { super(commandInput, command); this.source = source; } @Override public void execute(ExecutionContext executionContext, Frame frame) { this.traceCommandStart(executionContext, frame); this.execute(this.source, List.of(this.source), executionContext, frame, ChainModifiers.DEFAULT); } } public static class Unbound> extends BuildContexts implements UnboundEntryAction { public Unbound(String string, ContextChain contextChain) { super(string, contextChain); } public void execute(T executionCommandSource, ExecutionContext executionContext, Frame frame) { this.traceCommandStart(executionContext, frame); this.execute(executionCommandSource, List.of(executionCommandSource), executionContext, frame, ChainModifiers.DEFAULT); } } }