diff --git a/src/main/java/ch/njol/skript/events/EvtPlayerCommandSend.java b/src/main/java/ch/njol/skript/events/EvtPlayerCommandSend.java new file mode 100644 index 00000000000..9ef380ada7a --- /dev/null +++ b/src/main/java/ch/njol/skript/events/EvtPlayerCommandSend.java @@ -0,0 +1,75 @@ +/** + * 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.events; + +import ch.njol.skript.Skript; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import com.google.common.collect.ImmutableCollection; +import com.google.common.collect.ImmutableList; +import org.bukkit.event.Event; +import org.bukkit.event.player.PlayerCommandSendEvent; +import org.eclipse.jdt.annotation.Nullable; + +import java.util.ArrayList; +import java.util.Collection; + +public class EvtPlayerCommandSend extends SkriptEvent { + + static { + Skript.registerEvent("Send Command List", EvtPlayerCommandSend.class, PlayerCommandSendEvent.class, "send[ing] [of [the]] [server] command[s] list", "[server] command list send") + .description( + "Called when the server sends a list of commands to the player. This usually happens on join. The sent commands " + + "can be modified via the sent commands expression.", + "Modifications will affect what commands show up for the player to tab complete. They will not affect what commands the player can actually run.", + "Adding new commands to the list is illegal behavior and will be ignored." + ) + .examples( + "on send command list:", + "\tset command list to command list where [input does not contain \":\"]", + "\tremove \"help\" from command list" + ) + .since("INSERT VERSION"); + } + + private final Collection originalCommands = new ArrayList<>(); + + @Override + public boolean init(Literal[] args, int matchedPattern, ParseResult parseResult) { + return true; + } + + @Override + public boolean check(Event event) { + originalCommands.clear(); + originalCommands.addAll(((PlayerCommandSendEvent) event).getCommands()); + return true; + } + + public ImmutableCollection getOriginalCommands() { + return ImmutableList.copyOf(originalCommands); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "sending of the server command list"; + } + +} diff --git a/src/main/java/ch/njol/skript/expressions/ExprSentCommands.java b/src/main/java/ch/njol/skript/expressions/ExprSentCommands.java new file mode 100644 index 00000000000..5c4f17ab16e --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprSentCommands.java @@ -0,0 +1,155 @@ +/** + * 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.expressions; + +import ch.njol.skript.Skript; +import ch.njol.skript.classes.Changer.ChangeMode; +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Events; +import ch.njol.skript.doc.Examples; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.events.EvtPlayerCommandSend; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.util.Kleenean; +import com.google.common.collect.Lists; +import org.bukkit.event.Event; +import org.bukkit.event.player.PlayerCommandSendEvent; +import org.eclipse.jdt.annotation.Nullable; +import org.skriptlang.skript.lang.structure.Structure; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@Name("Sent Command List") +@Description({ + "The commands that will be sent to the player in a send commands to player event.", + "Modifications will affect what commands show up for the player to tab complete. They will not affect what commands the player can actually run.", + "Adding new commands to the list is illegal behavior and will be ignored." +}) +@Examples({ + "on send command list:", + "\tset command list to command list where [input does not contain \":\"]", + "\tremove \"help\" from command list" +}) +@Since("INSERT VERSION") +@Events("send command list") +public class ExprSentCommands extends SimpleExpression { + + static { + Skript.registerExpression(ExprSentCommands.class, String.class, ExpressionType.SIMPLE, "[the] [sent] [server] command[s] list"); + } + + private EvtPlayerCommandSend parent; + + @Override + public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + Structure structure = getParser().getCurrentStructure(); + if (!(structure instanceof EvtPlayerCommandSend)) { + Skript.error("The 'command list' expression can only be used in a 'send command list' event"); + return false; + } + + if (!isDelayed.isFalse()) { + Skript.error("Can't change the command list after the event has already passed"); + return false; + } + parent = (EvtPlayerCommandSend) structure; + return true; + } + + @Override + @Nullable + protected String[] get(Event event) { + if (!(event instanceof PlayerCommandSendEvent)) + return null; + return ((PlayerCommandSendEvent) event).getCommands().toArray(new String[0]); + } + + @Override + @Nullable + public Class[] acceptChange(ChangeMode mode) { + switch (mode) { + case REMOVE: + case DELETE: + case SET: + case RESET: + return new Class[]{String[].class}; + // note that ADD is not supported, as adding new commands to the commands collection is illegal behaviour + default: + return null; + } + } + + @Override + public void change(Event event, @Nullable Object[] delta, ChangeMode mode) { + if (!(event instanceof PlayerCommandSendEvent)) + return; + + Collection commands = ((PlayerCommandSendEvent) event).getCommands(); + + // short circuit if we're just clearing the list + if (mode == ChangeMode.DELETE) { + commands.clear(); + return; + } + + List deltaCommands = (delta != null && delta.length > 0) ? Lists.newArrayList((String[]) delta) : new ArrayList<>(); + switch (mode) { + case REMOVE: + commands.removeAll(deltaCommands); + break; + case SET: + // remove all completely new commands, as adding new commands to the commands collection is illegal behaviour + List newCommands = new ArrayList<>(deltaCommands); + newCommands.removeAll(parent.getOriginalCommands()); + deltaCommands.removeAll(newCommands); + commands.clear(); + commands.addAll(deltaCommands); + break; + case RESET: + commands.clear(); + commands.addAll(parent.getOriginalCommands()); + break; + default: + assert false; + break; + } + } + + @Override + public boolean isSingle() { + return false; + } + + @Override + public Class getReturnType() { + return String.class; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "the sent server command list"; + } + +}