diff --git a/Source/DiabloUI/diabloui.cpp b/Source/DiabloUI/diabloui.cpp index 2c0cb0447..da277396c 100644 --- a/Source/DiabloUI/diabloui.cpp +++ b/Source/DiabloUI/diabloui.cpp @@ -634,12 +634,10 @@ bool UiValidPlayerName(string_view name) if (name.find_first_of(",<>%&\\\"?*#/: ") != name.npos) return false; - constexpr auto isAsciiControlCharacter = [](char character) -> bool { - return (character >= 0x00 && character < 0x20) || character == 0x7F; - }; - for (char letter : name) - if (isAsciiControlCharacter(letter) || !IsLeadUtf8CodeUnit(letter)) - return false; + // Only basic latin alphabet is supported for multiplayer characters to avoid rendering issues for players who do + // not have fonts.mpq installed + if (!std::all_of(name.begin(), name.end(), IsBasicLatin)) + return false; string_view bannedNames[] = { "gvdl", diff --git a/Source/utils/utf8.hpp b/Source/utils/utf8.hpp index 399983b7f..9e6ffc35f 100644 --- a/Source/utils/utf8.hpp +++ b/Source/utils/utf8.hpp @@ -43,6 +43,16 @@ constexpr bool IsLeadUtf8CodeUnit(char x) return (x >= '\x00' && x <= '\x7F') || (x >= '\xC2' && x <= '\xF4'); } +/** + * Returns true if the character is part of the Basic Latin set. + * + * This includes ASCII punctuation, symbols, math operators, digits, and both uppercase/lowercase latin alphabets + */ +constexpr bool IsBasicLatin(char x) +{ + return x >= '\x20' && x <= '\x7E'; +} + /** * Returns true if this is a trailing byte in a UTF-8 code point encoding. * diff --git a/test/utf8_test.cpp b/test/utf8_test.cpp index e618e6576..555d92a75 100644 --- a/test/utf8_test.cpp +++ b/test/utf8_test.cpp @@ -67,5 +67,22 @@ TEST(Utf8CodeUnits, InvalidCodePoints) } } +TEST(Utf8CodeUnits, BasicLatin) +{ + for (char x = '\x00'; x < '\x20'; x++) { + EXPECT_FALSE(IsBasicLatin(x)) << "ASCII Control characters are not Basic Latin symbols"; + } + + for (char x = '\x20'; x <= '\x7E'; x++) { + EXPECT_TRUE(IsBasicLatin(x)) << "Basic Latin symbols are denoted by the range 0x20 to 0x7E inclusive"; + } + + EXPECT_FALSE(IsBasicLatin('\x7F')) << "ASCII Control character DEL is not a Basic Latin symbol"; + + for (char x = '\x80'; x >= '\x80' && x <= '\xFF'; x++) { + EXPECT_FALSE(IsBasicLatin(x)) << "Multibyte Utf8 code units are not Basic Latin symbols"; + } +} + } // namespace } // namespace devilution