package net.minecraft.command.construction; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import net.minecraft.command.SyntaxErrorException; import net.minecraft.command.construction.CommandDescriptorDefault.CParserData; import net.minecraft.command.construction.ICommandConstructor.CPU; import net.minecraft.command.parser.Parser; import net.minecraft.command.type.IDataType; import net.minecraft.command.type.IExParse; import net.minecraft.command.type.base.ExCustomParse; public class CommandConstructor implements CPU { public final Set<CommandProtoDescriptor> baseCommands; public final Set<CommandProtoDescriptor> ends; public CommandConstructor(final Set<CommandProtoDescriptor> baseCommands, final Set<CommandProtoDescriptor> ends) { this.baseCommands = baseCommands; this.ends = ends; } public CommandConstructor(final Set<CommandProtoDescriptor> baseCommands) { this.baseCommands = baseCommands; this.ends = new HashSet<>(); this.ends.addAll(baseCommands); } public CommandConstructor(final CommandProtoDescriptor baseCommand) { this.baseCommands = Collections.singleton(baseCommand); this.ends = new HashSet<>(); this.ends.add(baseCommand); } @Override public final CommandConstructor then(final IExParse<Void, ? super CParserData> arg) { CommandProtoDescriptor newEnd = null; final Iterator<CommandProtoDescriptor> it = this.ends.iterator(); while (it.hasNext()) { final CommandProtoDescriptor end = it.next(); if (end.subCommands.isEmpty()) end.args.add(arg); else { if (newEnd == null) { newEnd = new CommandProtoDescriptor.NoConstructable("", Collections.<String> emptyList(), null); newEnd.args.add(arg); } end.subCommands.add(newEnd); end.useEmptyConstructable = true; it.remove(); } } if (newEnd != null) this.ends.add(newEnd); return this; } @Override public final CommandConstructor then(final IDataType<?> arg) { return this.then(wrap(arg)); } private static final IExParse<Void, ? super CParserData> wrap(final IDataType<?> arg) { return new ExCustomParse<Void, CParserData>() { @Override public Void iParse(final Parser parser, final CParserData parserData) throws SyntaxErrorException { parserData.add(arg.parse(parser)); return null; } }; } @Override public final CommandConstructor sub(final ICommandConstructor... subCommands) { for (final CommandProtoDescriptor end : this.ends) { end.useEmptyConstructable = true; for (final ICommandConstructor subCommand : subCommands) end.subCommands.addAll(subCommand.baseCommands()); } this.ends.clear(); for (final ICommandConstructor subCommand : subCommands) this.ends.addAll(subCommand.ends()); return this; } /** * Single optional argument. If {@code arg} is missing while parsing, the command is finished (the whole subcommand-tree is dependent on {@code arg}) */ @Override public final CommandConstructor optional(final IExParse<Void, ? super CParserData> arg) { this.optional(arg, new CommandProtoDescriptor.NoConstructable("", Collections.<String> emptyList(), null)); return this; } @Override public final CommandConstructor optional(final IDataType<?> arg) { return this.optional(wrap(arg)); } /** * Single optional argument. If {@code arg} is missing while parsing, the command is finished (the whole subcommand-tree is dependent on this {@code arg}) * * @param constructable * Used to construct the command that is terminated exactly after {@code arg} */ @Override public final CommandConstructor optional(final IExParse<Void, ? super CParserData> arg, final CommandConstructable constructable) { this.optional(arg, new CommandProtoDescriptor.Constructable("", Collections.<String> emptyList(), constructable, null)); return this; } @Override public final CommandConstructor optional(final IDataType<?> arg, final CommandConstructable constructable) { return this.optional(wrap(arg), constructable); } private final void optional(final IExParse<Void, ? super CParserData> arg, final CommandProtoDescriptor descriptor) { descriptor.args.add(arg); for (final CommandProtoDescriptor end : this.ends) end.subCommands.add(descriptor); this.ends.clear(); this.ends.add(descriptor); } /** * Multiple optional subCommands. Everything added after this call gets added to all subCommands and to {@code this} */ @Override public final CommandConstructor optional(final ICommandConstructor... commands) { for (final CommandProtoDescriptor end : this.ends) for (final ICommandConstructor command : commands) end.subCommands.addAll(command.baseCommands()); for (final ICommandConstructor command : commands) this.ends.addAll(command.ends()); return this; } @Override public final Set<CommandProtoDescriptor> baseCommands() { return this.baseCommands; } @Override public final Set<CommandProtoDescriptor> ends() { return this.ends; } @Override public final CommandConstructor sub(final C... subCommands) { return this.sub((ICommandConstructor[]) subCommands); } @Override public final CommandConstructor sub(final P... subCommands) { return this.sub((ICommandConstructor[]) subCommands); } @Override public CommandConstructor sub(final CP... subCommands) { return this.sub((ICommandConstructor[]) subCommands); } }