548 lines
		
	
	
	
		
			24 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			548 lines
		
	
	
	
		
			24 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.commands;
 | |
| 
 | |
| import com.mojang.brigadier.CommandDispatcher;
 | |
| import com.mojang.brigadier.ParseResults;
 | |
| import com.mojang.brigadier.StringReader;
 | |
| import com.mojang.brigadier.arguments.ArgumentType;
 | |
| import com.mojang.brigadier.builder.ArgumentBuilder;
 | |
| import com.mojang.brigadier.builder.LiteralArgumentBuilder;
 | |
| import com.mojang.brigadier.builder.RequiredArgumentBuilder;
 | |
| import com.mojang.brigadier.context.CommandContextBuilder;
 | |
| import com.mojang.brigadier.context.ContextChain;
 | |
| import com.mojang.brigadier.exceptions.CommandSyntaxException;
 | |
| import com.mojang.brigadier.suggestion.SuggestionProvider;
 | |
| import com.mojang.brigadier.tree.ArgumentCommandNode;
 | |
| import com.mojang.brigadier.tree.CommandNode;
 | |
| import com.mojang.brigadier.tree.RootCommandNode;
 | |
| import com.mojang.logging.LogUtils;
 | |
| import java.util.HashMap;
 | |
| import java.util.Map;
 | |
| import java.util.Optional;
 | |
| import java.util.Set;
 | |
| import java.util.function.Consumer;
 | |
| import java.util.function.Predicate;
 | |
| import java.util.function.Supplier;
 | |
| import java.util.function.UnaryOperator;
 | |
| import java.util.stream.Collectors;
 | |
| import java.util.stream.Stream;
 | |
| import net.minecraft.ChatFormatting;
 | |
| import net.minecraft.SharedConstants;
 | |
| import net.minecraft.Util;
 | |
| import net.minecraft.commands.execution.ExecutionContext;
 | |
| import net.minecraft.commands.synchronization.ArgumentTypeInfos;
 | |
| import net.minecraft.commands.synchronization.ArgumentUtils;
 | |
| import net.minecraft.commands.synchronization.SuggestionProviders;
 | |
| import net.minecraft.core.HolderLookup;
 | |
| import net.minecraft.core.HolderSet;
 | |
| import net.minecraft.core.Registry;
 | |
| import net.minecraft.data.registries.VanillaRegistries;
 | |
| import net.minecraft.gametest.framework.TestCommand;
 | |
| import net.minecraft.network.chat.ClickEvent;
 | |
| import net.minecraft.network.chat.CommonComponents;
 | |
| import net.minecraft.network.chat.Component;
 | |
| import net.minecraft.network.chat.ComponentUtils;
 | |
| import net.minecraft.network.chat.HoverEvent;
 | |
| import net.minecraft.network.chat.MutableComponent;
 | |
| import net.minecraft.network.protocol.game.ClientboundCommandsPacket;
 | |
| import net.minecraft.resources.ResourceKey;
 | |
| import net.minecraft.resources.ResourceLocation;
 | |
| import net.minecraft.server.MinecraftServer;
 | |
| import net.minecraft.server.commands.AdvancementCommands;
 | |
| import net.minecraft.server.commands.AttributeCommand;
 | |
| import net.minecraft.server.commands.BanIpCommands;
 | |
| import net.minecraft.server.commands.BanListCommands;
 | |
| import net.minecraft.server.commands.BanPlayerCommands;
 | |
| import net.minecraft.server.commands.BossBarCommands;
 | |
| import net.minecraft.server.commands.ClearInventoryCommands;
 | |
| import net.minecraft.server.commands.CloneCommands;
 | |
| import net.minecraft.server.commands.DamageCommand;
 | |
| import net.minecraft.server.commands.DataPackCommand;
 | |
| import net.minecraft.server.commands.DeOpCommands;
 | |
| import net.minecraft.server.commands.DebugCommand;
 | |
| import net.minecraft.server.commands.DebugConfigCommand;
 | |
| import net.minecraft.server.commands.DebugMobSpawningCommand;
 | |
| import net.minecraft.server.commands.DebugPathCommand;
 | |
| import net.minecraft.server.commands.DefaultGameModeCommands;
 | |
