Fix/v6/click event actions (#3178)

Co-authored-by: NotMyFault <mc.cache@web.de>
Co-authored-by: dordsor21 <dordsor21@gmail.com>
This commit is contained in:
Hannes Greule 2021-08-08 13:28:43 +02:00 committed by GitHub
parent 5ab8d50b86
commit 3b2a04e4db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 414 additions and 24 deletions

View File

@ -27,6 +27,7 @@ package com.plotsquared.core.command;
import com.plotsquared.core.PlotSquared; import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.caption.CaptionUtility;
import com.plotsquared.core.configuration.caption.StaticCaption; import com.plotsquared.core.configuration.caption.StaticCaption;
import com.plotsquared.core.configuration.caption.Templates; import com.plotsquared.core.configuration.caption.Templates;
import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.configuration.caption.TranslatableCaption;
@ -335,10 +336,11 @@ public final class FlagCommand extends Command {
return; return;
} }
boolean force = event.getEventResult() == Result.FORCE; boolean force = event.getEventResult() == Result.FORCE;
final String value = StringMan.join(Arrays.copyOfRange(args, 1, args.length), " "); String value = StringMan.join(Arrays.copyOfRange(args, 1, args.length), " ");
if (!force && !checkPermValue(player, plotFlag, args[0], value)) { if (!force && !checkPermValue(player, plotFlag, args[0], value)) {
return; return;
} }
value = CaptionUtility.stripClickEvents(plotFlag, value);
final PlotFlag<?, ?> parsed; final PlotFlag<?, ?> parsed;
try { try {
parsed = plotFlag.parse(value); parsed = plotFlag.parse(value);

View File

@ -26,12 +26,14 @@
package com.plotsquared.core.configuration; package com.plotsquared.core.configuration;
import com.plotsquared.core.configuration.file.YamlConfiguration; import com.plotsquared.core.configuration.file.YamlConfiguration;
import net.kyori.adventure.text.event.ClickEvent;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
public class Settings extends Config { public class Settings extends Config {
@ -498,10 +500,12 @@ public class Settings extends Config {
"notify-enter, notify-leave, greeting or farewell flag."}) "notify-enter, notify-leave, greeting or farewell flag."})
public static boolean NOTIFICATION_AS_ACTIONBAR = false; public static boolean NOTIFICATION_AS_ACTIONBAR = false;
@Comment({"Whether to strip any possible <click_event> components from user-defined messages, e.g. plot greeting", @Comment({"The click event actions that should be removed from user input in e.g. plot flags like 'greeting'.",
"This can allow players to use commands to give themselves ranks as commands ran in this fashion cannot be prevent by " + "Actions like 'RUN_COMMAND' may be used maliciously as players could trick staff into clicking on messages",
"permissions etc."}) "triggering destructive commands."})
public static boolean REMOVE_USER_DEFINED_CLICK_EVENTS = true; public static List<String> CLICK_EVENT_ACTIONS_TO_REMOVE = Arrays.stream(ClickEvent.Action.values())
.map(Enum::name)
.collect(Collectors.toList());
} }

View File

