001/* 002 * PlotSquared, a land and world management plugin for Minecraft. 003 * Copyright (C) IntellectualSites <https://intellectualsites.com> 004 * Copyright (C) IntellectualSites team and contributors 005 * 006 * This program is free software: you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation, either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * This program is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <https://www.gnu.org/licenses/>. 018 */ 019package com.plotsquared.core.configuration.caption; 020 021import com.plotsquared.core.configuration.Settings; 022import com.plotsquared.core.player.PlotPlayer; 023import com.plotsquared.core.plot.flag.PlotFlag; 024import com.plotsquared.core.plot.flag.implementations.DescriptionFlag; 025import com.plotsquared.core.plot.flag.implementations.FarewellFlag; 026import com.plotsquared.core.plot.flag.implementations.GreetingFlag; 027import com.plotsquared.core.plot.flag.implementations.PlotTitleFlag; 028import net.kyori.adventure.text.Component; 029import net.kyori.adventure.text.event.ClickEvent; 030import net.kyori.adventure.text.minimessage.MiniMessage; 031import net.kyori.adventure.text.minimessage.ParsingException; 032import org.checkerframework.checker.nullness.qual.NonNull; 033import org.checkerframework.checker.nullness.qual.Nullable; 034 035import java.util.Set; 036import java.util.regex.Pattern; 037 038import static com.plotsquared.core.configuration.caption.ComponentTransform.nested; 039import static com.plotsquared.core.configuration.caption.ComponentTransform.stripClicks; 040 041public class CaptionUtility { 042 043 private static final Pattern LEGACY_FORMATTING = Pattern.compile("ยง[a-gklmnor0-9]"); 044 045 // flags which values are parsed by minimessage 046 private static final Set<Class<? extends PlotFlag<?, ?>>> MINI_MESSAGE_FLAGS = Set.of( 047 GreetingFlag.class, 048 FarewellFlag.class, 049 DescriptionFlag.class, 050 PlotTitleFlag.class 051 ); 052 053 private static final ComponentTransform CLICK_STRIP_TRANSFORM = nested( 054 stripClicks( 055 Settings.Chat.CLICK_EVENT_ACTIONS_TO_REMOVE.stream() 056 .map(ClickEvent.Action::valueOf) 057 .toArray(ClickEvent.Action[]::new) 058 ) 059 ); 060 061 062 /** 063 * Format a chat message but keep the formatting keys 064 * 065 * @param recipient Message recipient 066 * @param message Message 067 * @return Formatted message 068 */ 069 public static String formatRaw(PlotPlayer<?> recipient, String message) { 070 final ChatFormatter.ChatContext chatContext = 071 new ChatFormatter.ChatContext(recipient, message, true); 072 for (final ChatFormatter chatFormatter : ChatFormatter.formatters) { 073 chatFormatter.format(chatContext); 074 } 075 return chatContext.getMessage(); 076 } 077 078 /** 079 * Format a chat message 080 * 081 * @param recipient Message recipient 082 * @param message Message 083 * @return Formatted message 084 */ 085 public static String format( 086 final @Nullable PlotPlayer<?> recipient, 087 final @NonNull String message 088 ) { 089 final ChatFormatter.ChatContext chatContext = 090 new ChatFormatter.ChatContext(recipient, message, false); 091 for (final ChatFormatter chatFormatter : ChatFormatter.formatters) { 092 chatFormatter.format(chatContext); 093 } 094 return chatContext.getMessage(); 095 } 096 097 /** 098 * Strips configured click events from a MiniMessage string. 099 * 100 * @param miniMessageString the message from which the specified click events should be removed from. 101 * @return the string without the click events that are configured to be removed. 102 * @see Settings.Chat#CLICK_EVENT_ACTIONS_TO_REMOVE 103 * @since 6.0.10 104 */ 105 public static String stripClickEvents(final @NonNull String miniMessageString) { 106 // parse, transform and serialize again 107 Component component; 108 try { 109 component = MiniMessage.miniMessage().deserialize(miniMessageString); 110 } catch (ParsingException e) { 111 // if the String cannot be parsed, we try stripping legacy colors 112 String legacyStripped = LEGACY_FORMATTING.matcher(miniMessageString).replaceAll(""); 113 component = MiniMessage.miniMessage().deserialize(legacyStripped); 114 } 115 component = CLICK_STRIP_TRANSFORM.transform(component); 116 return MiniMessage.miniMessage().serialize(component); 117 } 118 119 /** 120 * Strips configured MiniMessage click events from a plot flag value. 121 * This is used before letting the string be parsed by the plot flag. 122 * This method works the same way as {@link #stripClickEvents(String)} but will only 123 * strip click events from messages that target flags that are meant to contain MiniMessage strings. 124 * 125 * @param flag the flag the message is targeted for. 126 * @param miniMessageString the message from which the specified click events should be removed from. 127 * @return the string without the click events that are configured to be removed. 128 * @see Settings.Chat#CLICK_EVENT_ACTIONS_TO_REMOVE 129 * @see #stripClickEvents(String) 130 * @since 6.0.10 131 */ 132 public static String stripClickEvents( 133 final @NonNull PlotFlag<?, ?> flag, 134 final @NonNull String miniMessageString 135 ) { 136 if (MINI_MESSAGE_FLAGS.contains(flag.getClass())) { 137 return stripClickEvents(miniMessageString); 138 } 139 return miniMessageString; 140 } 141 142}