| import net.minecraft.server.commands.DialogCommand;
 | |
| import net.minecraft.server.commands.DifficultyCommand;
 | |
| import net.minecraft.server.commands.EffectCommands;
 | |
| import net.minecraft.server.commands.EmoteCommands;
 | |
| import net.minecraft.server.commands.EnchantCommand;
 | |
| import net.minecraft.server.commands.ExecuteCommand;
 | |
| import net.minecraft.server.commands.ExperienceCommand;
 | |
| import net.minecraft.server.commands.FillBiomeCommand;
 | |
| import net.minecraft.server.commands.FillCommand;
 | |
| import net.minecraft.server.commands.ForceLoadCommand;
 | |
| import net.minecraft.server.commands.FunctionCommand;
 | |
| import net.minecraft.server.commands.GameModeCommand;
 | |
| import net.minecraft.server.commands.GameRuleCommand;
 | |
| import net.minecraft.server.commands.GiveCommand;
 | |
| import net.minecraft.server.commands.HelpCommand;
 | |
| import net.minecraft.server.commands.ItemCommands;
 | |
| import net.minecraft.server.commands.JfrCommand;
 | |
| import net.minecraft.server.commands.KickCommand;
 | |
| import net.minecraft.server.commands.KillCommand;
 | |
| import net.minecraft.server.commands.ListPlayersCommand;
 | |
| import net.minecraft.server.commands.LocateCommand;
 | |
| import net.minecraft.server.commands.LootCommand;
 | |
| import net.minecraft.server.commands.MsgCommand;
 | |
| import net.minecraft.server.commands.OpCommand;
 | |
| import net.minecraft.server.commands.PardonCommand;
 | |
| import net.minecraft.server.commands.PardonIpCommand;
 | |
| import net.minecraft.server.commands.ParticleCommand;
 | |
| import net.minecraft.server.commands.PerfCommand;
 | |
| import net.minecraft.server.commands.PermissionCheck;
 | |
| import net.minecraft.server.commands.PlaceCommand;
 | |
| import net.minecraft.server.commands.PlaySoundCommand;
 | |
| import net.minecraft.server.commands.PublishCommand;
 | |
| import net.minecraft.server.commands.RaidCommand;
 | |
| import net.minecraft.server.commands.RandomCommand;
 | |
| import net.minecraft.server.commands.RecipeCommand;
 | |
| import net.minecraft.server.commands.ReloadCommand;
 | |
| import net.minecraft.server.commands.ReturnCommand;
 | |
| import net.minecraft.server.commands.RideCommand;
 | |
| import net.minecraft.server.commands.RotateCommand;
 | |
| import net.minecraft.server.commands.SaveAllCommand;
 | |
| import net.minecraft.server.commands.SaveOffCommand;
 | |
| import net.minecraft.server.commands.SaveOnCommand;
 | |
| import net.minecraft.server.commands.SayCommand;
 | |
| import net.minecraft.server.commands.ScheduleCommand;
 | |
| import net.minecraft.server.commands.ScoreboardCommand;
 | |
| import net.minecraft.server.commands.SeedCommand;
 | |
| import net.minecraft.server.commands.ServerPackCommand;
 | |
| import net.minecraft.server.commands.SetBlockCommand;
 | |
| import net.minecraft.server.commands.SetPlayerIdleTimeoutCommand;
 | |
| import net.minecraft.server.commands.SetSpawnCommand;
 | |
| import net.minecraft.server.commands.SetWorldSpawnCommand;
 | |
| import net.minecraft.server.commands.SpawnArmorTrimsCommand;
 | |
| import net.minecraft.server.commands.SpectateCommand;
 | |
| import net.minecraft.server.commands.SpreadPlayersCommand;
 | |
| import net.minecraft.server.commands.StopCommand;
 | |
| import net.minecraft.server.commands.StopSoundCommand;
 | |
| import net.minecraft.server.commands.SummonCommand;
 | |
| import net.minecraft.server.commands.TagCommand;
 | |
| import net.minecraft.server.commands.TeamCommand;
 | |
| import net.minecraft.server.commands.TeamMsgCommand;
 | |
| import net.minecraft.server.commands.TeleportCommand;
 | |
