/* * This file is part of the Illarion project. * * Copyright © 2015 - Illarion e.V. * * Illarion is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Illarion is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ package illarion.client.util; import illarion.client.gui.ChatGui; import illarion.client.world.Char; import illarion.client.world.World; import illarion.common.types.ServerCoordinate; import org.illarion.engine.graphic.Color; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.RegEx; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * This Chat handler fetches all texts send by the network interface and * forwards the data to the required parts of the client. It takes care for * transforming the text properly for each part of the client. * * @author Martin Karing <nitram@illarion.org> */ public final class ChatHandler { /** * The possible speech modes that are displays on the screen. */ public enum SpeechMode { /** * Speech mode for emotes. */ Emote(Color.WHITE, "^\\s*[/#]me(.*)\\s*$", "$1"), /** * Speech mode for normal spoken text. */ Normal(Color.WHITE, null, null), /** * Speech mode for OOC messages. */ Ooc(Color.GRAY, "^\\s*[/#]o(oc)?\\s*(.*)\\s*$", "$2"), /** * Speech mode for shouted text. */ Shout(Color.RED, "^\\s*[/#]s(hout)?\\s*(.*)\\s*$", "$2"), /** * Speech mode for whispered text. */ Whisper(Color.GRAY, "^\\s*[/#]w(hisper)?\\s*(.*)\\s*$", "$2"); /** * The color of this speech mode. */ private final Color color; /** * The regular expression used to find out the type of the text. */ @Nullable private final Pattern regexp; /** * The replacement to extract the actual text */ @Nullable private final String replacement; /** * Constructor for the speech mode that stores the color of the mode. * * @param modeColor the color of the speech mode * @param findRegexp the regular expression used to find out if the line is fits this Chat type or not * @param replace the regular expression needed to isolate the actual text */ SpeechMode( Color modeColor, @Nullable @RegEx String findRegexp, @Nullable String replace) { color = modeColor; if (findRegexp == null) { regexp = null; replacement = null; } else { regexp = Pattern.compile(findRegexp); replacement = replace; } } /** * Get the color of the speech mode. * * @return the color of the speech mode */ public Color getColor() { return color; } /** * Get the regular expression pattern to find out if this speech type is * the one used in the text. * * @return the pattern with the regular expression or {@code null} * in case none applies */ @Nullable public Pattern getRegexp() { return regexp; } /** * Get the replacement needed to extract the actual text from the line. * * @return the replacement */ @Nullable public String getReplacement() { return replacement; } } /** * The logger that takes care of the logging output of the Chat handler. */ private static final Logger LOGGER = LoggerFactory.getLogger(ChatHandler.class); /** * Handle a message by this processor. This method stores a message in the * ChatHandler thread so the handler takes care of the message later on. * * @param text the text that was spoken * @param location the location where the text was spoken */ public void handleMessage( @Nonnull String text, @Nonnull ServerCoordinate location, @Nonnull SpeechMode receivedMode) { Char talkingChar = World.getPeople().getCharacterAt(location); SpeechMode mode; String resultText; switch (receivedMode) { case Whisper: @SuppressWarnings("ConstantConditions") Matcher oocMatcher = SpeechMode.Ooc.getRegexp().matcher(text); if (oocMatcher.find()) { mode = SpeechMode.Ooc; resultText = oocMatcher.replaceAll(SpeechMode.Ooc.getReplacement()).trim(); } else { mode = SpeechMode.Whisper; resultText = text.trim(); } break; case Shout: mode = SpeechMode.Shout; resultText = text.trim(); break; default: @SuppressWarnings("ConstantConditions") Matcher emoteMatcher = SpeechMode.Emote.getRegexp() .matcher(text); if (emoteMatcher.find()) { mode = SpeechMode.Emote; resultText = emoteMatcher.replaceAll(SpeechMode.Emote.getReplacement()); } else { mode = SpeechMode.Normal; resultText = text.trim(); } break; } StringBuilder textBuilder = new StringBuilder(); if (mode == SpeechMode.Emote) { // we need some kind of name if (talkingChar == null) { textBuilder.append(Lang.getMsg("chat.someone")); } else { textBuilder.append(talkingChar.getName()); } textBuilder.append(resultText); String emoteText = textBuilder.toString(); World.getPlayer().getChatLog().logText(emoteText); World.getGameGui().getChatGui().addChatMessage(emoteText, ChatGui.COLOR_EMOTE); World.getGameGui().getChatGui().showChatBubble(talkingChar, emoteText, ChatGui.COLOR_EMOTE); } else { if (talkingChar == null) { textBuilder.append(Lang.getMsg("chat.distantShout")); } else { textBuilder.append(talkingChar.getName()); switch (mode) { case Shout: textBuilder.append(' ').append(Lang.getMsg("log.shout")); break; case Whisper: textBuilder.append(' ').append(Lang.getMsg("log.whisper")); break; case Normal: case Ooc: textBuilder.append(' ').append(Lang.getMsg("log.say")); break; case Emote: break; } } textBuilder.append(": "); String bubbleText; if (mode == SpeechMode.Ooc) { bubbleText = "((" + resultText + "))"; } else { bubbleText = resultText; } textBuilder.append(bubbleText); de.lessvoid.nifty.tools.Color color; switch (mode) { case Shout: color = ChatGui.COLOR_SHOUT; break; case Whisper: color = ChatGui.COLOR_WHISPER; break; case Normal: color = ChatGui.COLOR_DEFAULT; break; case Ooc: color = ChatGui.COLOR_WHISPER; break; default: color = ChatGui.COLOR_DEFAULT; break; } String talkText = textBuilder.toString(); World.getPlayer().getChatLog().logText(talkText); World.getGameGui().getChatGui().addChatMessage(talkText, color); World.getGameGui().getChatGui().showChatBubble(talkingChar, bubbleText, color); } } }