/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.google.common.collect.Queues * com.mojang.brigadier.context.ContextChain * com.mojang.logging.LogUtils * it.unimi.dsi.fastutil.objects.ObjectArrayList * org.jspecify.annotations.Nullable * org.slf4j.Logger */ package net.minecraft.commands.execution; import com.google.common.collect.Queues; import com.mojang.brigadier.context.ContextChain; import com.mojang.logging.LogUtils; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import java.util.Deque; import java.util.List; import net.minecraft.commands.CommandResultCallback; import net.minecraft.commands.ExecutionCommandSource; import net.minecraft.commands.execution.CommandQueueEntry; import net.minecraft.commands.execution.Frame; import net.minecraft.commands.execution.TraceCallbacks; import net.minecraft.commands.execution.tasks.BuildContexts; import net.minecraft.commands.execution.tasks.CallFunction; import net.minecraft.commands.functions.InstantiatedFunction; import net.minecraft.util.profiling.ProfilerFiller; import org.jspecify.annotations.Nullable; import org.slf4j.Logger; public class ExecutionContext implements AutoCloseable { private static final int MAX_QUEUE_DEPTH = 10000000; private static final Logger LOGGER = LogUtils.getLogger(); private final int commandLimit; private final int forkLimit; private final ProfilerFiller profiler; private @Nullable TraceCallbacks tracer; private int commandQuota; private boolean queueOverflow; private final Deque> commandQueue = Queues.newArrayDeque(); private final List> newTopCommands = new ObjectArrayList(); private int currentFrameDepth; public ExecutionContext(int commandLimit, int forkLimit, ProfilerFiller profiler) { this.commandLimit = commandLimit; this.forkLimit = forkLimit; this.profiler = profiler; this.commandQuota = commandLimit; } private static > Frame createTopFrame(ExecutionContext context, CommandResultCallback frameResult) { if (context.currentFrameDepth == 0) { return new Frame(0, frameResult, context.commandQueue::clear); } int reentrantFrameDepth = context.currentFrameDepth + 1; return new Frame(reentrantFrameDepth, frameResult, context.frameControlForDepth(reentrantFrameDepth)); } public static > void queueInitialFunctionCall(ExecutionContext context, InstantiatedFunction function, T sender, CommandResultCallback functionReturn) { context.queueNext(new CommandQueueEntry(ExecutionContext.createTopFrame(context, functionReturn), new CallFunction(function, sender.callback(), false).bind(sender))); } public static > void queueInitialCommandExecution(ExecutionContext context, String command, ContextChain executionChain, T sender, CommandResultCallback commandReturn) { context.queueNext(new CommandQueueEntry(ExecutionContext.createTopFrame(context, commandReturn), new BuildContexts.TopLevel(command, executionChain, sender))); } private void handleQueueOverflow() { this.queueOverflow = true; this.newTopCommands.clear(); this.commandQueue.clear(); } public void queueNext(CommandQueueEntry entry) { if (this.newTopCommands.size() + this.commandQueue.size() > 10000000) { this.handleQueueOverflow(); } if (!this.queueOverflow) { this.newTopCommands.add(entry); } } public void discardAtDepthOrHigher(int depthToDiscard) { while (!this.commandQueue.isEmpty() && this.commandQueue.peek().frame().depth() >= depthToDiscard) { this.commandQueue.removeFirst(); } } public Frame.FrameControl frameControlForDepth(int depthToDiscard) { return () -> this.discardAtDepthOrHigher(depthToDiscard); } public void runCommandQueue() { this.pushNewCommands(); while (true) { if (this.commandQuota <= 0) { LOGGER.info("Command execution stopped due to limit (executed {} commands)", (Object)this.commandLimit); break; } CommandQueueEntry command = this.commandQueue.pollFirst(); if (command == null) { return; } this.currentFrameDepth = command.frame().depth(); command.execute(this); if (this.queueOverflow) { LOGGER.error("Command execution stopped due to command queue overflow (max {})", (Object)10000000); break; } this.pushNewCommands(); } this.currentFrameDepth = 0; } private void pushNewCommands() { for (int i = this.newTopCommands.size() - 1; i >= 0; --i) { this.commandQueue.addFirst(this.newTopCommands.get(i)); } this.newTopCommands.clear(); } public void tracer(@Nullable TraceCallbacks tracer) { this.tracer = tracer; } public @Nullable TraceCallbacks tracer() { return this.tracer; } public ProfilerFiller profiler() { return this.profiler; } public int forkLimit() { return this.forkLimit; } public void incrementCost() { --this.commandQuota; } @Override public void close() { if (this.tracer != null) { this.tracer.close(); } } }