I've written a simple util-method in my spigot plugin to check if a message contains a valid minecraft colour code. A valid minecraft colour code consists of a &
followed by a hex digit: 0
to f
. Minecraft itself exchanges all &
by a §
, for reasons that would take too long to explain, it's not possible for the users to send messages to the server directly. Therefore &
is generally used as a replacement.
I now have to check at some point, if the message the user sent to the server is coloured, which is the reason this method exists. Here are some quick examples, how it does work:
string value - return value
"Simple String" - false
"Smith&Wesson" - false
"&4This would be red." - true
"%aGreen &2Darker Green &0 Darkest Green" - true
"&& Omega &&" - false
Here's my code. It does what it's supposed to do, but for some reason it still seems unneccesary clunky to me. Any improvement is welcome :)
public static boolean isMessageColoured(String message) {
char[] arr = message.toCharArray();
for (int i = 0; i < message.length() - 2; i++) {
if (arr[i] == '&' && "0123456789abcdef".contains(Character.toString(arr[i + 1]))) {
return true;
}
}
return false;
}
2 Answers 2
Welcome to Code Review.
- Your code returns false for the message "hello&9", because the method doesn't check the last character. Change the condition in the for-loop to
message.length() - 1
.
An alternative is to use a regular expression:
public static boolean isMessageColoured(String message) {
return message.matches(".*&[a-f0-9].*");
}
This regular expression matches at least one occurrence of &[a-f0-9]
in the message.
-
4\$\begingroup\$ I think OP is saying that writing a message that includes
&9
would mean every character after&9
would be displayed in the color that&9
represents, therefor ending a message with&9
wouldn't mean anything. \$\endgroup\$Jonny Henly– Jonny Henly2020年10月15日 09:40:10 +00:00Commented Oct 15, 2020 at 9:40 -
1\$\begingroup\$ Exactly as @JonnyHenly said - everything after a colour code is displayed colourful. The codes themselves are not visible in the displayed message. But thanks for the suggestion with the regex :D \$\endgroup\$monamona– monamona2020年10月15日 10:08:56 +00:00Commented Oct 15, 2020 at 10:08
-
\$\begingroup\$ But the message is not coloured, therefore the method shall return false :) \$\endgroup\$monamona– monamona2020年10月15日 17:57:34 +00:00Commented Oct 15, 2020 at 17:57
-
\$\begingroup\$ @monamona Then your method is wrong. It would return true for
&a
,&a&b
,&a &b
etc. \$\endgroup\$xehpuk– xehpuk2020年10月15日 18:29:40 +00:00Commented Oct 15, 2020 at 18:29 -
\$\begingroup\$ Those messages are actually considered to be coloured spaces ^^, and Indeed, combining two colour codes is also considered a valid message ^^ - also a coloured space ^^ \$\endgroup\$monamona– monamona2020年10月15日 18:48:32 +00:00Commented Oct 15, 2020 at 18:48
There is no need to convert String
to char[]
array. Individual characters are accessible via String.charAt
method.
There is also no need to explicitly spell out the hexadecimals. Consider Character.digit(message.charAt[i+1], 16) != -1
.
-
3\$\begingroup\$ Is there a typo? charAt[] vs. charAt() \$\endgroup\$slepic– slepic2020年10月15日 06:14:16 +00:00Commented Oct 15, 2020 at 6:14
-
\$\begingroup\$ Is
Character.digit(message.charAt(i + 1), 16) != -1
not bulky (a lot more going on than justCharacter.digit
)? The way I see it, you're expecting an ASCII why not just stick with thechar
array and bounds check the index after'&'
in the loop --char next = arr[i+1]; if(arr[i] == '&' && (('0' <= next && next <= '9') || ('a' <= next && next <= 'f'))
-- is there an upside or downside to doing it this way? \$\endgroup\$Jonny Henly– Jonny Henly2020年10月15日 09:32:09 +00:00Commented Oct 15, 2020 at 9:32