| import net.minecraft.server.commands.TellRawCommand;
 | |
| import net.minecraft.server.commands.TickCommand;
 | |
| import net.minecraft.server.commands.TimeCommand;
 | |
| import net.minecraft.server.commands.TitleCommand;
 | |
| import net.minecraft.server.commands.TransferCommand;
 | |
| import net.minecraft.server.commands.TriggerCommand;
 | |
| import net.minecraft.server.commands.VersionCommand;
 | |
| import net.minecraft.server.commands.WardenSpawnTrackerCommand;
 | |
| import net.minecraft.server.commands.WaypointCommand;
 | |
| import net.minecraft.server.commands.WeatherCommand;
 | |
| import net.minecraft.server.commands.WhitelistCommand;
 | |
| import net.minecraft.server.commands.WorldBorderCommand;
 | |
| import net.minecraft.server.commands.data.DataCommands;
 | |
| import net.minecraft.server.level.ServerPlayer;
 | |
| import net.minecraft.tags.TagKey;
 | |
| import net.minecraft.util.profiling.Profiler;
 | |
| import net.minecraft.util.profiling.jfr.JvmProfiler;
 | |
| import net.minecraft.world.flag.FeatureFlagSet;
 | |
| import net.minecraft.world.flag.FeatureFlags;
 | |
| import net.minecraft.world.level.GameRules;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| import org.slf4j.Logger;
 | |
| 
 | |