@ -25,12 +25,42 @@
*/ */
package com.plotsquared.core.configuration.caption; package com.plotsquared.core.configuration.caption;
import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.player.PlotPlayer; import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.plot.flag.PlotFlag;
import com.plotsquared.core.plot.flag.implementations.DescriptionFlag;
import com.plotsquared.core.plot.flag.implementations.FarewellFlag;
import com.plotsquared.core.plot.flag.implementations.GreetingFlag;
import com.plotsquared.core.plot.flag.types.StringFlag;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Set;
import static com.plotsquared.core.configuration.caption.ComponentTransform.nested;
import static com.plotsquared.core.configuration.caption.ComponentTransform.stripClicks;
public class CaptionUtility { public class CaptionUtility {
// flags which values are parsed by minimessage
private static final Set<Class<? extends StringFlag<?>>> MINI_MESSAGE_FLAGS = Set.of(
GreetingFlag.class,
FarewellFlag.class,
DescriptionFlag.class
);
private static final ComponentTransform CLICK_STRIP_TRANSFORM = nested(
stripClicks(
Settings.Chat.CLICK_EVENT_ACTIONS_TO_REMOVE.stream()
.map(ClickEvent.Action::valueOf)
.toArray(ClickEvent.Action[]::new)
)
);
/** /**
* Format a chat message but keep the formatting keys * Format a chat message but keep the formatting keys
* *
@ -66,4 +96,42 @@ public class CaptionUtility {
return chatContext.getMessage(); return chatContext.getMessage();
} }
/**
* Strips configured click events from a MiniMessage string.
*
* @param miniMessageString the message from which the specified click events should be removed from.
* @return the string without the click events that are configured to be removed.
*
* @see Settings.Chat#CLICK_EVENT_ACTIONS_TO_REMOVE
*/
public static String stripClickEvents(final @NonNull String miniMessageString) {
// parse, transform and serialize again
Component component = MiniMessage.get().parse(miniMessageString);
component = CLICK_STRIP_TRANSFORM.transform(component);
return MiniMessage.get().serialize(component);
}
/**
* Strips configured MiniMessage click events from a plot flag value.
* This is used before letting the string be parsed by the plot flag.
* This method works the same way as {@link #stripClickEvents(String)} but will only
* strip click events from messages that target flags that are meant to contain MiniMessage strings.
*
* @param flag the flag the message is targeted for.
* @param miniMessageString the message from which the specified click events should be removed from.
* @return the string without the click events that are configured to be removed.
*
* @see Settings.Chat#CLICK_EVENT_ACTIONS_TO_REMOVE
* @see #stripClickEvents(String)
*/
public static String stripClickEvents(
final @NonNull PlotFlag<?, ?> flag,
final @NonNull String miniMessageString
) {
if (MINI_MESSAGE_FLAGS.contains(flag.getClass())) {
return stripClickEvents(miniMessageString);
}
return miniMessageString;
}
} }

View File

@ -0,0 +1,50 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2021 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.configuration.caption;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.jetbrains.annotations.NotNull;
import java.util.EnumSet;
import java.util.Set;
final class ClickStripTransform implements ComponentTransform {
private final Set<ClickEvent.@NotNull Action> actionsToStrip;
public ClickStripTransform(final Set<ClickEvent.@NotNull Action> actionsToStrip) {
this.actionsToStrip = EnumSet.copyOf(actionsToStrip);
}
@Override
public @NonNull Component transform(@NonNull final Component original) {
var clickEvent = original.clickEvent();
if (clickEvent == null || !actionsToStrip.contains(clickEvent.action())) return original;
return original.clickEvent(null); // remove it
}
}

View File

@ -0,0 +1,67 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2021 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.configuration.caption;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Set;
public interface ComponentTransform {
/**
* Creates a transform that applies the given transform on all child components and the
* component itself. The children are transformed before the component itself is transformed.
*
* @param transform the transform to apply.
* @return a new transform which is applied on all child components and the component itself.
*/
static ComponentTransform nested(ComponentTransform transform) {
return new NestedComponentTransform(transform);
}
/**
* Creates a transform that removes click events of the given actions from a component.
* Note: To remove click events from children too, the returned transform must be wrapped
* using {@link #nested(ComponentTransform)}.
*
* @param actionsToRemove the actions used to filter which click events should be removed.
* @return a new transform that removes click events from a component.
*/
static ComponentTransform stripClicks(ClickEvent.Action... actionsToRemove) {
return new ClickStripTransform(Set.of(actionsToRemove));
}
/**
* Applies this transform on the given component and returns the result.
*
* @param original the component to transform.
* @return the transformed component.
*/
@NonNull Component transform(@NonNull Component original);
}

View File

