Skip to content

Implementation details

Jorel Ali edited this page Jun 15, 2023 · 1 revision

A page outlining various implementations and why they were implemented that way. These are here to ensure code isn't too drowned out with "excessively long comments"

ChatComponentArgument raw arguments

To access the raw (string) text of an argument, the CommandAPI uses the CommandContext which contains a map of parsed arguments and the command input. The command input is the whole command sent to be executed, without the leading / character. The (private) parsed argument map is a mapping of node names to ParsedArgument objects which contain the range (a StringRange where the start is the first 'position' of the argument in the command input and the end is the last 'position' of the argument in the command input) and the result.

For example if we have the command /mycommand myargument:

  00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19
/  m  y  c  o  m  m  a  n  d     m  y  a  r  g  u  m  e  n  t

The CommandContext input is 20 characters long. The ParsedArgument for myargument has a start at 10 and an end at 19.

When parsing a ChatComponent argument, the net.minecraft.commands.arguments.ComponentArgument#parse method is called. This method calls net.minecraft.network.chat.Component.Serializer.fromJson. In this method, the parsing StringReader's cursor is set to the current cursor position plus the position of the JsonReader, which is (the reader's position - the reader's line starting position + 1). This + 1 at the end adds 1 to the end of the StringReader, which pushes the reader's position beyond the contents of the actual argument. In the example command above, this sets the ParsedArgument's end position to 20.

The StringReader is then turned into a StringRange (via ParsedArgument#<init>) starting from the start of the argument to the argument's cursor's position. This generates a ParsedArgument where the "end" of the argument is beyond the argument.

This causes parsedArgument.getRange().get(cmdCtx.getInput()) to throw a StringIndexOutOfBoundsException.