package com.supaham.commons.bukkit.text; import com.google.common.base.Preconditions; import org.bukkit.ChatColor; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.annotation.Nonnull; /** * Represents a class that transforms a {@link String} into a {@link FancyMessage}. Useful for * fixing multicolor lines. * * @since 0.2.4 */ public class SafeFancyMessage { private String message; private FancyMessage fancyMessage; private int currentIndex; private final Pattern INCREMENTAL_PATTERN = Pattern.compile( "(" + ChatColor.COLOR_CHAR + "[0-9a-fk-or])|(\\n)|(?:(https?://[^ ][^ ]*?)(?=[\\.\\?!,;:]?(?:[ \\n]|$)))", Pattern.CASE_INSENSITIVE ); /** * Converts a {@link String} to to {@link FancyMessage} with minecraft json-chat support. * * @param message message to convert * * @return fancy message of {@code message} */ public static FancyMessage from(@Nonnull String message) { Preconditions.checkNotNull(message, "message cannot be null."); FancyMessage fancyMessage = new FancyMessage(); new SafeFancyMessage(message, fancyMessage); return fancyMessage; } public SafeFancyMessage(String message, FancyMessage fancyMessage) { this.message = message; this.fancyMessage = fancyMessage; Matcher matcher = INCREMENTAL_PATTERN.matcher(message); String match; while (matcher.find()) { int group = 0; while ((match = matcher.group(++group)) == null) { } appendMessage(matcher.start(group)); switch (group) { case 1: // Color/format group ChatColor color = ChatColor.getByChar(match.charAt(1)); if (color.equals(ChatColor.RESET)) { fancyMessage.then(); } else if (color.isFormat()) { fancyMessage.then(); switch (color) { case BOLD: fancyMessage.style(ChatColor.BOLD); break; case ITALIC: fancyMessage.style(ChatColor.ITALIC); break; case STRIKETHROUGH: fancyMessage.style(ChatColor.STRIKETHROUGH); break; case UNDERLINE: fancyMessage.style(ChatColor.UNDERLINE); break; case MAGIC: fancyMessage.style(ChatColor.MAGIC); break; default: throw new UnsupportedOperationException("Unexpected ChatColor format " + color); } } else { fancyMessage.then().color(color); } break; case 2: // New line fancyMessage.then("\n"); break; case 3: // URL appendMessage(matcher.end(group)); fancyMessage.link(match); } currentIndex = matcher.end(group); } if (currentIndex < message.length()) { appendMessage(message.length()); } } private void appendMessage(int index) { if (index <= currentIndex) { return; } String message = this.message.substring(currentIndex, index); this.currentIndex = index; fancyMessage.append(message); } }