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 org.checkerframework.checker.nullness.qual.NonNull;
032import org.checkerframework.checker.nullness.qual.Nullable;
033
034import java.util.Set;
035
036import static com.plotsquared.core.configuration.caption.ComponentTransform.nested;
037import static com.plotsquared.core.configuration.caption.ComponentTransform.stripClicks;
038
039public class CaptionUtility {
040
041    // flags which values are parsed by minimessage
042    private static final Set<Class<? extends PlotFlag<?, ?>>> MINI_MESSAGE_FLAGS = Set.of(
043            GreetingFlag.class,
044            FarewellFlag.class,
045            DescriptionFlag.class,
046            PlotTitleFlag.class
047    );
048
049    private static final ComponentTransform CLICK_STRIP_TRANSFORM = nested(
050            stripClicks(
051                    Settings.Chat.CLICK_EVENT_ACTIONS_TO_REMOVE.stream()
052                            .map(ClickEvent.Action::valueOf)
053                            .toArray(ClickEvent.Action[]::new)
054            )
055    );
056
057
058    /**
059     * Format a chat message but keep the formatting keys
060     *
061     * @param recipient Message recipient
062     * @param message   Message
063     * @return Formatted message
064     */
065    public static String formatRaw(PlotPlayer<?> recipient, String message) {
066        final ChatFormatter.ChatContext chatContext =
067                new ChatFormatter.ChatContext(recipient, message, true);
068        for (final ChatFormatter chatFormatter : ChatFormatter.formatters) {
069            chatFormatter.format(chatContext);
070        }
071        return chatContext.getMessage();
072    }
073
074    /**
075     * Format a chat message
076     *
077     * @param recipient Message recipient
078     * @param message   Message
079     * @return Formatted message
080     */
081    public static String format(
082            final @Nullable PlotPlayer<?> recipient,
083            final @NonNull String message
084    ) {
085        final ChatFormatter.ChatContext chatContext =
086                new ChatFormatter.ChatContext(recipient, message, false);
087        for (final ChatFormatter chatFormatter : ChatFormatter.formatters) {
088            chatFormatter.format(chatContext);
089        }
090        return chatContext.getMessage();
091    }
092
093    /**
094     * Strips configured click events from a MiniMessage string.
095     *
096     * @param miniMessageString the message from which the specified click events should be removed from.
097     * @return the string without the click events that are configured to be removed.
098     * @see Settings.Chat#CLICK_EVENT_ACTIONS_TO_REMOVE
099     * @since 6.0.10
100     */
101    public static String stripClickEvents(final @NonNull String miniMessageString) {
102        // parse, transform and serialize again
103        Component component = MiniMessage.get().parse(miniMessageString);
104        component = CLICK_STRIP_TRANSFORM.transform(component);
105        return MiniMessage.get().serialize(component);
106    }
107
108    /**
109     * Strips configured MiniMessage click events from a plot flag value.
110     * This is used before letting the string be parsed by the plot flag.
111     * This method works the same way as {@link #stripClickEvents(String)} but will only
112     * strip click events from messages that target flags that are meant to contain MiniMessage strings.
113     *
114     * @param flag              the flag the message is targeted for.
115     * @param miniMessageString the message from which the specified click events should be removed from.
116     * @return the string without the click events that are configured to be removed.
117     * @see Settings.Chat#CLICK_EVENT_ACTIONS_TO_REMOVE
118     * @see #stripClickEvents(String)
119     * @since 6.0.10
120     */
121    public static String stripClickEvents(
122            final @NonNull PlotFlag<?, ?> flag,
123            final @NonNull String miniMessageString
124    ) {
125        if (MINI_MESSAGE_FLAGS.contains(flag.getClass())) {
126            return stripClickEvents(miniMessageString);
127        }
128        return miniMessageString;
129    }
130
131}