174 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
	
		
			6.7 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| 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<T extends ExecutionCommandSource<T>> {
 | |
| 	@VisibleForTesting
 | |
| 	public static final DynamicCommandExceptionType ERROR_FORK_LIMIT_REACHED = new DynamicCommandExceptionType(
 | |
| 		object -> Component.translatableEscape("command.forkLimit", object)
 | |
| 	);
 | |
| 	private final String commandInput;
 | |
| 	private final ContextChain<T> command;
 | |
| 
 | |
| 	public BuildContexts(String commandInput, ContextChain<T> command) {
 | |
| 		this.commandInput = commandInput;
 | |
| 		this.command = command;
 | |
| 	}
 | |
| 
 | |
| 	protected void execute(T originalSource, List<T> sources, ExecutionContext<T> context, Frame frame, ChainModifiers chainModifiers) {
 | |
| 		ContextChain<T> contextChain = this.command;
 | |
| 		ChainModifiers chainModifiers2 = chainModifiers;
 | |
| 		List<T> list = sources;
 | |
| 		if (contextChain.getStage() != Stage.EXECUTE) {
 | |
| 			context.profiler().push((Supplier<String>)(() -> "prepare " + this.commandInput));
 | |
| 
 | |
| 			try {
 | |
| 				for (int i = context.forkLimit(); contextChain.getStage() != Stage.EXECUTE; contextChain = contextChain.nextStage()) {
 | |
| 					CommandContext<T> commandContext = contextChain.getTopContext();
 | |
| 					if (commandContext.isForked()) {
 | |
| 						chainModifiers2 = chainModifiers2.setForked();
 | |
| 					}
 | |
| 
 | |
| 					RedirectModifier<T> redirectModifier = commandContext.getRedirectModifier();
 | |
| 					if (redirectModifier instanceof CustomModifierExecutor<T> customModifierExecutor) {
 | |
| 						customModifierExecutor.apply(originalSource, list, contextChain, chainModifiers2, ExecutionControl.create(context, frame));
 | |
| 						return;
 | |
| 					}
 | |
| 
 | |
| 					if (redirectModifier != null) {
 | |
| 						context.incrementCost();
 | |
| 						boolean bl = chainModifiers2.isForked();
 | |
| 						List<T> list2 = new ObjectArrayList<>();
 | |
| 
 | |
| 						for (T executionCommandSource : list) {
 | |
| 							try {
 | |
| 								Collection<T> 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<T> commandContext2 = contextChain.getTopContext();
 | |
| 			if (commandContext2.getCommand() instanceof CustomCommandExecutor<T> customCommandExecutor) {
 | |
| 				ExecutionControl<T> 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<T> 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<T> 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<T extends ExecutionCommandSource<T>> extends BuildContexts<T> implements EntryAction<T> {
 | |
| 		private final ChainModifiers modifiers;
 | |
| 		private final T originalSource;
 | |
| 		private final List<T> sources;
 | |
| 
 | |
| 		public Continuation(String commandInput, ContextChain<T> command, ChainModifiers modifiers, T originalSource, List<T> sources) {
 | |
| 			super(commandInput, command);
 | |
| 			this.originalSource = originalSource;
 | |
| 			this.sources = sources;
 | |
| 			this.modifiers = modifiers;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public void execute(ExecutionContext<T> executionContext, Frame frame) {
 | |
| 			this.execute(this.originalSource, this.sources, executionContext, frame, this.modifiers);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static class TopLevel<T extends ExecutionCommandSource<T>> extends BuildContexts<T> implements EntryAction<T> {
 | |
| 		private final T source;
 | |
| 
 | |
| 		public TopLevel(String commandInput, ContextChain<T> command, T source) {
 | |
| 			super(commandInput, command);
 | |
| 			this.source = source;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public void execute(ExecutionContext<T> executionContext, Frame frame) {
 | |
| 			this.traceCommandStart(executionContext, frame);
 | |
| 			this.execute(this.source, List.of(this.source), executionContext, frame, ChainModifiers.DEFAULT);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static class Unbound<T extends ExecutionCommandSource<T>> extends BuildContexts<T> implements UnboundEntryAction<T> {
 | |
| 		public Unbound(String string, ContextChain<T> contextChain) {
 | |
| 			super(string, contextChain);
 | |
| 		}
 | |
| 
 | |
| 		public void execute(T executionCommandSource, ExecutionContext<T> executionContext, Frame frame) {
 | |
| 			this.traceCommandStart(executionContext, frame);
 | |
| 			this.execute(executionCommandSource, List.of(executionCommandSource), executionContext, frame, ChainModifiers.DEFAULT);
 | |
| 		}
 | |
| 	}
 | |
| }
 |