@ -0,0 +1,54 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2021 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.configuration.caption;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import net.kyori.adventure.text.Component;
import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.List;
import java.util.stream.Collectors;
/**
* A transform that applies a nested transform on all child components and the component itself.
*/
final class NestedComponentTransform implements ComponentTransform {
private final ComponentTransform transform;
public NestedComponentTransform(final ComponentTransform transform) {
this.transform = transform;
}
@Override
public @NonNull Component transform(final @NonNull Component original) {
return this.transform.transform(original.children(transformChildren(original.children())));
}
private List<Component> transformChildren(List<Component> children) {
return children.stream().map(this::transform).collect(Collectors.toList());
}
}

View File

@ -30,6 +30,7 @@ import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.configuration.ConfigurationSection; import com.plotsquared.core.configuration.ConfigurationSection;
import com.plotsquared.core.configuration.Settings; import com.plotsquared.core.configuration.Settings;
import com.plotsquared.core.configuration.Storage; import com.plotsquared.core.configuration.Storage;
import com.plotsquared.core.configuration.caption.CaptionUtility;
import com.plotsquared.core.configuration.file.YamlConfiguration; import com.plotsquared.core.configuration.file.YamlConfiguration;
import com.plotsquared.core.inject.annotations.WorldConfig; import com.plotsquared.core.inject.annotations.WorldConfig;
import com.plotsquared.core.listener.PlotListener; import com.plotsquared.core.listener.PlotListener;
@ -2033,7 +2034,7 @@ public class SQLManager implements AbstractDB {
while (resultSet.next()) { while (resultSet.next()) {
id = resultSet.getInt("plot_id"); id = resultSet.getInt("plot_id");
final String flag = resultSet.getString("flag"); final String flag = resultSet.getString("flag");
final String value = resultSet.getString("value"); String value = resultSet.getString("value");
final Plot plot = plots.get(id); final Plot plot = plots.get(id);
if (plot != null) { if (plot != null) {
final PlotFlag<?, ?> plotFlag = final PlotFlag<?, ?> plotFlag =
@ -2041,6 +2042,7 @@ public class SQLManager implements AbstractDB {
if (plotFlag == null) { if (plotFlag == null) {
plot.getFlagContainer().addUnknownFlag(flag, value); plot.getFlagContainer().addUnknownFlag(flag, value);
} else { } else {
value = CaptionUtility.stripClickEvents(plotFlag, value);
try { try {
plot.getFlagContainer().addFlag(plotFlag.parse(value)); plot.getFlagContainer().addFlag(plotFlag.parse(value));
} catch (final FlagParseException e) { } catch (final FlagParseException e) {

View File

@ -171,9 +171,6 @@ public class PlotListener {
String greeting = plot.getFlag(GreetingFlag.class); String greeting = plot.getFlag(GreetingFlag.class);
if (!greeting.isEmpty()) { if (!greeting.isEmpty()) {
if (Settings.Chat.REMOVE_USER_DEFINED_CLICK_EVENTS) {
greeting = greeting.replaceAll(".([c-lC-L]{5}):([a-uA-U_]{11}):[^\\/]*[^>]*>>", "").replace("</click>", "");
}
if (!Settings.Chat.NOTIFICATION_AS_ACTIONBAR) { if (!Settings.Chat.NOTIFICATION_AS_ACTIONBAR) {
plot.format(StaticCaption.of(greeting), player, false).thenAcceptAsync(player::sendMessage); plot.format(StaticCaption.of(greeting), player, false).thenAcceptAsync(player::sendMessage);
} else { } else {
@ -395,9 +392,6 @@ public class PlotListener {
String farewell = plot.getFlag(FarewellFlag.class); String farewell = plot.getFlag(FarewellFlag.class);
if (!farewell.isEmpty()) { if (!farewell.isEmpty()) {
if (Settings.Chat.REMOVE_USER_DEFINED_CLICK_EVENTS) {
farewell = farewell.replaceAll(".([c-lC-L]{5}):([a-uA-U_]{11}):[^\\/]*[^>]*>", "").replace("</click>", "");
}
if (!Settings.Chat.NOTIFICATION_AS_ACTIONBAR) { if (!Settings.Chat.NOTIFICATION_AS_ACTIONBAR) {
plot.format(StaticCaption.of(farewell), player, false).thenAcceptAsync(player::sendMessage); plot.format(StaticCaption.of(farewell), player, false).thenAcceptAsync(player::sendMessage);
} else { } else {

View File

@ -2790,9 +2790,6 @@ public class Plot {
String description = this.getFlag(DescriptionFlag.class); String description = this.getFlag(DescriptionFlag.class);
if (description.isEmpty()) { if (description.isEmpty()) {
description = TranslatableCaption.of("info.plot_no_description").getComponent(player); description = TranslatableCaption.of("info.plot_no_description").getComponent(player);
} else if (Settings.Chat.REMOVE_USER_DEFINED_CLICK_EVENTS) {
description = description.replaceAll(".([c-lC-L]{5}):([a-uA-U_]{11}):[^\\/]*[^>]*>", "").replace("</click>",
"");
} }
Component flags; Component flags;

View File

@ -27,6 +27,7 @@ package com.plotsquared.core.plot.flag;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.plotsquared.core.configuration.caption.CaptionUtility;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
@ -316,8 +317,9 @@ public class FlagContainer {
) { ) {
if (plotFlagUpdateType != PlotFlagUpdateType.FLAG_REMOVED && this.unknownFlags if (plotFlagUpdateType != PlotFlagUpdateType.FLAG_REMOVED && this.unknownFlags
.containsKey(flag.getName())) { .containsKey(flag.getName())) {
final String value = this.unknownFlags.remove(flag.getName()); String value = this.unknownFlags.remove(flag.getName());
if (value != null) { if (value != null) {
value = CaptionUtility.stripClickEvents(flag, value);
try { try {
this.addFlag(flag.parse(value)); this.addFlag(flag.parse(value));
} catch (final Exception ignored) { } catch (final Exception ignored) {

View File

@ -26,10 +26,10 @@
package com.plotsquared.core.plot.flag.implementations; package com.plotsquared.core.plot.flag.implementations;
import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.plot.flag.PlotFlag; import com.plotsquared.core.plot.flag.types.StringFlag;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
public class DescriptionFlag extends PlotFlag<String, DescriptionFlag> { public class DescriptionFlag extends StringFlag<DescriptionFlag> {
public static final DescriptionFlag DESCRIPTION_FLAG_EMPTY = new DescriptionFlag(""); public static final DescriptionFlag DESCRIPTION_FLAG_EMPTY = new DescriptionFlag("");

View File

@ -28,10 +28,10 @@ package com.plotsquared.core.plot.flag.implementations;
import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.plot.Plot; import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.flag.InternalFlag; import com.plotsquared.core.plot.flag.InternalFlag;
import com.plotsquared.core.plot.flag.PlotFlag; import com.plotsquared.core.plot.flag.types.StringFlag;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
public class DoneFlag extends PlotFlag<String, DoneFlag> implements InternalFlag { public class DoneFlag extends StringFlag<DoneFlag> implements InternalFlag {
/** /**
* Construct a new flag instance. * Construct a new flag instance.

View File

@ -26,10 +26,10 @@
package com.plotsquared.core.plot.flag.implementations; package com.plotsquared.core.plot.flag.implementations;
import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.plot.flag.PlotFlag; import com.plotsquared.core.plot.flag.types.StringFlag;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
public class FarewellFlag extends PlotFlag<String, FarewellFlag> { public class FarewellFlag extends StringFlag<FarewellFlag> {
public static final FarewellFlag FAREWELL_FLAG_EMPTY = new FarewellFlag(""); public static final FarewellFlag FAREWELL_FLAG_EMPTY = new FarewellFlag("");

View File

@ -26,10 +26,10 @@
package com.plotsquared.core.plot.flag.implementations; package com.plotsquared.core.plot.flag.implementations;
import com.plotsquared.core.configuration.caption.TranslatableCaption; import com.plotsquared.core.configuration.caption.TranslatableCaption;
import com.plotsquared.core.plot.flag.PlotFlag; import com.plotsquared.core.plot.flag.types.StringFlag;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
public class GreetingFlag extends PlotFlag<String, GreetingFlag> { public class GreetingFlag extends StringFlag<GreetingFlag> {
public static final GreetingFlag GREETING_FLAG_EMPTY = new GreetingFlag(""); public static final GreetingFlag GREETING_FLAG_EMPTY = new GreetingFlag("");

View File

@ -0,0 +1,49 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2021 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.plot.flag.types;
import com.plotsquared.core.configuration.caption.Caption;
import com.plotsquared.core.plot.flag.PlotFlag;
import org.checkerframework.checker.nullness.qual.NonNull;
public abstract class StringFlag<F extends StringFlag<F>> extends PlotFlag<String, F> {
/**
* Construct a new flag instance.
*
* @param value Flag value
* @param flagCategory The flag category
* @param flagDescription A caption describing the flag functionality
*/
protected StringFlag(
final @NonNull String value,
final @NonNull Caption flagCategory,
final @NonNull Caption flagDescription
) {
super(value, flagCategory, flagDescription);
}
}

View File

@ -0,0 +1,96 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2021 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.configuration.caption;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.util.EnumSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
class ClickStripTransformTest {
@Test
@DisplayName("Remove click event of specific action correctly")
void removeClickEvent() {
var commonAction = ClickEvent.Action.OPEN_FILE;
var transform = new ClickStripTransform(EnumSet.of(commonAction));
var component = Component.text("Hello")
.clickEvent(ClickEvent.clickEvent(
commonAction,
"World"
)
);
var transformedComponent = transform.transform(component);
assertNull(transformedComponent.clickEvent());
}
@Test
@DisplayName("Don't remove click events of other action types")
void ignoreClickEvent() {
var actionToRemove = ClickEvent.Action.SUGGEST_COMMAND;
var transform = new ClickStripTransform(EnumSet.of(actionToRemove));
var originalClickEvent = ClickEvent.clickEvent(
ClickEvent.Action.CHANGE_PAGE,
"World"
);
var component = Component.text("Hello")
.clickEvent(originalClickEvent);
var transformedComponent = transform.transform(component);
assertEquals(originalClickEvent, transformedComponent.clickEvent());
}
@Test
@DisplayName("Remove nested click events correctly")
void removeNestedClickEvent() {
// nested transform is required to apply on children
var transform = new NestedComponentTransform(new ClickStripTransform(EnumSet.allOf(ClickEvent.Action.class)));
var inner = Component
// some arbitrary values that should remain
.text("World")
.color(NamedTextColor.AQUA)
.hoverEvent(HoverEvent.showText(Component.text("ABC")))
.decorate(TextDecoration.OBFUSCATED)
.insertion("DEF");
var component = Component.text("Hello ")
.append(
inner.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, "https://example.org"))
);
var transformedComponent = transform.transform(component);
assertFalse(transformedComponent.children().isEmpty()); // child still exists
assertEquals(inner, transformedComponent.children().get(0)); // only the click event has changed
assertNull(transformedComponent.children().get(0).clickEvent());
}
}

View File

@ -81,6 +81,7 @@ allprojects {
dependencies { dependencies {
// Tests // Tests
testImplementation("junit:junit:4.13.2") testImplementation("junit:junit:4.13.2")
testImplementation("org.junit.jupiter:junit-jupiter:5.7.2")
} }
plugins.withId("java") { plugins.withId("java") {
@ -215,7 +216,11 @@ allprojects {
named("build") { named("build") {
dependsOn(named("shadowJar")) dependsOn(named("shadowJar"))
} }
test {
useJUnitPlatform()
}
} }
} }
tasks { tasks {