package net.minecraft.command;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
import net.minecraft.command.arg.ArgWrapper;
import net.minecraft.command.arg.CommandArg;
import net.minecraft.command.arg.CompositeString;
import net.minecraft.command.arg.PrimitiveParameter;
import net.minecraft.command.arg.TypedWrapper;
import net.minecraft.command.arg.TypedWrapper.Getter;
import net.minecraft.command.collections.TypeIDs;
import net.minecraft.command.parser.CompletionParser;
import net.minecraft.command.parser.Context;
import net.minecraft.command.parser.MatcherRegistry;
import net.minecraft.command.parser.Parser;
import net.minecraft.command.type.IParse;
import net.minecraft.command.type.custom.ParserName;
import net.minecraft.command.type.management.CConvertable;
import net.minecraft.command.type.management.Converter;
import net.minecraft.command.type.management.SConverter;
import net.minecraft.command.type.management.TypeID;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IChatComponent;
public final class ParsingUtilities
{
public static final MatcherRegistry aKeyMatcher = new MatcherRegistry("\\G\\s*+([\\w-]++)\\s*+\\=");
public static final MatcherRegistry listEndMatcher = new MatcherRegistry("\\G\\s*+([,\\]}])");
public static final MatcherRegistry nameMatcher = new MatcherRegistry("\\G[\\w-]++");
public static final MatcherRegistry keyMatcher = new MatcherRegistry("\\G\\s*+([\\w-]++)");
public static final MatcherRegistry endingMatcher = new MatcherRegistry("\\G(\\s*+)([,;)\\]]|\\z)");
public static final MatcherRegistry endingMatcherCompletion = new MatcherRegistry("\\G(\\s*+)([,;)\\]])");
public static final MatcherRegistry idMatcher = new MatcherRegistry("\\G\\s*+([/@])");
public static final MatcherRegistry oParenthMatcher = new MatcherRegistry("\\G\\s*+\\(");
public static final MatcherRegistry generalMatcher = new MatcherRegistry("\\G\\s*+([@\\$])");
public static final MatcherRegistry spaceMatcher = new MatcherRegistry("\\G\\s");
public static final MatcherRegistry stringMatcher = new MatcherRegistry("\\G\\s*+([\\w\\.:-]++)");
public static final MatcherRegistry quoteMatcher = new MatcherRegistry("\\G\\s*+\"");
public final static MatcherRegistry baseMatcher = new MatcherRegistry("\\G[^\\[\\s]*+(?:(\\[)|(?=\\s|\\z))");
public final static MatcherRegistry stackedMatcher = new MatcherRegistry("\\G[^\\[\\]]*+(\\[|\\])");
public static final MatcherRegistry whitespaceMatcher = new MatcherRegistry("\\G\\s*+");
private ParsingUtilities()
{
}
public static <R> R generalParse(final Parser parser, final CConvertable<?, R> target, final Matcher m) throws SyntaxErrorException
{
if (!parser.findInc(m))
return null;
terminateCompletion(parser);
return "@".equals(m.group(1)) ? target.selectorParser.parse(parser) : target.labelParser.parse(parser);
}
public static Entity entiyFromIdentifier(final String identifier)
{
final MinecraftServer server = MinecraftServer.getServer();
Entity ret = server.getConfigurationManager().getPlayerByUsername(identifier);
if (ret != null)
return ret;
try
{
final UUID uuid = UUID.fromString(identifier);
ret = server.getEntityFromUuid(uuid);
if (ret != null)
return ret;
// getPlayerFromUuid
return server.getConfigurationManager().func_177451_a(uuid);
} catch (final IllegalArgumentException ex)
{
return null;
}
}
public static IChatComponent join(final List<IChatComponent> toJoin)
{
final ChatComponentText ret = new ChatComponentText("");
for (int i = 0; i < toJoin.size(); ++i)
{
if (i > 0)
if (i == toJoin.size() - 1)
ret.appendText(" and ");
else if (i > 0)
ret.appendText(", ");
ret.appendSibling(toJoin.get(i));
}
return ret;
}
public static String joinNiceString(final Object... elements)
{
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < elements.length; ++i)
{
final String item = elements[i].toString();
if (i > 0)
if (i == elements.length - 1)
sb.append(" and ");
else
sb.append(", ");
sb.append(item);
}
return sb.toString();
}
public static String joinNiceString(final Collection<?> strings)
{
return joinNiceString(strings.toArray());
}
public static String getEntityIdentifier(final Entity entity)
{
return entity instanceof EntityPlayerMP ? entity.getName() : entity.getUniqueID().toString();
}
/**
* Returns the given ICommandSender as a EntityPlayer or throw an exception.
*/
public static EntityPlayerMP getCommandSenderAsPlayer(final ICommandSender sender) throws PlayerNotFoundException
{
if (sender.getCommandSenderEntity() instanceof EntityPlayerMP)
return (EntityPlayerMP) sender.getCommandSenderEntity();
throw new PlayerNotFoundException("You must specify which player you wish to perform this action on.");
}
/**
* Note: Does not call generalParse
*/
public static <T> CommandArg<T> parseString(final Parser parser, final Matcher stringMatcher, final Converter<String, T, ?> converter, final PrimitiveCallback<T> callback) throws SyntaxErrorException
{
if (parser.findInc(stringMatcher))
return callback.call(parser, stringMatcher.group(1));
if (parser.findInc(quoteMatcher))
return parseQuotedString(parser, converter, callback);
return null;
}
public static <T> ArgWrapper<T> parseString(final Parser parser, final Context context, final TypeID<T> target, final Converter<String, T, ?> converter, final Matcher stringMatcher, final PrimitiveCallback<T> callback) throws SyntaxErrorException
{
final ArgWrapper<T> ret = context.generalParse(parser, target);
if (ret != null)
return ret;
final CommandArg<T> ret2 = parseString(parser, stringMatcher, converter, callback);
if (ret2 != null)
return target.wrap(ret2);
return null;
}
public static <T> ArgWrapper<T> parseString(final Parser parser, final Context context, final TypeID<T> target, final Converter<String, T, ?> converter, final MatcherRegistry m, final PrimitiveCallback<T> callback) throws SyntaxErrorException
{
return parseString(parser, context, target, converter, parser.getMatcher(m), callback);
}
public static ArgWrapper<String> parseString(final Parser parser, final Context context, final TypeID<String> target, final MatcherRegistry m, final PrimitiveCallback<String> callback) throws SyntaxErrorException
{
return parseString(parser, context, target, idStringConverter, parser.getMatcher(m), callback);
}
/**
* Note: Does not call generalParse
*/
public static String parseLiteralString(final Parser parser, final Matcher m, final String errorMessage) throws SyntaxErrorException
{
if (parser.findInc(m))
return m.group(1);
throw parser.SEE(errorMessage);
}
/**
* Note: Does not call generalParse
*/
public static String parseLiteralString(final Parser parser, final MatcherRegistry m, final String errorMessage) throws SyntaxErrorException
{
return parseLiteralString(parser, parser.getMatcher(m), errorMessage);
}
/**
* Note: Does not call generalParse
*/
public static String parseLiteralString(final Parser parser, final String errorMessage) throws SyntaxErrorException
{
return parseLiteralString(parser, parser.getMatcher(stringMatcher), errorMessage);
}
/**
* Requires the opening quotation mark to be parsed!
*/
public static String parseEscapedString(final Parser parser, final char endChar) throws SyntaxErrorException
{
final StringBuilder sb = new StringBuilder();
int partStart = parser.getIndex();
while (!parser.endReached())
{
final char nextChar = parser.consumeNextChar();
if (nextChar == endChar)
return sb.append(parser.toParse, partStart, parser.getIndex() - 1).toString();
if (nextChar == '\\')
{
if (parser.endReached())
throw parser.SEE("Unterminated string ");
sb.append(parser.toParse, partStart, parser.getIndex() - 1);
procCSequence(parser, parser.consumeNextChar(), sb);
partStart = parser.getIndex();
}
}
throw parser.SEE("Missing " + (endChar != '\'' ? "'" + endChar + "'" : "\"'\"") + " ");
}
/**
* Requires the opening quotation mark to be parsed!
*/
public static <T> CommandArg<T> parseQuotedString(final Parser parser, final Converter<String, T, ?> converter, final PrimitiveCallback<T> callback, final char endChar) throws SyntaxErrorException
{
StringBuilder sb = new StringBuilder();
final List<CommandArg<String>> parts = new ArrayList<>();
final IParse<ArgWrapper<String>> selectorParser = TypeIDs.String.selectorParser;
final IParse<ArgWrapper<String>> labelParser = TypeIDs.String.labelParser;
int partStart = parser.getIndex();
while (!parser.endReached())
{
final char nextChar = parser.consumeNextChar();
if (nextChar == endChar)
{
sb.append(parser.toParse, partStart, parser.getIndex() - 1);
if (parts.isEmpty())
return callback.call(parser, sb.toString());
if (sb.length() != 0)
parts.add(new PrimitiveParameter<>(sb.toString()));
return converter.transform(new CompositeString(parts));
}
if (nextChar == '\\')
{
if (parser.endReached())
throw parser.SEE("Unterminated string ");
sb.append(parser.toParse, partStart, parser.getIndex() - 1);
final char controlChar = parser.consumeNextChar();
switch (controlChar)
{
case '@':
sb = resetSB(parts, sb);
parts.add(selectorParser.parse(parser).arg());
break;
case '$':
sb = resetSB(parts, sb);
parts.add(labelParser.parse(parser).arg());
break;
case '!': // '\!' represents 'nothing', useful for stuff like "@s-text" => use "@s\!-text"
break;
default:
procCSequence(parser, controlChar, sb);
}
partStart = parser.getIndex();
}
}
throw parser.SEE("Missing " + (endChar != '\'' ? "'" + endChar + "'" : "\"'\"") + " ");
}
public static final void procCSequence(final Parser parser, final char controlChar, final StringBuilder sb) throws SyntaxErrorException
{
switch (controlChar)
{
case 'b':
sb.append('\b');
return;
case 'f':
sb.append('\f');
return;
case 'n':
sb.append('\n');
return;
case 'r':
sb.append('\r');
return;
case 't':
sb.append('\t');
return;
case 'u':
if (parser.getIndex() + 4 > parser.len)
throw parser.SEE("Unterminated escape sequence: \\u" + parser.toParse.substring(parser.getIndex()) + " ");
char result = 0;
for (int i = 1; i <= 4; ++i)
{
final char c = parser.consumeNextChar();
result = (char) (result << 4);
if ((c >= '0') && (c <= '9'))
result = (char) (result + c - '0');
else if ((c >= 'a') && (c <= 'f'))
result = (char) (result + c - 'a' + 10);
else if ((c >= 'A') && (c <= 'F'))
result = (char) (result + c - 'A' + 10);
else
throw parser.SEE("Invalid escape sequence: \\u" + parser.toParse.substring(parser.getIndex() - i, parser.getIndex() - i + 4) + " ");
}
sb.append(result);
return;
default:
sb.append(controlChar);
}
}
/**
* Requires the opening quotation mark to be parsed!
*/
public static <T> CommandArg<T> parseQuotedString(final Parser parser, final Converter<String, T, ?> converter, final PrimitiveCallback<T> callback) throws SyntaxErrorException
{
return parseQuotedString(parser, converter, callback, '"');
}
/**
* Requires the opening quotation mark to be parsed!
*/
public static CommandArg<String> parseQuotedString(final Parser parser, final PrimitiveCallback<String> callback) throws SyntaxErrorException
{
return parseQuotedString(parser, idStringConverter, callback);
}
/**
* Requires the opening quotation mark to be parsed!
*/
public static CommandArg<String> parseQuotedString(final Parser parser) throws SyntaxErrorException
{
return parseQuotedString(parser, ParserName.callback);
}
/**
* Requires the opening quotation mark to be parsed!
*/
public static CommandArg<String> parseQuotedString(final Parser parser, final PrimitiveCallback<String> callback, final char endChar) throws SyntaxErrorException
{
return parseQuotedString(parser, idStringConverter, callback, endChar);
}
/**
* Requires the opening quotation mark to be parsed!
*/
public static CommandArg<String> parseQuotedString(final Parser parser, final char endChar) throws SyntaxErrorException
{
return parseQuotedString(parser, ParserName.callback, endChar);
}
public static interface PrimitiveCallback<T>
{
public CommandArg<T> call(final Parser parser, final String s) throws SyntaxErrorException;
}
public static final SConverter<String, String> idStringConverter = new SConverter<String, String>()
{
@Override
public String convert(final String toConvert) throws SyntaxErrorException
{
return toConvert;
}
@Override
public CommandArg<String> transform(final CommandArg<String> toTransform)
{
return toTransform;
};
};
public static final <T> PrimitiveCallback<T> callbackImmediate(final Converter<String, T, ? super SyntaxErrorException> converter)
{
return new PrimitiveCallback<T>()
{
@Override
public CommandArg<T> call(final Parser parser, final String s) throws SyntaxErrorException
{
try
{
return new PrimitiveParameter<>(converter.convert(s));
} catch (final SyntaxErrorException e)
{
throw e;
} catch (final CommandException e)
{
throw parser.SEE(e.getMessage(), false, e.getErrorOjbects());
}
}
};
}
public static final <T> PrimitiveCallback<T> callbackNonImmediate(final Converter<String, T, ?> converter)
{
return new PrimitiveCallback<T>()
{
@Override
public CommandArg<T> call(final Parser parser, final String s) throws SyntaxErrorException
{
return converter.transform(new PrimitiveParameter<>(s));
}
};
}
private static StringBuilder resetSB(final List<CommandArg<String>> parts, final StringBuilder sb)
{
if (sb.length() != 0)
{
parts.add(new PrimitiveParameter<>(sb.toString()));
return new StringBuilder();
}
return sb;
}
public static boolean isTrue(final String toCheck)
{
return "true".equalsIgnoreCase(toCheck) || "t".equalsIgnoreCase(toCheck) || "1".equalsIgnoreCase(toCheck);
}
public static boolean isFalse(final String toCheck)
{
return "false".equalsIgnoreCase(toCheck) || "f".equalsIgnoreCase(toCheck) || "0".equalsIgnoreCase(toCheck);
}
public static final String parseLazyString(final Parser parser, final MatcherRegistry baseMatcher) throws SyntaxErrorException
{
final int startIndex = parser.getIndex();
int level = 0;
final Matcher bm = parser.getMatcher(baseMatcher);
final Matcher sm = parser.getMatcher(ParsingUtilities.stackedMatcher);
parser.findInc(whitespaceMatcher);
while (true)
if (level == 0)
{
if (!parser.findInc(bm))
throw parser.SEE("Missing ']', '}' or ',' ");
if (bm.group(1) == null)
return parser.toParse.substring(startIndex, parser.getIndex()).trim();
level = 1;
}
else
{
if (!parser.findInc(sm))
throw parser.SEE("Missing ']' ");
if ("[".equals(sm.group(1)))
++level;
else
--level;
}
}
public static <T> Getter<T> get(final TypeID<T> type, final TypedWrapper<?> wrapper)
{
if (wrapper == null)
return null;
return wrapper.get(type);
}
@SafeVarargs
public static final <T> Set<T> setOrNull(final T... elements)
{
return elements == null || elements.length == 0 ? null : elements.length == 1 ? Collections.singleton(elements[0]) : new HashSet<>(Arrays.asList(elements));
}
public static void proposeCompletion(final Parser parser)
{
parser.supplyHint(CompletionParser.propose);
}
public static void terminateCompletion(final Parser parser)
{
parser.supplyHint(CompletionParser.terminate);
}
public static IChatComponent location(final Parser parser)
{
final String toParse = parser.toParse;
final int index = parser.getIndex();
final int start = index > 19 ? index - 20 : 0;
final int end = index < toParse.length() - 20 ? index + 19 : toParse.length();
final IChatComponent prefix = new ChatComponentText((start > 0 ? "�" : "") + toParse.substring(start, index));
final IChatComponent cursor = new ChatComponentText("|");
final IChatComponent postfix = new ChatComponentText(toParse.substring(index, end) + (end < toParse.length() ? "�" : ""));
prefix.getChatStyle().setColor(EnumChatFormatting.GRAY);
cursor.getChatStyle().setColor(EnumChatFormatting.RED);
postfix.getChatStyle().setColor(EnumChatFormatting.GRAY);
final IChatComponent message = prefix.appendSibling(cursor).appendSibling(postfix);
return message;
}
}