From 92ba72d202af6b64205a6158f01568433db93c08 Mon Sep 17 00:00:00 2001 From: Efy <35348263+Efnilite@users.noreply.github.com> Date: Wed, 2 Oct 2024 00:21:49 +0200 Subject: [PATCH] Prevent cancelling of Swim Toggle event (#7066) --- .../njol/skript/effects/EffCancelEvent.java | 106 ++++++++---------- .../syntaxes/effects/EffCancelEventTest.java | 17 +++ src/test/skript/junit/EffCancelEvent.sk | 21 ++++ .../7054-update event cancelling.sk | 26 +++++ 4 files changed, 112 insertions(+), 58 deletions(-) create mode 100644 src/test/java/org/skriptlang/skript/test/tests/syntaxes/effects/EffCancelEventTest.java create mode 100644 src/test/skript/junit/EffCancelEvent.sk create mode 100644 src/test/skript/tests/regressions/7054-update event cancelling.sk diff --git a/src/main/java/ch/njol/skript/effects/EffCancelEvent.java b/src/main/java/ch/njol/skript/effects/EffCancelEvent.java index 317cdd3a9ee..3343f032cdf 100644 --- a/src/main/java/ch/njol/skript/effects/EffCancelEvent.java +++ b/src/main/java/ch/njol/skript/effects/EffCancelEvent.java @@ -1,34 +1,5 @@ -/** - * This file is part of Skript. - * - * Skript 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. - * - * Skript 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 Skript. If not, see . - * - * Copyright Peter Güttinger, SkriptLang team and contributors - */ package ch.njol.skript.effects; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.Event.Result; -import org.bukkit.event.block.BlockCanBuildEvent; -import org.bukkit.event.inventory.InventoryInteractEvent; -import org.bukkit.event.player.PlayerDropItemEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerLoginEvent; -import org.jetbrains.annotations.Nullable; - import ch.njol.skript.Skript; import ch.njol.skript.bukkitutil.PlayerUtils; import ch.njol.skript.doc.Description; @@ -42,39 +13,58 @@ import ch.njol.skript.log.ErrorQuality; import ch.njol.skript.util.Utils; import ch.njol.util.Kleenean; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.block.BlockCanBuildEvent; +import org.bukkit.event.entity.EntityToggleSwimEvent; +import org.bukkit.event.inventory.InventoryInteractEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerLoginEvent; +import org.jetbrains.annotations.Nullable; -/** - * @author Peter Güttinger - */ @Name("Cancel Event") @Description("Cancels the event (e.g. prevent blocks from being placed, or damage being taken).") -@Examples({"on damage:", - " victim is a player", - " victim has the permission \"skript.god\"", - " cancel the event"}) +@Examples({ + "on damage:", + "\tvictim is a player", + "\tvictim has the permission \"skript.god\"", + "\tcancel the event" +}) @Since("1.0") public class EffCancelEvent extends Effect { + static { Skript.registerEffect(EffCancelEvent.class, "cancel [the] event", "uncancel [the] event"); } private boolean cancel; - - @SuppressWarnings("null") + @Override - public boolean init(final Expression[] vars, final int matchedPattern, final Kleenean isDelayed, final ParseResult parser) { + public boolean init(Expression[] expressions, int matchedPattern, + Kleenean isDelayed, ParseResult parseResult) { if (isDelayed == Kleenean.TRUE) { - Skript.error("Can't cancel an event anymore after it has already passed", ErrorQuality.SEMANTIC_ERROR); + Skript.error("An event cannot be cancelled after it has already passed", ErrorQuality.SEMANTIC_ERROR); return false; } + cancel = matchedPattern == 0; - final Class[] es = getParser().getCurrentEvents(); - if (es == null) + Class[] currentEvents = getParser().getCurrentEvents(); + + if (currentEvents == null) + return false; + + if (cancel && getParser().isCurrentEvent(EntityToggleSwimEvent.class)) { + Skript.error("Cancelling a toggle swim event has no effect"); return false; - for (final Class e : es) { - if (Cancellable.class.isAssignableFrom(e) || BlockCanBuildEvent.class.isAssignableFrom(e)) + } + + for (Class event : currentEvents) { + if (Cancellable.class.isAssignableFrom(event) || BlockCanBuildEvent.class.isAssignableFrom(event)) return true; // TODO warning if some event(s) cannot be cancelled even though some can (needs a way to be suppressed) } + if (getParser().isCurrentEvent(PlayerLoginEvent.class)) Skript.error("A connect event cannot be cancelled, but the player may be kicked ('kick player by reason of \"...\"')", ErrorQuality.SEMANTIC_ERROR); else @@ -83,24 +73,24 @@ public boolean init(final Expression[] vars, final int matchedPattern, final } @Override - public void execute(final Event e) { - if (e instanceof Cancellable) - ((Cancellable) e).setCancelled(cancel); - if (e instanceof PlayerInteractEvent) { - EvtClick.interactTracker.eventModified((Cancellable) e); - ((PlayerInteractEvent) e).setUseItemInHand(cancel ? Result.DENY : Result.DEFAULT); - ((PlayerInteractEvent) e).setUseInteractedBlock(cancel ? Result.DENY : Result.DEFAULT); - } else if (e instanceof BlockCanBuildEvent) { - ((BlockCanBuildEvent) e).setBuildable(!cancel); - } else if (e instanceof PlayerDropItemEvent) { - PlayerUtils.updateInventory(((PlayerDropItemEvent) e).getPlayer()); - } else if (e instanceof InventoryInteractEvent) { - PlayerUtils.updateInventory(((Player) ((InventoryInteractEvent) e).getWhoClicked())); + public void execute(Event event) { + if (event instanceof Cancellable) + ((Cancellable) event).setCancelled(cancel); + if (event instanceof PlayerInteractEvent) { + EvtClick.interactTracker.eventModified((Cancellable) event); + ((PlayerInteractEvent) event).setUseItemInHand(cancel ? Event.Result.DENY : Event.Result.DEFAULT); + ((PlayerInteractEvent) event).setUseInteractedBlock(cancel ? Event.Result.DENY : Event.Result.DEFAULT); + } else if (event instanceof BlockCanBuildEvent) { + ((BlockCanBuildEvent) event).setBuildable(!cancel); + } else if (event instanceof PlayerDropItemEvent) { + PlayerUtils.updateInventory(((PlayerDropItemEvent) event).getPlayer()); + } else if (event instanceof InventoryInteractEvent) { + PlayerUtils.updateInventory(((Player) ((InventoryInteractEvent) event).getWhoClicked())); } } @Override - public String toString(final @Nullable Event e, final boolean debug) { + public String toString(@Nullable Event event, boolean debug) { return (cancel ? "" : "un") + "cancel event"; } diff --git a/src/test/java/org/skriptlang/skript/test/tests/syntaxes/effects/EffCancelEventTest.java b/src/test/java/org/skriptlang/skript/test/tests/syntaxes/effects/EffCancelEventTest.java new file mode 100644 index 00000000000..9b9320570c3 --- /dev/null +++ b/src/test/java/org/skriptlang/skript/test/tests/syntaxes/effects/EffCancelEventTest.java @@ -0,0 +1,17 @@ +package org.skriptlang.skript.test.tests.syntaxes.effects; + +import ch.njol.skript.test.runner.SkriptJUnitTest; +import org.junit.Test; + +public class EffCancelEventTest extends SkriptJUnitTest { + + static { + setShutdownDelay(1); + } + + @Test + public void test() { + spawnTestPig(); + } + +} diff --git a/src/test/skript/junit/EffCancelEvent.sk b/src/test/skript/junit/EffCancelEvent.sk new file mode 100644 index 00000000000..db6e4c9edb5 --- /dev/null +++ b/src/test/skript/junit/EffCancelEvent.sk @@ -0,0 +1,21 @@ +test "EffCancelEventJUnit" when running JUnit: + set {_tests::1} to "event not cancelled by default" + set {_tests::2} to "cancel event" + set {_tests::3} to "uncancel event" + + ensure junit test "org.skriptlang.skript.test.tests.syntaxes.effects.EffCancelEventTest" completes {_tests::*} + +on spawn of pig: + set {_test} to "org.skriptlang.skript.test.tests.syntaxes.effects.EffCancelEventTest" + junit test is {_test} + + if event is not cancelled: + complete objective "event not cancelled by default" for {_test} + + cancel event + if event is cancelled: + complete objective "cancel event" for {_test} + + uncancel event + if event is not cancelled: + complete objective "uncancel event" for {_test} diff --git a/src/test/skript/tests/regressions/7054-update event cancelling.sk b/src/test/skript/tests/regressions/7054-update event cancelling.sk new file mode 100644 index 00000000000..8a371308d8d --- /dev/null +++ b/src/test/skript/tests/regressions/7054-update event cancelling.sk @@ -0,0 +1,26 @@ +parse: + results: {PlayerLogin::parse::*} + code: + on connect: + cancel event + +parse: + results: {PlayerQuit::parse::*} + code: + on quit: + cancel event + +parse: + results: {SwimToggle::parse::*} + code: + on swim toggle: + cancel event + +test "cancelling swim toggle": + assert {SwimToggle::parse::*} contains "Cancelling a toggle swim event has no effect" with "cancelling swim toggle doesn't error" + +test "cancelling player login": + assert {PlayerLogin::parse::*} contains "A connect event cannot be cancelled, but the player may be kicked ('kick player by reason of ""...""')" with "cancelling player login doesn't error" + +test "cancelling regular event": + assert {PlayerQuit::parse::*} contains "An on quit event cannot be cancelled" with "cancelling regular event doesn't error"