package net.minecraft.command.type.custom.nbt; import java.util.ArrayList; import java.util.HashSet; import java.util.Set; import java.util.regex.Matcher; import org.apache.commons.collections4.trie.PatriciaTrie; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.command.ParsingUtilities; import net.minecraft.command.SyntaxErrorException; import net.minecraft.command.arg.CommandArg; import net.minecraft.command.parser.Parser; import net.minecraft.command.type.IExParse; import net.minecraft.command.type.custom.nbt.NBTDescriptor.Compound; import net.minecraft.command.type.custom.nbt.NBTUtilities.NBTData; import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; public class ParserNBTCompound { private final Compound descriptor; public ParserNBTCompound(final Compound descriptor) { this.descriptor = descriptor; } public static class CompoundData extends NBTData { public String name = null; public final PatriciaTrie<NBTBase> primitiveData = new PatriciaTrie<>(); public final ArrayList<Pair<String, CommandArg<NBTBase>>> data = new ArrayList<>(); @Override public void put(final NBTBase data) { this.primitiveData.put(this.name, data); } @Override public void add(final CommandArg<NBTBase> data) { this.data.add(new ImmutablePair<>(this.name, data)); } public Set<String> keySet() { final Set<String> keySet = new HashSet<>(); keySet.addAll(this.primitiveData.keySet()); for (final Pair<String, ?> item : this.data) keySet.add(item.getLeft()); return keySet; } } public void parse(final Parser parser, final NBTData parserData) throws SyntaxErrorException { ParsingUtilities.terminateCompletion(parser); final CompoundData data = new CompoundData(); this.parseItems(parser, data); if (data.data.isEmpty()) parserData.put(new NBTTagCompound(data.primitiveData)); else parserData.add(createNBTCompound(data)); } public static final CommandArg<NBTBase> createNBTCompound(final CompoundData data) { final ArrayList<Pair<String, CommandArg<NBTBase>>> dynamicData = data.data; dynamicData.trimToSize(); return new CommandArg<NBTBase>() { final NBTTagCompound compound = new NBTTagCompound(data.primitiveData); @Override public NBTTagCompound eval(final ICommandSender sender) throws CommandException { for (final Pair<String, CommandArg<NBTBase>> tag : dynamicData) this.compound.setTag(tag.getKey(), tag.getValue().eval(sender)); return this.compound; } }; } public void parseItems(final Parser parser, final CompoundData data) throws SyntaxErrorException { final Matcher m = parser.getMatcher(ParsingUtilities.listEndMatcher); final IExParse<Void, CompoundData> pair = this.descriptor.getPair(); while (true) { if (parser.findInc(m)) // Because {Name:Value,} is valid... (or at least the output of NBTTagCompound.toString) { if ("}".equals(m.group(1))) return; throw parser.SEE("Unexpected '" + m.group(1) + "' "); } pair.parse(parser, data); if (!parser.findInc(m)) throw parser.SEE("No delimiter found while parsing tag compound "); if ("}".equals(m.group(1))) return; if ("]".equals(m.group(1))) throw parser.SEE("Unexpected ']' "); } } }