package com.forgeessentials.util.output; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.regex.Pattern; import net.minecraft.command.ICommandSender; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.server.MinecraftServer; import net.minecraft.util.ChatComponentText; import net.minecraft.util.ChatStyle; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.IChatComponent; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.util.FakePlayer; import com.forgeessentials.core.moduleLauncher.config.ConfigLoader.ConfigLoaderBase; import com.forgeessentials.util.output.LoggingHandler; public final class ChatOutputHandler extends ConfigLoaderBase { public static final char COLOR_FORMAT_CHARACTER = '\u00a7'; public static final String CONFIG_CAT = "Core.Output"; public static EnumChatFormatting chatErrorColor, chatWarningColor, chatConfirmationColor, chatNotificationColor; /* ------------------------------------------------------------ */ /** * Sends a chat message to the given command sender (usually a player) with the given text and no special formatting. * * @param recipient * The recipient of the chat message. * @param message * The message to send. */ public static void sendMessage(ICommandSender recipient, String message) { sendMessage(recipient, new ChatComponentText(message)); } /** * Sends a message to a {@link ICommandSender} and performs some security checks * * @param recipient * @param message */ public static void sendMessage(ICommandSender recipient, IChatComponent message) { if (recipient instanceof FakePlayer && ((EntityPlayerMP) recipient).playerNetServerHandler == null) LoggingHandler.felog.info(String.format("Fakeplayer %s: %s", recipient.getCommandSenderName(), message.getUnformattedText())); else recipient.addChatMessage(message); } /** * actually sends the color-formatted message to the sender * * @param recipient * CommandSender to chat to. * @param message * The message to be sent * @param color * Color of text to format */ public static void sendMessage(ICommandSender recipient, String message, EnumChatFormatting color) { message = formatColors(message); if (recipient instanceof EntityPlayer) { ChatComponentText component = new ChatComponentText(message); component.getChatStyle().setColor(color); sendMessage(recipient, component); } else sendMessage(recipient, stripFormatting(message)); } /** * Sends a message to all clients * * @param message * The message to send */ public static void broadcast(IChatComponent message) { MinecraftServer.getServer().getConfigurationManager().sendChatMsg(message); } /* ------------------------------------------------------------ */ public static IChatComponent confirmation(String message) { return setChatColor(new ChatComponentText(formatColors(message)), chatConfirmationColor); } public static IChatComponent notification(String message) { return setChatColor(new ChatComponentText(formatColors(message)), chatNotificationColor); } public static IChatComponent warning(String message) { return setChatColor(new ChatComponentText(formatColors(message)), chatWarningColor); } public static IChatComponent error(String message) { return setChatColor(new ChatComponentText(formatColors(message)), chatErrorColor); } /** * Utility method to set {@link IChatComponent} color * * @param message * @param color * @return message */ public static IChatComponent setChatColor(IChatComponent message, EnumChatFormatting color) { message.getChatStyle().setColor(color); return message; } /* ------------------------------------------------------------ */ /** * outputs an error message to the chat box of the given sender. * * @param sender * CommandSender to chat to. * @param msg * the message to be sent */ public static void chatError(ICommandSender sender, String msg) { sendMessage(sender, msg, chatErrorColor); } /** * outputs a confirmation message to the chat box of the given sender. * * @param sender * CommandSender to chat to. * @param msg * the message to be sent */ public static void chatConfirmation(ICommandSender sender, String msg) { sendMessage(sender, msg, chatConfirmationColor); } /** * outputs a warning message to the chat box of the given sender. * * @param sender * CommandSender to chat to. * @param msg * the message to be sent */ public static void chatWarning(ICommandSender sender, String msg) { sendMessage(sender, msg, chatWarningColor); } /** * outputs a notification message to the chat box of the given sender. * * @param sender * CommandSender to chat to. * @param msg */ public static void chatNotification(ICommandSender sender, String msg) { sendMessage(sender, msg, chatNotificationColor); } /* ------------------------------------------------------------ */ /** * Format color codes * * @param message * @return formatted message */ public static String formatColors(String message) { // TODO: Improve this to replace codes less aggressively char[] b = message.toCharArray(); for (int i = 0; i < b.length - 1; i++) { if (b[i] == '&' && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i + 1]) > -1) { b[i] = COLOR_FORMAT_CHARACTER; b[i + 1] = Character.toLowerCase(b[i + 1]); } } return new String(b); } public static final Pattern FORMAT_CODE_PATTERN; static { String codes = ""; for (EnumChatFormatting code : EnumChatFormatting.values()) codes += code.getFormattingCode(); FORMAT_CODE_PATTERN = Pattern.compile(COLOR_FORMAT_CHARACTER + "[" + codes + "]"); } /** * Strips any minecraft formatting codes * * @param message * @return */ public static String stripFormatting(String message) { return FORMAT_CODE_PATTERN.matcher(message).replaceAll(""); } /** * Apply a set of {@link EnumChatFormatting} to a {@link ChatStyle} * * @param chatStyle * @param formattings */ public static void applyFormatting(ChatStyle chatStyle, Collection<EnumChatFormatting> formattings) { for (EnumChatFormatting format : formattings) applyFormatting(chatStyle, format); } /** * Apply an {@link EnumChatFormatting} to a {@link ChatStyle} * * @param chatStyle * @param formatting */ public static void applyFormatting(ChatStyle chatStyle, EnumChatFormatting formatting) { switch (formatting) { case BOLD: chatStyle.setBold(true); break; case ITALIC: chatStyle.setItalic(true); break; case OBFUSCATED: chatStyle.setObfuscated(true); break; case STRIKETHROUGH: chatStyle.setStrikethrough(true); break; case UNDERLINE: chatStyle.setUnderlined(true); break; case RESET: break; default: chatStyle.setColor(formatting); break; } } /** * Take a string of chat format codes (without \u00a7) and return them as {@link EnumChatFormatting} collection * * @param textFormats * @return */ public static Collection<EnumChatFormatting> enumChatFormattings(String textFormats) { List<EnumChatFormatting> result = new ArrayList<EnumChatFormatting>(); for (int i = 0; i < textFormats.length(); i++) { char formatChar = textFormats.charAt(i); for (EnumChatFormatting format : EnumChatFormatting.values()) if (format.getFormattingCode() == formatChar) { result.add(format); break; } } return result; } /* ------------------------------------------------------------ */ public static final long SECOND = 1; public static final long MINUTE_SECONDS = 60 * SECOND; public static final long HOUR_SECONDS = 60 * MINUTE_SECONDS; public static final long DAY_SECONDS = 24 * HOUR_SECONDS; public static final long WEEK_SECONDS = 7 * DAY_SECONDS; /** * Gets a nice string with only needed elements. Max time is weeks * * @param time * @return Time in string format */ public static String formatTimeDurationReadable(long time, boolean showSeconds) { long weeks = time / WEEK_SECONDS; time -= WEEK_SECONDS * weeks; long days = time / DAY_SECONDS; time -= DAY_SECONDS * days; long hours = time / HOUR_SECONDS; time -= HOUR_SECONDS * hours; long minutes = time / MINUTE_SECONDS; time -= MINUTE_SECONDS * minutes; long seconds = time / SECOND; StringBuilder sb = new StringBuilder(); if (weeks != 0) sb.append(String.format("%d weeks ", weeks)); if (days != 0) { if (sb.length() > 0) sb.append(", "); sb.append(String.format("%d days ", days)); } if (hours != 0) { if (sb.length() > 0) sb.append(", "); sb.append(String.format("%d hours ", hours)); } if (minutes != 0 || !showSeconds) { if (sb.length() > 0) if (!showSeconds) sb.append("and "); else sb.append(", "); sb.append(String.format("%d minutes ", minutes)); } if (showSeconds) { if (sb.length() > 0) sb.append("and "); sb.append(String.format("%d seconds ", seconds)); } sb.setLength(sb.length() - 1); return sb.toString(); } /* ------------------------------------------------------------ */ public static void setConfirmationColor(String color) { chatConfirmationColor = EnumChatFormatting.getValueByName(color); if (chatConfirmationColor == null) chatConfirmationColor = EnumChatFormatting.GREEN; } public static void setErrorColor(String color) { chatErrorColor = EnumChatFormatting.getValueByName(color); if (chatErrorColor == null) chatErrorColor = EnumChatFormatting.RED; } public static void setNotificationColor(String color) { chatNotificationColor = EnumChatFormatting.getValueByName(color); if (chatNotificationColor == null) chatNotificationColor = EnumChatFormatting.AQUA; } public static void setWarningColor(String color) { chatWarningColor = EnumChatFormatting.getValueByName(color); if (chatWarningColor == null) chatWarningColor = EnumChatFormatting.YELLOW; } @Override public void load(Configuration config, boolean isReload) { config.addCustomCategoryComment(CONFIG_CAT, "This controls the colors of the various chats output by ForgeEssentials." + "\nValid output colors are as follows:" + "\naqua, black, blue, dark_aqua, dark_blue, dark_gray, dark_green, dark_purple, dark_red" + "\ngold, gray, green, light_purple, red, white, yellow"); setConfirmationColor(config.get(CONFIG_CAT, "confirmationColor", "green", "Defaults to green.").getString()); setErrorColor(config.get(CONFIG_CAT, "errorOutputColor", "red", "Defaults to red.").getString()); setNotificationColor(config.get(CONFIG_CAT, "notificationOutputColor", "aqua", "Defaults to aqua.").getString()); setWarningColor(config.get(CONFIG_CAT, "warningOutputColor", "yellow", "Defaults to yellow.").getString()); } }