package com.alttd.chat.util; import com.alttd.chat.ChatAPI; import com.alttd.chat.config.Config; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.ComponentLike; import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.minimessage.MiniMessage; import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver; import net.kyori.adventure.text.minimessage.tag.standard.StandardTags; import net.luckperms.api.LuckPerms; import net.luckperms.api.model.group.Group; import net.luckperms.api.model.user.User; import net.luckperms.api.node.Node; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Utility { private static final List EMPTY_LIST = new ArrayList<>(); static final Pattern DEFAULT_URL_PATTERN = Pattern.compile("(https?://)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)"); private static MiniMessage miniMessage = null; public static String stringRegen = "\\{#[A-Fa-f0-9]{6}(<)?(>)?}"; public static HashMap colors; static { // this might be in minimessage already? colors = new HashMap<>(); colors.put("&0", ""); colors.put("&1", ""); colors.put("&2", ""); colors.put("&3", ""); colors.put("&4", ""); colors.put("&5", ""); colors.put("&6", ""); colors.put("&7", ""); colors.put("&8", ""); colors.put("&9", ""); colors.put("&a", ""); colors.put("&b", ""); colors.put("&c", ""); colors.put("&d", ""); colors.put("&e", ""); colors.put("&f", ""); } public static HashMap>> formattingPerms = new HashMap<>(); static { formattingPerms.put("chat.format.color", new Pair<>(StandardTags.color(), colors.values().stream().toList())); formattingPerms.put("chat.format.bold", new Pair<>(StandardTags.decorations(TextDecoration.BOLD), List.of("", ""))); formattingPerms.put("chat.format.italic", new Pair<>(StandardTags.decorations(TextDecoration.ITALIC), List.of("", ""))); formattingPerms.put("chat.format.underlined", new Pair<>(StandardTags.decorations(TextDecoration.UNDERLINED), List.of("", ""))); formattingPerms.put("chat.format.strikethrough", new Pair<>(StandardTags.decorations(TextDecoration.STRIKETHROUGH), List.of("", ""))); formattingPerms.put("chat.format.obfuscated", new Pair<>(StandardTags.decorations(TextDecoration.OBFUSCATED), List.of("", ""))); formattingPerms.put("chat.format.gradient", new Pair<>(StandardTags.gradient(), EMPTY_LIST)); formattingPerms.put("chat.format.font", new Pair<>(StandardTags.font(), EMPTY_LIST)); formattingPerms.put("chat.format.rainbow", new Pair<>(StandardTags.rainbow(), List.of(""))); formattingPerms.put("chat.format.hover", new Pair<>(StandardTags.hoverEvent(), EMPTY_LIST)); formattingPerms.put("chat.format.click", new Pair<>(StandardTags.clickEvent(), EMPTY_LIST)); formattingPerms.put("chat.format.transition", new Pair<>(StandardTags.transition(), EMPTY_LIST)); formattingPerms.put("chat.format.reset", new Pair<>(StandardTags.reset(), List.of("", ""))); formattingPerms.put("chat.format.newline", new Pair<>(StandardTags.newline(), List.of(""))); } public static String parseColors(String message) { if (message == null) { return ""; } // split string in sections and check those vs looping hashmap?:/ // think this is better, but will check numbers on this for (String key : colors.keySet()) { if (message.contains(key)) { message = message.replace(key, colors.get(key)); } } return message; } public static ComponentLike getPrefix(UUID uuid, boolean single) { StringBuilder prefix = new StringBuilder(); LuckPerms luckPerms = ChatAPI.get().getLuckPerms(); User user = luckPerms.getUserManager().getUser(uuid); List prefixGroups = Config.PREFIXGROUPS; if (user == null) { return Component.empty(); } if (!single) { Collection inheritedGroups = user.getInheritedGroups(user.getQueryOptions()); if (inheritedGroups.stream().anyMatch(group -> group.getName().equals("eventleader"))) { prefixGroups.remove("eventteam"); // hardcoded for now, new prefix system would load this from config } inheritedGroups.stream() .sorted(Comparator.comparingInt(o -> o.getWeight().orElse(0))) .forEach(group -> { if (prefixGroups.contains(group.getName())) { prefix.append(getGroupPrefix(group)); } }); } prefix.append(getUserPrefix(user)); return applyColor(prefix.toString()); } public static ComponentLike getStaffPrefix(UUID uuid) { StringBuilder prefix = new StringBuilder(); LuckPerms luckPerms = ChatAPI.get().getLuckPerms(); User user = luckPerms.getUserManager().getUser(uuid); if (user == null) { return Component.empty(); } if (user.getCachedData().getPermissionData().checkPermission("group." + Config.MINIMIUMSTAFFRANK).asBoolean()) { Group group = luckPerms.getGroupManager().getGroup(user.getPrimaryGroup()); if (group != null) { prefix.append(getGroupPrefix(group)); } // prefix.append(group.getCachedData().getMetaData().getPrefix()); } return applyColor(prefix.toString()); } public static String getUserPrefix(User user) { LuckPerms luckPerms = ChatAPI.get().getLuckPerms(); Group group = luckPerms.getGroupManager().getGroup(user.getPrimaryGroup()); if (group == null) { return ""; } String prefix = user.getCachedData().getMetaData().getPrefix(); if (prefix == null) { ALogger.warn("User " + user.getUsername() + " has no prefix set!"); return ""; } return ChatAPI.get().getPrefixes().get(group.getName()).replace("", prefix); } public static String getGroupPrefix(Group group) { String prefix = group.getCachedData().getMetaData().getPrefix(); if (prefix == null) { ALogger.warn("Group " + group.getName() + " has no prefix set!"); return ""; } return ChatAPI.get().getPrefixes().get(group.getName()).replace("", prefix); } public static String getDisplayName(UUID uuid, String playerName) { if (!playerName.isBlank()) { return playerName; } LuckPerms luckPerms = ChatAPI.get().getLuckPerms(); User user = luckPerms.getUserManager().getUser(uuid); if (user == null) { return ""; } return user.getUsername(); } public static void flipPermission(UUID uuid, String permission) { ChatAPI.get().getLuckPerms().getUserManager().modifyUser(uuid, user -> { // Add the permission user.data().add(Node.builder(permission) .value(!user.getCachedData().getPermissionData().checkPermission(permission).asBoolean()).build()); }); } public static boolean hasPermission(UUID uuid, String permission) { LuckPerms luckPerms = ChatAPI.get().getLuckPerms(); User user = luckPerms.getUserManager().getUser(uuid); if (user == null) { return false; } return user.getCachedData().getPermissionData().checkPermission(permission).asBoolean(); } public static ComponentLike applyColor(String message) { String hexColor1 = ""; String hexColor2; StringBuilder stringBuilder = new StringBuilder(); message = parseColors(message); boolean startsWithColor = false; boolean lastColorMatters = false; if (message.matches(".*" + stringRegen + ".*")) { String[] split = message.split(stringRegen); ArrayList list = new ArrayList<>(); int nextIndex = 0; if (message.indexOf("}") <= 11) { startsWithColor = true; list.add(message.substring(0, message.indexOf("}") + 1)); } for (String s : split) { nextIndex += s.length(); int tmp = message.indexOf("}", nextIndex); if (tmp < message.length() && tmp >= 0) { list.add(message.substring(nextIndex, tmp + 1)); nextIndex = tmp + 1; } } int i; boolean firstLoop = true; if (startsWithColor) { i = -1; } else { i = 0; stringBuilder.append(split[i]); } for (String s : list) { boolean lesser = s.contains("<"); boolean bigger = s.contains(">"); if (bigger && lesser) { hexColor2 = s.substring(1, s.length() - 3); } else if (bigger || lesser) { hexColor2 = s.substring(1, s.length() - 2); } else { hexColor2 = s.substring(1, s.length() - 1); } if (firstLoop) { lastColorMatters = bigger; hexColor1 = hexColor2; firstLoop = false; i++; continue; } if (lesser && lastColorMatters) { stringBuilder.append("").append(split[i]).append(""); } else { stringBuilder.append("<").append(hexColor1).append(">").append(split[i]); } hexColor1 = hexColor2; lastColorMatters = bigger; i++; } if (split.length > i) { stringBuilder.append("<").append(hexColor1).append(">").append(split[i]); } } return stringBuilder.isEmpty() ? Utility.parseMiniMessage(message) : Utility.parseMiniMessage(stringBuilder.toString()); } public static boolean checkNickBrightEnough(String nickname) { if (!nickname.matches(".*" + stringRegen + ".*")) { return true; } Pattern pattern = Pattern.compile(stringRegen); Matcher matcher = pattern.matcher(nickname); while (matcher.find()) { String hexColor = matcher.group(); if (!checkHexHighEnough(hexColor)) { return false; } } return true; } private static boolean checkHexHighEnough(String hexColor) { // Remove the leading "#" if present if (hexColor.startsWith("{")) { hexColor = hexColor.substring(1); } if (hexColor.startsWith("#")) { hexColor = hexColor.substring(1); } // Extract the color parts String redPart = hexColor.substring(0, 2); String greenPart = hexColor.substring(2, 4); String bluePart = hexColor.substring(4, 6); // Convert the color parts to integers int red = Integer.parseInt(redPart, 16); int green = Integer.parseInt(greenPart, 16); int blue = Integer.parseInt(bluePart, 16); // Check if any part is over 30 in hexadecimal return red > 0x30 || green > 0x30 || blue > 0x30; } public static String formatText(String message) { Matcher matcher = DEFAULT_URL_PATTERN.matcher(message); while (matcher.find()) { String url = matcher.group(); String urlFormat = Config.URLFORMAT; message = message.replace(url, urlFormat .replaceAll("", "" + url + "") .replaceAll("", formatUrl(url))); } return message; } private static String formatUrl(String url) { if (url.startsWith("http://") || url.startsWith("https://")) { return url; } return "https://" + url; } public static ComponentLike parseMiniMessage(String message) { return getMiniMessage().deserialize(message); } public static ComponentLike parseMiniMessage(String message, TagResolver placeholders) { if (placeholders == null) { return getMiniMessage().deserialize(message); } else { return getMiniMessage().deserialize(message, placeholders); } } public static ComponentLike parseMiniMessage(String message, TagResolver... placeholders) { if (placeholders == null) { return getMiniMessage().deserialize(message); } else { return getMiniMessage().deserialize(message, TagResolver.resolver(placeholders)); } } public static String stripTokens(String input) { return getMiniMessage().stripTags(input); } public static MiniMessage getMiniMessage() { if (miniMessage == null) { miniMessage = MiniMessage.miniMessage(); } return miniMessage; } public static String removeAllColors(String string) { for (String colorCodes : colors.keySet()) { string = string.replace(colorCodes, ""); } return string.replaceAll("\\{#[A-Fa-f0-9]{6}(<)?(>)?}", ""); } }