| public class Commands {
 | |
| 	public static final String COMMAND_PREFIX = "/";
 | |
| 	private static final ThreadLocal<ExecutionContext<CommandSourceStack>> CURRENT_EXECUTION_CONTEXT = new ThreadLocal();
 | |
| 	private static final Logger LOGGER = LogUtils.getLogger();
 | |
| 	public static final int LEVEL_ALL = 0;
 | |
| 	public static final int LEVEL_MODERATORS = 1;
 | |
| 	public static final int LEVEL_GAMEMASTERS = 2;
 | |
| 	public static final int LEVEL_ADMINS = 3;
 | |
| 	public static final int LEVEL_OWNERS = 4;
 | |
| 	private static final ClientboundCommandsPacket.NodeInspector<CommandSourceStack> COMMAND_NODE_INSPECTOR = new ClientboundCommandsPacket.NodeInspector<CommandSourceStack>() {
 | |
| 		@Nullable
 | |
| 		@Override
 | |
| 		public ResourceLocation suggestionId(ArgumentCommandNode<CommandSourceStack, ?> node) {
 | |
| 			SuggestionProvider<CommandSourceStack> suggestionProvider = node.getCustomSuggestions();
 | |
| 			return suggestionProvider != null ? SuggestionProviders.getName(suggestionProvider) : null;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean isExecutable(CommandNode<CommandSourceStack> node) {
 | |
| 			return node.getCommand() != null;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean isRestricted(CommandNode<CommandSourceStack> node) {
 | |
| 			return node.getRequirement() instanceof PermissionCheck<?> permissionCheck && permissionCheck.requiredLevel() > 0;
 | |
| 		}
 | |
| 	};
 | |
| 	private final CommandDispatcher<CommandSourceStack> dispatcher = new CommandDispatcher<>();
 | |
| 
 | |
| 	public Commands(Commands.CommandSelection selection, CommandBuildContext context) {
 | |
| 		AdvancementCommands.register(this.dispatcher);
 | |
| 		AttributeCommand.register(this.dispatcher, context);
 | |
| 		ExecuteCommand.register(this.dispatcher, context);
 | |
| 		BossBarCommands.register(this.dispatcher, context);
 | |
| 		ClearInventoryCommands.register(this.dispatcher, context);
 | |
| 		CloneCommands.register(this.dispatcher, context);
 | |
| 		DamageCommand.register(this.dispatcher, context);
 | |
| 		DataCommands.register(this.dispatcher);
 | |
| 		DataPackCommand.register(this.dispatcher, context);
 | |
| 		DebugCommand.register(this.dispatcher);
 | |
| 		DefaultGameModeCommands.register(this.dispatcher);
 | |
| 		DialogCommand.register(this.dispatcher, context);
 | |
| 		DifficultyCommand.register(this.dispatcher);
 | |
| 		EffectCommands.register(this.dispatcher, context);
 | |
| 		EmoteCommands.register(this.dispatcher);
 | |
| 		EnchantCommand.register(this.dispatcher, context);
 | |
| 		ExperienceCommand.register(this.dispatcher);
 | |
| 		FillCommand.register(this.dispatcher, context);
 | |
| 		FillBiomeCommand.register(this.dispatcher, context);
 | |
| 		ForceLoadCommand.register(this.dispatcher);
 | |
| 		FunctionCommand.register(this.dispatcher);
 | |
| 		GameModeCommand.register(this.dispatcher);
 | |
| 		GameRuleCommand.register(this.dispatcher, context);
 | |
| 		GiveCommand.register(this.dispatcher, context);
 | |
| 		HelpCommand.register(this.dispatcher);
 | |
| 		ItemCommands.register(this.dispatcher, context);
 | |
| 		KickCommand.register(this.dispatcher);
 | |
| 		KillCommand.register(this.dispatcher);
 | |
| 		ListPlayersCommand.register(this.dispatcher);
 | |
| 		LocateCommand.register(this.dispatcher, context);
 | |
| 		LootCommand.register(this.dispatcher, context);
 | |
| 		MsgCommand.register(this.dispatcher);
 | |
| 		ParticleCommand.register(this.dispatcher, context);
 | |
| 		PlaceCommand.register(this.dispatcher);
 | |
| 		PlaySoundCommand.register(this.dispatcher);
 | |
| 		RandomCommand.register(this.dispatcher);
 | |
| 		ReloadCommand.register(this.dispatcher);
 | |
| 		RecipeCommand.register(this.dispatcher);
 | |
| 		ReturnCommand.register(this.dispatcher);
 | |
| 		RideCommand.register(this.dispatcher);
 | |
| 		RotateCommand.register(this.dispatcher);
 | |
| 		SayCommand.register(this.dispatcher);
 | |
| 		ScheduleCommand.register(this.dispatcher);
 | |
| 		ScoreboardCommand.register(this.dispatcher, context);
 | |
| 		SeedCommand.register(this.dispatcher, selection != Commands.CommandSelection.INTEGRATED);
 | |
| 		VersionCommand.register(this.dispatcher, selection != Commands.CommandSelection.INTEGRATED);
 | |
| 		SetBlockCommand.register(this.dispatcher, context);
 | |
| 		SetSpawnCommand.register(this.dispatcher);
 | |
| 		SetWorldSpawnCommand.register(this.dispatcher);
 | |
| 		SpectateCommand.register(this.dispatcher);
 | |
| 		SpreadPlayersCommand.register(this.dispatcher);
 | |
| 		StopSoundCommand.register(this.dispatcher);
 | |
| 		SummonCommand.register(this.dispatcher, context);
 | |
| 		TagCommand.register(this.dispatcher);
 | |
| 		TeamCommand.register(this.dispatcher, context);
 | |
| 		TeamMsgCommand.register(this.dispatcher);
 | |
| 		TeleportCommand.register(this.dispatcher);
 | |
| 		TellRawCommand.register(this.dispatcher, context);
 | |
| 		TestCommand.register(this.dispatcher, context);
 | |
| 		TickCommand.register(this.dispatcher);
 | |
| 		TimeCommand.register(this.dispatcher);
 | |
| 		TitleCommand.register(this.dispatcher, context);
 | |
| 		TriggerCommand.register(this.dispatcher);
 | |
| 		WaypointCommand.register(this.dispatcher, context);
 | |
| 		WeatherCommand.register(this.dispatcher);
 | |
| 		WorldBorderCommand.register(this.dispatcher);
 | |
| 		if (JvmProfiler.INSTANCE.isAvailable()) {
 | |
| 			JfrCommand.register(this.dispatcher);
 | |
| 		}
 | |
| 
 | |
| 		if (SharedConstants.IS_RUNNING_IN_IDE) {
 | |
| 			RaidCommand.register(this.dispatcher, context);
 | |
| 			DebugPathCommand.register(this.dispatcher);
 | |
| 			DebugMobSpawningCommand.register(this.dispatcher);
 | |
| 			WardenSpawnTrackerCommand.register(this.dispatcher);
 | |
| 			SpawnArmorTrimsCommand.register(this.dispatcher);
 | |
| 			ServerPackCommand.register(this.dispatcher);
 | |
| 			if (selection.includeDedicated) {
 | |
| 				DebugConfigCommand.register(this.dispatcher, context);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		if (selection.includeDedicated) {
 | |
| 			BanIpCommands.register(this.dispatcher);
 | |
| 			BanListCommands.register(this.dispatcher);
 | |
| 			BanPlayerCommands.register(this.dispatcher);
 | |
| 			DeOpCommands.register(this.dispatcher);
 | |
| 			OpCommand.register(this.dispatcher);
 | |
| 			PardonCommand.register(this.dispatcher);
 | |
| 			PardonIpCommand.register(this.dispatcher);
 | |
| 			PerfCommand.register(this.dispatcher);
 | |
| 			SaveAllCommand.register(this.dispatcher);
 | |
| 			SaveOffCommand.register(this.dispatcher);
 | |
| 			SaveOnCommand.register(this.dispatcher);
 | |
| 			SetPlayerIdleTimeoutCommand.register(this.dispatcher);
 | |
| 			StopCommand.register(this.dispatcher);
 | |
| 			TransferCommand.register(this.dispatcher);
 | |
| 			WhitelistCommand.register(this.dispatcher);
 | |
| 		}
 | |
| 
 | |
| 		if (selection.includeIntegrated) {
 | |
| 			PublishCommand.register(this.dispatcher);
 | |
| 		}
 | |
| 
 | |
| 		this.dispatcher.setConsumer(ExecutionCommandSource.resultConsumer());
 | |
| 	}
 | |
| 
 | |
| 	public static <S> ParseResults<S> mapSource(ParseResults<S> parseResults, UnaryOperator<S> mapper) {
 | |
| 		CommandContextBuilder<S> commandContextBuilder = parseResults.getContext();
 | |
| 		CommandContextBuilder<S> commandContextBuilder2 = commandContextBuilder.withSource((S)mapper.apply(commandContextBuilder.getSource()));
 | |
| 		return new ParseResults<>(commandContextBuilder2, parseResults.getReader(), parseResults.getExceptions());
 | |
| 	}
 | |
| 
 | |
| 	public void performPrefixedCommand(CommandSourceStack source, String command) {
 | |
| 		command = trimOptionalPrefix(command);
 | |
| 		this.performCommand(this.dispatcher.parse(command, source), command);
 | |
| 	}
 | |
| 
 | |
| 	public static String trimOptionalPrefix(String command) {
 | |
| 		return command.startsWith("/") ? command.substring(1) : command;
 | |
| 	}
 | |
| 
 | |
| 	public void performCommand(ParseResults<CommandSourceStack> parseResults, String command) {
 | |
| 		CommandSourceStack commandSourceStack = parseResults.getContext().getSource();
 | |
| 		Profiler.get().push((Supplier<String>)(() -> "/" + command));
 | |
| 		ContextChain<CommandSourceStack> contextChain = finishParsing(parseResults, command, commandSourceStack);
 | |
| 
 | |
| 		try {
 | |
| 			if (contextChain != null) {
 | |
| 				executeCommandInContext(
 | |
| 					commandSourceStack,
 | |
| 					executionContext -> ExecutionContext.queueInitialCommandExecution(executionContext, command, contextChain, commandSourceStack, CommandResultCallback.EMPTY)
 | |
| 				);
 | |
| 			}
 | |
| 		} catch (Exception var12) {
 | |
| 			MutableComponent mutableComponent = Component.literal(var12.getMessage() == null ? var12.getClass().getName() : var12.getMessage());
 | |
| 			if (LOGGER.isDebugEnabled()) {
 | |
| 				LOGGER.error("Command exception: /{}", command, var12);
 | |
| 				StackTraceElement[] stackTraceElements = var12.getStackTrace();
 | |
| 
 | |
| 				for (int i = 0; i < Math.min(stackTraceElements.length, 3); i++) {
 | |
| 					mutableComponent.append("\n\n")
 | |
| 						.append(stackTraceElements[i].getMethodName())
 | |
| 						.append("\n ")
 | |
| 						.append(stackTraceElements[i].getFileName())
 | |
| 						.append(":")
 | |
| 						.append(String.valueOf(stackTraceElements[i].getLineNumber()));
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			commandSourceStack.sendFailure(Component.translatable("command.failed").withStyle(style -> style.withHoverEvent(new HoverEvent.ShowText(mutableComponent))));
 | |
| 			if (SharedConstants.IS_RUNNING_IN_IDE) {
 | |
| 				commandSourceStack.sendFailure(Component.literal(Util.describeError(var12)));
 | |
| 				LOGGER.error("'/{}' threw an exception", command, var12);
 | |
| 			}
 | |
| 		} finally {
 | |
| 			Profiler.get().pop();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Nullable
 | |
| 	private static ContextChain<CommandSourceStack> finishParsing(ParseResults<CommandSourceStack> parseResults, String command, CommandSourceStack source) {
 | |
| 		try {
 | |
| 			validateParseResults(parseResults);
 | |
| 			return (ContextChain<CommandSourceStack>)ContextChain.tryFlatten(parseResults.getContext().build(command))
 | |
| 				.orElseThrow(() -> CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(parseResults.getReader()));
 | |
| 		} catch (CommandSyntaxException var7) {
 | |
| 			source.sendFailure(ComponentUtils.fromMessage(var7.getRawMessage()));
 | |
| 			if (var7.getInput() != null && var7.getCursor() >= 0) {
 | |
| 				int i = Math.min(var7.getInput().length(), var7.getCursor());
 | |
| 				MutableComponent mutableComponent = Component.empty()
 | |
| 					.withStyle(ChatFormatting.GRAY)
 | |
| 					.withStyle(style -> style.withClickEvent(new ClickEvent.SuggestCommand("/" + command)));
 | |
| 				if (i > 10) {
 | |
| 					mutableComponent.append(CommonComponents.ELLIPSIS);
 | |
| 				}
 | |
| 
 | |
| 				mutableComponent.append(var7.getInput().substring(Math.max(0, i - 10), i));
 | |
| 				if (i < var7.getInput().length()) {
 | |
| 					Component component = Component.literal(var7.getInput().substring(i)).withStyle(ChatFormatting.RED, ChatFormatting.UNDERLINE);
 | |
| 					mutableComponent.append(component);
 | |
| 				}
 | |
| 
 | |
| 				mutableComponent.append(Component.translatable("command.context.here").withStyle(ChatFormatting.RED, ChatFormatting.ITALIC));
 | |
| 				source.sendFailure(mutableComponent);
 | |
| 			}
 | |
| 
 | |
| 			return null;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static void executeCommandInContext(CommandSourceStack source, Consumer<ExecutionContext<CommandSourceStack>> contextConsumer) {
 | |
| 		MinecraftServer minecraftServer = source.getServer();
 | |
| 		ExecutionContext<CommandSourceStack> executionContext = (ExecutionContext<CommandSourceStack>)CURRENT_EXECUTION_CONTEXT.get();
 | |
| 		boolean bl = executionContext == null;
 | |
| 		if (bl) {
 | |
| 			int i = Math.max(1, minecraftServer.getGameRules().getInt(GameRules.RULE_MAX_COMMAND_CHAIN_LENGTH));
 | |
| 			int j = minecraftServer.getGameRules().getInt(GameRules.RULE_MAX_COMMAND_FORK_COUNT);
 | |
| 
 | |
| 			try (ExecutionContext<CommandSourceStack> executionContext2 = new ExecutionContext<>(i, j, Profiler.get())) {
 | |
| 				CURRENT_EXECUTION_CONTEXT.set(executionContext2);
 | |
| 				contextConsumer.accept(executionContext2);
 | |
| 				executionContext2.runCommandQueue();
 | |
| 			} finally {
 | |
| 				CURRENT_EXECUTION_CONTEXT.set(null);
 | |
| 			}
 | |
| 		} else {
 | |
| 			contextConsumer.accept(executionContext);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public void sendCommands(ServerPlayer player) {
 | |
| 		Map<CommandNode<CommandSourceStack>, CommandNode<CommandSourceStack>> map = new HashMap();
 | |
| 		RootCommandNode<CommandSourceStack> rootCommandNode = new RootCommandNode<>();
 | |
| 		map.put(this.dispatcher.getRoot(), rootCommandNode);
 | |
| 		fillUsableCommands(this.dispatcher.getRoot(), rootCommandNode, player.createCommandSourceStack(), map);
 | |
| 		player.connection.send(new ClientboundCommandsPacket(rootCommandNode, COMMAND_NODE_INSPECTOR));
 | |
| 	}
 | |
| 
 | |
| 	private static <S> void fillUsableCommands(CommandNode<S> root, CommandNode<S> current, S source, Map<CommandNode<S>, CommandNode<S>> output) {
 | |
| 		for (CommandNode<S> commandNode : root.getChildren()) {
 | |
| 			if (commandNode.canUse(source)) {
 | |
| 				ArgumentBuilder<S, ?> argumentBuilder = commandNode.createBuilder();
 | |
| 				if (argumentBuilder.getRedirect() != null) {
 | |
| 					argumentBuilder.redirect((CommandNode<S>)output.get(argumentBuilder.getRedirect()));
 | |
| 				}
 | |
| 
 | |
| 				CommandNode<S> commandNode2 = argumentBuilder.build();
 | |
| 				output.put(commandNode, commandNode2);
 | |
| 				current.addChild(commandNode2);
 | |
| 				if (!commandNode.getChildren().isEmpty()) {
 | |
| 					fillUsableCommands(commandNode, commandNode2, source, output);
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Creates a new argument. Intended to be imported statically. The benefit of this over the brigadier {@link LiteralArgumentBuilder#literal} method is that it is typed to {@link CommandSource}.
 | |
| 	 */
 | |
| 	public static LiteralArgumentBuilder<CommandSourceStack> literal(String name) {
 | |
| 		return LiteralArgumentBuilder.literal(name);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Creates a new argument. Intended to be imported statically. The benefit of this over the brigadier {@link RequiredArgumentBuilder#argument} method is that it is typed to {@link CommandSource}.
 | |
| 	 */
 | |
| 	public static <T> RequiredArgumentBuilder<CommandSourceStack, T> argument(String name, ArgumentType<T> type) {
 | |
| 		return RequiredArgumentBuilder.argument(name, type);
 | |
| 	}
 | |
| 
 | |
| 	public static Predicate<String> createValidator(Commands.ParseFunction parser) {
 | |
| 		return string -> {
 | |
| 			try {
 | |
| 				parser.parse(new StringReader(string));
 | |
| 				return true;
 | |
| 			} catch (CommandSyntaxException var3) {
 | |
| 				return false;
 | |
| 			}
 | |
| 		};
 | |
| 	}
 | |
| 
 | |
| 	public CommandDispatcher<CommandSourceStack> getDispatcher() {
 | |
| 		return this.dispatcher;
 | |
| 	}
 | |
| 
 | |
| 	public static <S> void validateParseResults(ParseResults<S> parseResults) throws CommandSyntaxException {
 | |
| 		CommandSyntaxException commandSyntaxException = getParseException(parseResults);
 | |
| 		if (commandSyntaxException != null) {
 | |
| 			throw commandSyntaxException;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Nullable
 | |
| 	public static <S> CommandSyntaxException getParseException(ParseResults<S> result) {
 | |
| 		if (!result.getReader().canRead()) {
 | |
| 			return null;
 | |
| 		} else if (result.getExceptions().size() == 1) {
 | |
| 			return (CommandSyntaxException)result.getExceptions().values().iterator().next();
 | |
| 		} else {
 | |
| 			return result.getContext().getRange().isEmpty()
 | |
| 				? CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand().createWithContext(result.getReader())
 | |
| 				: CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().createWithContext(result.getReader());
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static CommandBuildContext createValidationContext(HolderLookup.Provider provider) {
 | |
| 		return new CommandBuildContext() {
 | |
| 			@Override
 | |
| 			public FeatureFlagSet enabledFeatures() {
 | |
| 				return FeatureFlags.REGISTRY.allFlags();
 | |
| 			}
 | |
| 
 | |
| 			@Override
 | |
| 			public Stream<ResourceKey<? extends Registry<?>>> listRegistryKeys() {
 | |
| 				return provider.listRegistryKeys();
 | |
| 			}
 | |
| 
 | |
| 			@Override
 | |
| 			public <T> Optional<HolderLookup.RegistryLookup<T>> lookup(ResourceKey<? extends Registry<? extends T>> registryKey) {
 | |
| 				return provider.lookup(registryKey).map(this::createLookup);
 | |
| 			}
 | |
| 
 | |
| 			private <T> HolderLookup.RegistryLookup.Delegate<T> createLookup(HolderLookup.RegistryLookup<T> registryLookup) {
 | |
| 				return new HolderLookup.RegistryLookup.Delegate<T>() {
 | |
| 					@Override
 | |
| 					public HolderLookup.RegistryLookup<T> parent() {
 | |
| 						return registryLookup;
 | |
| 					}
 | |
| 
 | |
| 					@Override
 | |
| 					public Optional<HolderSet.Named<T>> get(TagKey<T> tagKey) {
 | |
| 						return Optional.of(this.getOrThrow(tagKey));
 | |
| 					}
 | |
| 
 | |
| 					@Override
 | |
| 					public HolderSet.Named<T> getOrThrow(TagKey<T> tagKey) {
 | |
| 						Optional<HolderSet.Named<T>> optional = this.parent().get(tagKey);
 | |
| 						return (HolderSet.Named<T>)optional.orElseGet(() -> HolderSet.emptyNamed(this.parent(), tagKey));
 | |
| 					}
 | |
| 				};
 | |
| 			}
 | |
| 		};
 | |
| 	}
 | |
| 
 | |
| 	public static void validate() {
 | |
| 		CommandBuildContext commandBuildContext = createValidationContext(VanillaRegistries.createLookup());
 | |
| 		CommandDispatcher<CommandSourceStack> commandDispatcher = new Commands(Commands.CommandSelection.ALL, commandBuildContext).getDispatcher();
 | |
| 		RootCommandNode<CommandSourceStack> rootCommandNode = commandDispatcher.getRoot();
 | |
| 		commandDispatcher.findAmbiguities(
 | |
| 			(commandNode, commandNode2, commandNode3, collection) -> LOGGER.warn(
 | |
| 				"Ambiguity between arguments {} and {} with inputs: {}", commandDispatcher.getPath(commandNode2), commandDispatcher.getPath(commandNode3), collection
 | |
| 			)
 | |
| 		);
 | |
| 		Set<ArgumentType<?>> set = ArgumentUtils.findUsedArgumentTypes(rootCommandNode);
 | |
| 		Set<ArgumentType<?>> set2 = (Set<ArgumentType<?>>)set.stream()
 | |
| 			.filter(argumentType -> !ArgumentTypeInfos.isClassRecognized(argumentType.getClass()))
 | |
| 			.collect(Collectors.toSet());
 | |
| 		if (!set2.isEmpty()) {
 | |
| 			LOGGER.warn(
 | |
| 				"Missing type registration for following arguments:\n {}", set2.stream().map(argumentType -> "\t" + argumentType).collect(Collectors.joining(",\n"))
 | |
| 			);
 | |
| 			throw new IllegalStateException("Unregistered argument types");
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static <T extends PermissionSource> PermissionCheck<T> hasPermission(int level) {
 | |
| 		return new PermissionSource.Check<>(level);
 | |
| 	}
 | |
| 
 | |
| 	public static enum CommandSelection {
 | |
| 		ALL(true, true),
 | |
| 		DEDICATED(false, true),
 | |
| 		INTEGRATED(true, false);
 | |
| 
 | |
| 		final boolean includeIntegrated;
 | |
| 		final boolean includeDedicated;
 | |
| 
 | |
| 		private CommandSelection(final boolean includeIntegrated, final boolean includeDedicated) {
 | |
| 			this.includeIntegrated = includeIntegrated;
 | |
| 			this.includeDedicated = includeDedicated;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@FunctionalInterface
 | |
| 	public interface ParseFunction {
 | |
| 		void parse(StringReader stringReader) throws CommandSyntaxException;
 | |
| 	}
 | |
| }
 |