diff --git a/bukkit/loader/src/main/resources/translations/en.yml b/bukkit/loader/src/main/resources/translations/en.yml index 06b1acd9f..28cf30a1f 100644 --- a/bukkit/loader/src/main/resources/translations/en.yml +++ b/bukkit/loader/src/main/resources/translations/en.yml @@ -80,7 +80,7 @@ warning.config.image.invalid_font_chars: "Issue found in file - warning.config.image.missing_char: "Issue found in file - The image '' is missing the required 'char' argument." warning.config.image.codepoint_conflict: "Issue found in file - The image '' is using a character '()' in font that has been used by another image ''." warning.config.image.invalid_codepoint_grid: "Issue found in file - Image '' has an invalid 'chars' codepoint grid." -warning.config.image.invalid_char: "Issue found in file - The image '' has a 'char' argument is invalid. Please do not write a character that contains two Unicode characters such as '⁉️'." +warning.config.image.invalid_char: "Issue found in file - Image '' has a char parameter containing combining characters, which may result in image splitting." warning.config.image.file_not_found: "Issue found in file - PNG file '' not found for image ''." warning.config.image.invalid_hex_value: "Issue found in file - The image '' is using a unicode character '' that is not a valid hexadecimal (radix 16) value." warning.config.recipe.duplicate: "Issue found in file - Duplicated recipe ''. Please check if there is the same configuration in other files." diff --git a/bukkit/loader/src/main/resources/translations/zh_cn.yml b/bukkit/loader/src/main/resources/translations/zh_cn.yml index c1d7f67a8..dff59914a 100644 --- a/bukkit/loader/src/main/resources/translations/zh_cn.yml +++ b/bukkit/loader/src/main/resources/translations/zh_cn.yml @@ -80,7 +80,7 @@ warning.config.image.invalid_font_chars: "在文件 发现问题 warning.config.image.missing_char: "在文件 发现问题 - 图片 '' 缺少必需的 'char' 参数" warning.config.image.codepoint_conflict: "在文件 发现问题 - 图片 '' 在字体 中使用的字符 '()' 已被其他图片 '' 占用" warning.config.image.invalid_codepoint_grid: "在文件 发现问题 - 图片 '' 的 'chars' 码位网格无效" -warning.config.image.invalid_char: "在文件 发现问题 - 图片 '' 的 'char' 参数无效 请不要写一个包含两个 Unicode 的字符例如 '⁉️'" +warning.config.image.invalid_char: "在文件 发现问题 - 图片 '' 的 'char' 参数包含组合字符可能导致图片分裂" warning.config.image.file_not_found: "在文件 发现问题 - 图片 '' 的 PNG 文件 '' 未找到" warning.config.image.invalid_hex_value: "在文件 发现问题 - 图片 '' 使用的 Unicode 字符 '' 不是有效的十六进制值" warning.config.recipe.duplicate: "在文件 发现问题 - 重复的配方 '' 请检查其他文件中是否存在相同配置" diff --git a/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java b/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java index 5dc6a1986..fd0c030a0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/font/AbstractFontManager.java @@ -462,7 +462,18 @@ public abstract class AbstractFontManager implements FontManager { if (character.length() == 1) { chars = List.of(character.toCharArray()); } else { - chars = List.of(CharacterUtils.decodeUnicodeToChars(character)); + if (character.startsWith("\\u")) { + chars = List.of(CharacterUtils.decodeUnicodeToChars(character)); + } else { + if (CharacterUtils.containsCombinedCharacter(character)) { + TranslationManager.instance().log("warning.config.image.invalid_char", path.toString(), id.toString()); + } + StringBuilder stringBuilder = new StringBuilder(); + for (char c : character.toCharArray()) { + stringBuilder.append(String.format("\\u%04x", (int) c)); + } + chars = List.of(CharacterUtils.decodeUnicodeToChars(stringBuilder.toString())); + } } } } @@ -482,7 +493,7 @@ public abstract class AbstractFontManager implements FontManager { } } if (codepoints.length == 0) { - throw new LocalizedResourceConfigException("warning.config.image.invalid_char", path, id); + throw new LocalizedResourceConfigException("warning.config.image.missing_char", path, id); } codepointGrid[i] = codepoints; if (size == -1) size = codepoints.length; diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/CharacterUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/CharacterUtils.java index 2d8693728..940274bba 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/CharacterUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/CharacterUtils.java @@ -2,6 +2,7 @@ package net.momirealms.craftengine.core.util; import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException; +import java.util.regex.Pattern; import java.util.stream.IntStream; public class CharacterUtils { @@ -72,4 +73,27 @@ public class CharacterUtils { } return builder.toString(); } + + public static boolean containsCombinedCharacter(String input) { + if (input == null || input.isEmpty() || input.length() == 1) return false; + for (int i = 0; i < input.length();) { + int codePoint = input.codePointAt(i); + i += Character.charCount(codePoint); + int type = Character.getType(codePoint); + if (type == Character.NON_SPACING_MARK || + type == Character.ENCLOSING_MARK || + type == Character.COMBINING_SPACING_MARK || + type == Character.FORMAT || + type == Character.CONTROL || + type == Character.SURROGATE || + type == Character.PRIVATE_USE || + Pattern.compile("[\\p{Mn}\\p{Me}\\p{Mc}\\p{Cf}]").matcher(new String(Character.toChars(codePoint))).find() + ) return true; + if (i < input.length()) { + int nextCodePoint = input.codePointAt(i); + if (Character.isSurrogatePair(Character.toChars(codePoint)[0], Character.toChars(nextCodePoint)[0])) return true; + } + } + return false; + } }