Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Effect Command API Enhancement & Skript Event Support #6587

Open
wants to merge 12 commits into
base: dev/feature
Choose a base branch
from
13 changes: 12 additions & 1 deletion src/main/java/ch/njol/skript/classes/data/BukkitEventValues.java
Expand Up @@ -27,6 +27,7 @@
import ch.njol.skript.aliases.Aliases;
import ch.njol.skript.aliases.ItemType;
import ch.njol.skript.command.CommandEvent;
import ch.njol.skript.command.EffectCommandEvent;
import ch.njol.skript.events.bukkit.ScriptEvent;
import ch.njol.skript.events.bukkit.SkriptStartEvent;
import ch.njol.skript.events.bukkit.SkriptStopEvent;
Expand Down Expand Up @@ -1840,7 +1841,7 @@ public Entity[] get(BellResonateEvent event) {
}
}, EventValues.TIME_NOW);
}

// InventoryMoveItemEvent
EventValues.registerEventValue(InventoryMoveItemEvent.class, Inventory.class, new Getter<Inventory, InventoryMoveItemEvent>() {
@Override
Expand Down Expand Up @@ -1872,5 +1873,15 @@ public ItemStack get(InventoryMoveItemEvent event) {
return event.getItem();
}
}, EventValues.TIME_NOW);

