Skip to content

Commit

Permalink
Prevent cancelling of Swim Toggle event (#7066)
Browse files Browse the repository at this point in the history
  • Loading branch information
Efnilite authored Oct 1, 2024
1 parent c8ccc5b commit 92ba72d
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 58 deletions.
106 changes: 48 additions & 58 deletions src/main/java/ch/njol/skript/effects/EffCancelEvent.java
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*
* 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;
Expand All @@ -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<? extends Event>[] es = getParser().getCurrentEvents();
if (es == null)
Class<? extends Event>[] 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<? extends Event> e : es) {
if (Cancellable.class.isAssignableFrom(e) || BlockCanBuildEvent.class.isAssignableFrom(e))
}

for (Class<? extends Event> 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
Expand All @@ -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";
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}

}
21 changes: 21 additions & 0 deletions src/test/skript/junit/EffCancelEvent.sk
Original file line number Diff line number Diff line change
@@ -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}
26 changes: 26 additions & 0 deletions src/test/skript/tests/regressions/7054-update event cancelling.sk
Original file line number Diff line number Diff line change
@@ -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"

0 comments on commit 92ba72d

Please sign in to comment.