use of com.easterlyn.util.text.ParsedText in project Easterlyn by Easterlyn.
the class StringUtil method toJSON.
// TODO appears to not be parsing colors correctly
public static Collection<TextComponent> toJSON(@Nullable String message, Collection<QuoteConsumer> additionalHandlers) {
if (message == null) {
return Collections.emptyList();
}
ParsedText parsedText = new ParsedText();
StringBuilder builder = new StringBuilder();
Collection<QuoteConsumer> consumers = Stream.concat(QUOTE_CONSUMERS.stream(), additionalHandlers.stream()).collect(Collectors.toSet());
int maxIndex = message.length() - 1;
nextChar: for (int i = 0; i < message.length(); ++i) {
char c = message.charAt(i);
BlockQuoteMatcher matcher = BLOCK_QUOTES.get(c);
// noinspection ConstantConditions
do {
if (matcher == null) {
break;
}
BlockQuote quote = matcher.findQuote(message, i);
if (quote == null) {
break;
}
i += quote.getQuoteLength() - 1;
if (!matcher.allowAdditionalParsing()) {
if (quote.getQuoteMarks() != null) {
builder.append(quote.getQuoteMarks()).append(quote.getQuoteText()).append(quote.getQuoteMarks());
} else {
builder.append(quote.getQuoteText());
}
continue nextChar;
}
if (quote.getQuoteMarks() != null) {
builder.append(quote.getQuoteMarks());
}
String quoteText = quote.getQuoteText();
consumeQuote(parsedText, consumers, builder, quote.getQuoteText());
if (quote.getQuoteMarks() != null) {
builder.append(quote.getQuoteMarks());
}
continue nextChar;
} while (false);
if (c == ' ') {
builder.append(c);
continue;
}
int nextSpace = message.indexOf(' ', i);
if (nextSpace == -1) {
nextSpace = message.length();
}
consumeQuote(parsedText, consumers, builder, message.substring(i, nextSpace));
i = nextSpace - 1;
}
// Parse remaining text in builder
consumeQuote(parsedText, consumers, builder, null);
// The client will crash if the array is empty
if (parsedText.getComponents().isEmpty()) {
parsedText.addComponent(new TextComponent(""));
}
return parsedText.getComponents();
}
use of com.easterlyn.util.text.ParsedText in project Easterlyn by Easterlyn.
the class EasterlynChat method register.
@Override
protected void register(EasterlynCore plugin) {
StringUtil.addQuoteConsumer(new StaticQuoteConsumer(CHANNEL_PATTERN) {
@Override
public void addComponents(@NotNull ParsedText components, @NotNull Supplier<Matcher> matcherSupplier) {
Matcher matcher = matcherSupplier.get();
String channelName = matcher.group(1);
Channel channel = getChannels().get(channelName.toLowerCase().substring(1));
TextComponent component;
if (channel != null) {
component = channel.getMention();
} else {
int end = matcher.end(1);
component = new TextComponent(matcher.group().substring(0, end));
component.setColor(Colors.CHANNEL);
component.setUnderlined(true);
component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(TextComponent.fromLegacyText(Colors.COMMAND + "/join " + Colors.CHANNEL + channelName))));
component.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/join " + channelName));
}
components.addComponent(component);
String trailingPunctuation = matcher.group(2);
if (trailingPunctuation != null && !trailingPunctuation.isEmpty()) {
components.addText(trailingPunctuation, component.getHoverEvent(), component.getClickEvent());
}
}
});
IssuerAwareContextResolver<Channel, BukkitCommandExecutionContext> channelContext = context -> {
String firstArg = context.getFirstArg();
// Current channel or unspecified, defaulting to current
if (context.hasFlag(ChannelFlag.CURRENT) || (context.hasFlag(ChannelFlag.LISTENING_OR_CURRENT) || context.hasFlag(ChannelFlag.VISIBLE_OR_CURRENT)) && (firstArg == null || firstArg.indexOf('#') != 0)) {
if (!context.getIssuer().isPlayer()) {
// Console never has a current channel
throw new InvalidCommandArgument(CoreLang.NO_CONSOLE);
}
String channelName = plugin.getUserManager().getUser(context.getPlayer().getUniqueId()).getStorage().getString(USER_CURRENT);
Channel channel = channels.get(channelName);
if (channel == null) {
throw new InvalidCommandArgument(MessageKey.of("chat.common.no_current_channel"));
}
return channel;
}
// Channel name must be specified for anything beyond this point, pop argument
context.popFirstArg();
if (firstArg == null) {
throw new InvalidCommandArgument(MessageKey.of("chat.common.no_specified_channel"));
}
if (firstArg.length() == 0 || firstArg.charAt(0) != '#') {
throw new InvalidCommandArgument(MessageKey.of("chat.commands.channel.create.error.naming_conventions"));
}
Channel channel = channels.get(firstArg.substring(1).toLowerCase());
if (channel == null) {
throw new InvalidCommandArgument(MessageKey.of("chat.common.no_matching_channel"), "{value}", firstArg);
}
User user;
if (context.getIssuer().isPlayer()) {
user = getCore().getUserManager().getUser(context.getIssuer().getUniqueId());
} else {
user = null;
}
if (context.hasFlag(ChannelFlag.VISIBLE) || context.hasFlag(ChannelFlag.VISIBLE_OR_CURRENT)) {
if (user == null || !channel.isPrivate() || channel.isWhitelisted(user)) {
return channel;
}
throw new InvalidCommandArgument(MessageKey.of("chat.common.no_channel_access"), "{value}", channel.getDisplayName());
}
if (context.hasFlag(ChannelFlag.LISTENING) || context.hasFlag(ChannelFlag.LISTENING_OR_CURRENT)) {
if (user == null) {
return channel;
}
List<String> channels = user.getStorage().getStringList(EasterlynChat.USER_CHANNELS);
if (!channels.contains(channel.getName())) {
throw new InvalidCommandArgument(MessageKey.of("chat.common.not_listening_to_channel"), "{value}", channel.getDisplayName());
}
return channel;
}
if (user == null) {
throw new InvalidCommandArgument(CoreLang.NO_CONSOLE);
}
if (context.hasFlag(ChannelFlag.NOT_LISTENING)) {
List<String> channels = user.getStorage().getStringList(EasterlynChat.USER_CHANNELS);
if (channels.contains(channel.getName())) {
throw new InvalidCommandArgument(MessageKey.of("chat.common.listening_to_channel"), "{value}", channel.getDisplayName());
}
return channel;
}
ReportableEvent.call("Missing Channel context flag!", 10);
throw new InvalidCommandArgument(CoreLang.ERROR_LOGGED);
};
plugin.getCommandManager().getCommandContexts().registerIssuerAwareContext(Channel.class, channelContext);
plugin.getCommandManager().getCommandContexts().registerIssuerAwareContext(NormalChannel.class, context -> {
Channel channel = channelContext.getContext(context);
if (!(channel instanceof NormalChannel)) {
throw new InvalidCommandArgument(MessageKey.of("chat.common.channel_not_modifiable"));
}
return (NormalChannel) channel;
});
// TODO ACF is removing leading # from channel display names in completions
plugin.getCommandManager().getCommandCompletions().registerCompletion("channels", getUserHandler(user -> channels.values().stream().distinct().filter(channel -> channel.isWhitelisted(user)).map(Channel::getDisplayName).collect(Collectors.toSet())));
plugin.getCommandManager().getCommandCompletions().setDefaultCompletion("channels", Channel.class, NormalChannel.class);
plugin.getCommandManager().getCommandCompletions().registerCompletion("channelsJoinable", getUserHandler(user -> {
List<String> channelsJoined = user.getStorage().getStringList(EasterlynChat.USER_CHANNELS);
return channels.values().stream().distinct().filter(channel -> !channelsJoined.contains(channel.getName()) && channel.isWhitelisted(user)).map(Channel::getDisplayName).collect(Collectors.toSet());
}));
plugin.getCommandManager().getCommandCompletions().registerCompletion("channelsListening", getUserHandler(user -> user.getStorage().getStringList(EasterlynChat.USER_CHANNELS)));
plugin.getCommandManager().getCommandCompletions().registerCompletion("channelsModerated", getUserHandler(user -> channels.values().stream().distinct().filter(channel -> channel.isModerator(user)).map(Channel::getDisplayName).collect(Collectors.toSet())));
plugin.getCommandManager().getCommandCompletions().registerCompletion("channelsOwned", getUserHandler(user -> channels.values().stream().distinct().filter(channel -> channel.isOwner(user)).map(Channel::getDisplayName).collect(Collectors.toSet())));
plugin.getLocaleManager().addLocaleSupplier(this);
plugin.registerCommands(this, getClassLoader(), "com.easterlyn.chat.command");
}
use of com.easterlyn.util.text.ParsedText in project Easterlyn by Easterlyn.
the class UserChatEvent method send.
public void send(Collection<UUID> additionalRecipients) {
Bukkit.getPluginManager().callEvent(this);
if (this.isCancelled()) {
return;
}
TextComponent channelElement = new TextComponent();
TextComponent[] channelHover = new TextComponent[] { new TextComponent("/join "), new TextComponent(channel.getDisplayName()) };
channelHover[0].setColor(Colors.COMMAND);
channelHover[1].setColor(Colors.CHANNEL);
channelElement.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(channelHover)));
channelElement.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/join " + channel.getDisplayName()));
TextComponent channelName = new TextComponent(channel.getDisplayName());
channelName.setColor((channel.isOwner(getUser()) ? Colors.CHANNEL_OWNER : channel.isModerator(getUser()) ? Colors.CHANNEL_MODERATOR : Colors.CHANNEL_MEMBER));
TextComponent nameElement = new TextComponent(thirdPerson ? "> " : " <");
TextComponent userElement = getUser().getMention();
nameElement.setHoverEvent(userElement.getHoverEvent());
nameElement.setClickEvent(userElement.getClickEvent());
TextComponent nameText = new TextComponent(userElement.getText().substring(1));
nameText.setColor(userElement.getColor());
nameElement.addExtra(nameText);
nameElement.addExtra(new TextComponent(thirdPerson ? " " : "> "));
Collection<TextComponent> messageComponents;
Player player = getUser().getPlayer();
if (player == null) {
messageComponents = StringUtil.toJSON(message);
} else {
messageComponents = StringUtil.toJSON(message, Collections.singleton(new StaticQuoteConsumer(PLAYER_ITEMS) {
@Override
public void addComponents(@NotNull ParsedText components, @NotNull Supplier<Matcher> matcherSupplier) {
Matcher matcher = matcherSupplier.get();
int slot;
try {
slot = Integer.parseInt(matcher.group(1));
} catch (NumberFormatException e) {
components.addText(matcher.group());
return;
}
if (slot < 0 || slot >= player.getInventory().getSize()) {
components.addText(matcher.group());
return;
}
ItemStack item = player.getInventory().getItem(slot);
if (item == null) {
item = ItemUtil.AIR;
}
components.addComponent(ItemUtil.getItemComponent(item));
}
}));
}
Stream.concat(additionalRecipients.stream(), channel.getMembers().stream()).distinct().map(uuid -> getUser().getPlugin().getUserManager().getUser(uuid)).forEach(user -> {
boolean highlight = false;
// Copy and convert TextComponents from parsed message
List<TextComponent> highlightedComponents = new LinkedList<>();
for (TextComponent textComponent : messageComponents) {
String text = textComponent.getText();
Matcher matcher = getHighlightPattern(user).matcher(text);
int previousMatch = 0;
while (matcher.find()) {
highlight = true;
if (matcher.start() > 0) {
TextComponent start = new TextComponent(textComponent);
start.setText(text.substring(previousMatch, matcher.start()));
highlightedComponents.add(start);
}
TextComponent mention = user.getMention();
mention.setColor(Colors.HIGHLIGHT);
highlightedComponents.add(mention);
// Set previous match to end of group 1 so next will pick up group 2 if it exists.
previousMatch = matcher.end(1);
}
if (previousMatch == 0) {
// No matches, no need to modify component for user.
highlightedComponents.add(textComponent);
continue;
}
if (previousMatch == text.length()) {
// Last match coincided with the end of the text.
continue;
}
TextComponent end = new TextComponent(textComponent);
end.setText(text.substring(previousMatch));
highlightedComponents.add(end);
}
TextComponent finalMessage = new TextComponent();
// Set text a nice relaxing grey if not focused or explicitly set
finalMessage.setColor(channel.getName().equals("pm") || channel.getName().equals(user.getStorage().getString(EasterlynChat.USER_CURRENT)) ? ChatColor.WHITE : ChatColor.GRAY);
TextComponent channelBrace;
if (highlight) {
channelBrace = new TextComponent("!!");
channelBrace.setColor(Colors.HIGHLIGHT);
} else {
channelBrace = new TextComponent("[");
}
BaseComponent finalChannel = channelElement.duplicate();
finalChannel.addExtra(channelBrace);
finalChannel.addExtra(channelName);
if (!highlight) {
channelBrace = new TextComponent("]");
}
finalChannel.addExtra(channelBrace);
finalMessage.addExtra(finalChannel);
finalMessage.addExtra(nameElement);
for (TextComponent component : highlightedComponents) {
finalMessage.addExtra(component);
}
user.sendMessage(getUser() instanceof AutoUser ? null : getUser().getUniqueId(), finalMessage);
});
Bukkit.getConsoleSender().sendMessage(ChatColor.stripColor(String.format("[%1$s]" + (thirdPerson ? "> %2$s " : " <%2$s> ") + "%3$s", channel.getDisplayName(), getUser().getDisplayName(), message)));
}
Aggregations