// EffectCommandEvent
EventValues.registerEventValue(EffectCommandEvent.class, CommandSender.class, new Getter<CommandSender, EffectCommandEvent>() {
@Override
public CommandSender get(EffectCommandEvent event) {
return event.getSender();
}
}, EventValues.TIME_NOW);

}

}
28 changes: 13 additions & 15 deletions src/main/java/ch/njol/skript/command/Commands.java
Expand Up @@ -181,34 +181,32 @@ static boolean handleEffectCommand(CommandSender sender, String command) {
command = "" + command.substring(SkriptConfig.effectCommandToken.value().length()).trim();
RetainingLogHandler log = SkriptLogger.startRetainingLog();
try {
// Call the event on the Bukkit API for addon developers.
EffectCommandEvent effectCommand = new EffectCommandEvent(sender, command);
Bukkit.getPluginManager().callEvent(effectCommand);
command = effectCommand.getCommand();
ParserInstance parserInstance = ParserInstance.get();
parserInstance.setCurrentEvent("effect command", EffectCommandEvent.class);
Effect effect = Effect.parse(command, null);
parserInstance.deleteCurrentEvent();

if (effect != null) {
log.clear(); // ignore warnings and stuff
log.printLog();
if (!effectCommand.isCancelled()) {
// Call the event on the Bukkit API for addon developers.
EffectCommandEvent effectCommand = new EffectCommandEvent(sender, command, effect);
Bukkit.getPluginManager().callEvent(effectCommand);
if (!effectCommand.isCancelled()) {
if (effect != null) {
log.clear(); // ignore warnings and stuff
log.printLog();
sender.sendMessage(ChatColor.GRAY + "executing '" + SkriptColor.replaceColorChar(command) + "'");
// TODO: remove logPlayerCommands for 2.8.0
if ((SkriptConfig.logEffectCommands.value() || SkriptConfig.logPlayerCommands.value()) && !(sender instanceof ConsoleCommandSender))
Skript.info(sender.getName() + " issued effect command: " + SkriptColor.replaceColorChar(command));
TriggerItem.walk(effect, effectCommand);
Variables.removeLocals(effectCommand);
} else {
sender.sendMessage(ChatColor.RED + "your effect command '" + SkriptColor.replaceColorChar(command) + "' was cancelled.");
if (sender == Bukkit.getConsoleSender()) // log as SEVERE instead of INFO like printErrors below
SkriptLogger.LOGGER.severe("Error in: " + SkriptColor.replaceColorChar(command));
else
sender.sendMessage(ChatColor.RED + "Error in: " + ChatColor.GRAY + SkriptColor.replaceColorChar(command));
log.printErrors(sender, "(No specific information is available)");
}
} else {
if (sender == Bukkit.getConsoleSender()) // log as SEVERE instead of INFO like printErrors below
SkriptLogger.LOGGER.severe("Error in: " + SkriptColor.replaceColorChar(command));
else
sender.sendMessage(ChatColor.RED + "Error in: " + ChatColor.GRAY + SkriptColor.replaceColorChar(command));
log.printErrors(sender, "(No specific information is available)");
sender.sendMessage(ChatColor.RED + "Your effect command '" + SkriptColor.replaceColorChar(command) + "' was cancelled.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These error messages probably ought to be lang entries, but it's okay if you feel that's out of scope for this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeking for extended support of this in the skriptlang channel.

}
} finally {
log.stop();
Expand Down
28 changes: 25 additions & 3 deletions src/main/java/ch/njol/skript/command/EffectCommandEvent.java
Expand Up @@ -18,23 +18,45 @@
*/
package ch.njol.skript.command;

import ch.njol.skript.lang.Effect;
import org.bukkit.command.CommandSender;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.jetbrains.annotations.Nullable;

/**
* @author Peter Güttinger
* Called whenever an effect command attempt is done.
*/
public class EffectCommandEvent extends CommandEvent implements Cancellable {

private boolean cancelled;
@Nullable
private final Effect effect;

public EffectCommandEvent(CommandSender sender, String command) {
public EffectCommandEvent(CommandSender sender, String command, @Nullable Effect effect) {
super(sender, command, new String[0]);
this.effect = effect;
}

/**
* @see EffectCommandEvent#EffectCommandEvent(CommandSender, String, Effect)
*/
@Deprecated
public EffectCommandEvent(CommandSender sender, String command) {
this(sender, command, null);
}

/**
* @return the parsed effect, if valid
*/
@Nullable
public Effect getEffect() {
return effect;
}

@Deprecated
public void setCommand(String command) {
this.command = command;
throw new UnsupportedOperationException();
}

@Override
Expand Down
@@ -0,0 +1,69 @@
/**
* 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.conditions;

import ch.njol.skript.Skript;
import ch.njol.skript.command.EffectCommandEvent;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.lang.Condition;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.SkriptParser;
import ch.njol.util.Kleenean;
import org.bukkit.event.Event;
import org.eclipse.jdt.annotation.Nullable;

@Name("Effect Command Is Valid")
@Description("Checks whether the parsed effect command in an 'effect command' event is valid.")
@Examples({
"if the effect command is valid:",
"\tsend \"%sender% has executed an invalid effect command!\" to console"
})
@Since("INSERT VERSION")
public class CondEffectCommandIsValid extends Condition {

static {
Skript.registerCondition(CondEffectCommandIsValid.class, "[the] effect command is [not:(not |in)]valid");
}

@Override
public boolean init(Expression<?>[] expressions, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) {
if (!getParser().isCurrentEvent(EffectCommandEvent.class)) {
Skript.error("The 'effect command is valid' condition can only be used in an 'effect command' event");
return false;
}
setNegated(parseResult.hasTag("not"));
return true;
}

@Override
public boolean check(Event event) {
if (!(event instanceof EffectCommandEvent))
return false;
return ((EffectCommandEvent) event).getEffect() != null ^ isNegated();
}

@Override
public String toString(@Nullable Event event, boolean debug) {
return "effect command is " + (isNegated() ? "in" : "") + "valid";
}

}
95 changes: 95 additions & 0 deletions src/main/java/ch/njol/skript/events/EvtEffectCommand.java
@@ -0,0 +1,95 @@
/**
* 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.events;

import ch.njol.skript.Skript;
import ch.njol.skript.command.EffectCommandEvent;
import ch.njol.skript.lang.Literal;
import ch.njol.skript.lang.SkriptEvent;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.eclipse.jdt.annotation.Nullable;

public class EvtEffectCommand extends SkriptEvent {

static {
Skript.registerEvent("Effect Command Event", EvtEffectCommand.class, EffectCommandEvent.class,
"[executor:(1:console|2:player)] effect command")
.description("Called when a player or console executes a skript effect command.")
.examples(
"on effect command:",
"\tlog \"%sender%: %command%\" to file \"effectcommands.log\"")
.since("INSERT VERSION");
}

private enum Executor {

ANY("any"),
CONSOLE("console"),
PLAYER("player");

final String toString;

Executor(String toString) {
this.toString = toString;
}

@Override
public String toString() {
return toString;
}

}

@SuppressWarnings("NotNullFieldNotInitialized")
private Executor executor;

@Override
public boolean init(Literal<?>[] args, int matchedPattern, ParseResult parseResult) {
executor = parseResult.hasTag("executor") ? Executor.values()[parseResult.mark] : Executor.ANY;
return true;
}

@Override
public boolean check(Event event) {
if (!(event instanceof EffectCommandEvent))
return false;
CommandSender sender = ((EffectCommandEvent) event).getSender();
switch (executor) {
case ANY:
return true;
case PLAYER:
return sender instanceof Player;
case CONSOLE:
return sender instanceof ConsoleCommandSender;
}
return false;
}

@Override
public String toString(@Nullable Event event, boolean debug) {
if (executor != Executor.ANY)
return executor + " effect command";
return "effect command";
}

}
59 changes: 32 additions & 27 deletions src/main/java/ch/njol/skript/expressions/ExprCommand.java
Expand Up @@ -18,6 +18,7 @@
*/
package ch.njol.skript.expressions;

import ch.njol.skript.command.EffectCommandEvent;
import ch.njol.skript.command.ScriptCommandEvent;
import org.bukkit.event.Event;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
Expand All @@ -36,19 +37,21 @@
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.util.Kleenean;

/**
* @author Peter Güttinger
*/
@Name("Command")
@Description("The command that caused an 'on command' event (excluding the leading slash and all arguments)")
@Examples({"# prevent any commands except for the /exit command during some game",
"on command:",
@Description("The command that caused an 'on command' event (excluding the leading slash and all arguments), or an 'effect command' event.")
@Examples({
"# prevent any commands except for the /exit command during some game",
"on command:",
"\tif {game::%player%::playing} is true:",
"\t\tif the command is not \"exit\":",
"\t\t\tmessage \"You're not allowed to use commands during the game\"",
"\t\t\tcancel the event"})
@Since("2.0, 2.7 (support for script commands)")
@Events("command")
"\t\tif the command is not \"exit\":",
"\t\t\tmessage \"You're not allowed to use commands during the game\"",
"\t\t\tcancel the event",
"",
"on effect command:",
"\tlog \"%sender%: %command%\" to file \"effectcommand.log\""
})
@Since("2.0, 2.7 (script commands), INSERT VERSION (effect commands)")
@Events({"command", "effect command"})
public class ExprCommand extends SimpleExpression<String> {

static {
Expand All @@ -62,8 +65,8 @@ public class ExprCommand extends SimpleExpression<String> {

@Override
public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) {
if (!getParser().isCurrentEvent(PlayerCommandPreprocessEvent.class, ServerCommandEvent.class, ScriptCommandEvent.class)) {
Skript.error("The 'command' expression can only be used in a script command or command event");
if (!getParser().isCurrentEvent(PlayerCommandPreprocessEvent.class, ServerCommandEvent.class, ScriptCommandEvent.class, EffectCommandEvent.class)) {
Skript.error("The 'command' expression can only be used in a command, script command or effect command event");
return false;
}
fullCommand = matchedPattern == 0;
Expand All @@ -72,23 +75,25 @@ public boolean init(Expression<?>[] exprs, int matchedPattern, Kleenean isDelaye

@Override
@Nullable
protected String[] get(final Event e) {
final String s;
protected String[] get(Event event) {
String command;

if (e instanceof PlayerCommandPreprocessEvent) {
s = ((PlayerCommandPreprocessEvent) e).getMessage().substring(1).trim();
} else if (e instanceof ServerCommandEvent) {
s = ((ServerCommandEvent) e).getCommand().trim();
} else { // It's a script command event
ScriptCommandEvent event = (ScriptCommandEvent) e;
s = event.getCommandLabel() + " " + event.getArgsString();
if (event instanceof PlayerCommandPreprocessEvent) {
command = ((PlayerCommandPreprocessEvent) event).getMessage().substring(1).trim();
} else if (event instanceof ServerCommandEvent) {
command = ((ServerCommandEvent) event).getCommand().trim();
} else if (event instanceof ScriptCommandEvent) {
ScriptCommandEvent e = (ScriptCommandEvent) event;
command = e.getCommandLabel() + " " + e.getArgsString();
} else { // It's an EffectCommandEvent
command = ((EffectCommandEvent) event).getCommand();
}

if (fullCommand) {
return new String[]{s};
if (event instanceof EffectCommandEvent || fullCommand) {
return new String[]{command};
} else {
int c = s.indexOf(' ');
return new String[] {c == -1 ? s : s.substring(0, c)};
int c = command.indexOf(' ');
return new String[] {c == -1 ? command : command.substring(0, c)};
}
}

Expand All @@ -103,7 +108,7 @@ public Class<? extends String> getReturnType() {
}

@Override
public String toString(@Nullable Event e, boolean debug) {
public String toString(@Nullable Event event, boolean debug) {
return fullCommand ? "the full command" : "the command";
}

Expand Down