mirror of
https://github.com/EssentialsX/Essentials.git
synced 2025-01-03 06:57:39 +01:00
Asynchronously filter commands on Paper when possible (#4460)
Co-authored-by: MD <1917406+mdcfe@users.noreply.github.com> Co-authored-by: Josh Roy <10731363+JRoy@users.noreply.github.com>
This commit is contained in:
parent
d86b471402
commit
f0da17b75c
@ -13,6 +13,9 @@ import com.earth2me.essentials.utils.VersionUtil;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.events.AfkStatusChangeEvent;
|
||||
import net.ess3.provider.CommandSendListenerProvider;
|
||||
import net.ess3.provider.providers.BukkitCommandSendListenerProvider;
|
||||
import net.ess3.provider.providers.PaperCommandSendListenerProvider;
|
||||
import net.essentialsx.api.v2.events.AsyncUserDataLoadEvent;
|
||||
import org.bukkit.BanEntry;
|
||||
import org.bukkit.BanList;
|
||||
@ -37,7 +40,6 @@ import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.bukkit.event.player.PlayerBucketEmptyEvent;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||
import org.bukkit.event.player.PlayerCommandSendEvent;
|
||||
import org.bukkit.event.player.PlayerEggThrowEvent;
|
||||
import org.bukkit.event.player.PlayerFishEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
@ -68,6 +70,7 @@ import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
@ -101,6 +104,15 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isPaperCommandSendEvent() {
|
||||
try {
|
||||
Class.forName("com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent");
|
||||
return true;
|
||||
} catch (final ClassNotFoundException ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isArrowPickupEvent() {
|
||||
try {
|
||||
Class.forName("org.bukkit.event.player.PlayerPickupArrowEvent");
|
||||
@ -123,8 +135,10 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
ess.getServer().getPluginManager().registerEvents(new PickupListenerPre1_12(), ess);
|
||||
}
|
||||
|
||||
if (isCommandSendEvent()) {
|
||||
ess.getServer().getPluginManager().registerEvents(new CommandSendListener(), ess);
|
||||
if (isPaperCommandSendEvent()) {
|
||||
ess.getServer().getPluginManager().registerEvents(new PaperCommandSendListenerProvider(new CommandSendFilter()), ess);
|
||||
} else if (isCommandSendEvent()) {
|
||||
ess.getServer().getPluginManager().registerEvents(new BukkitCommandSendListenerProvider(new CommandSendFilter()), ess);
|
||||
}
|
||||
}
|
||||
|
||||
@ -975,15 +989,14 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
}
|
||||
}
|
||||
|
||||
private final class CommandSendListener implements Listener {
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onCommandSend(final PlayerCommandSendEvent event) {
|
||||
final User user = ess.getUser(event.getPlayer());
|
||||
|
||||
private final class CommandSendFilter implements CommandSendListenerProvider.Filter {
|
||||
@Override
|
||||
public Predicate<String> apply(Player player) {
|
||||
final User user = ess.getUser(player);
|
||||
final Set<PluginCommand> checked = new HashSet<>();
|
||||
final Set<PluginCommand> toRemove = new HashSet<>();
|
||||
|
||||
event.getCommands().removeIf(label -> {
|
||||
return label -> {
|
||||
if (isEssentialsCommand(label)) {
|
||||
final PluginCommand command = ess.getServer().getPluginCommand(label);
|
||||
if (!checked.contains(command)) {
|
||||
@ -995,25 +1008,21 @@ public class EssentialsPlayerListener implements Listener, FakeAccessor {
|
||||
return toRemove.contains(command);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (ess.getSettings().isDebug()) {
|
||||
ess.getLogger().info("Removed commands: " + toRemove.toString());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all of the following are true:
|
||||
* - The command is a plugin command
|
||||
* - The plugin command is from a plugin in an essentials-controlled package
|
||||
* - The plugin command is from an official EssentialsX plugin or addon
|
||||
* - There is no known alternative OR the alternative is overridden by Essentials
|
||||
*/
|
||||
private boolean isEssentialsCommand(final String label) {
|
||||
final PluginCommand command = ess.getServer().getPluginCommand(label);
|
||||
|
||||
return command != null
|
||||
&& (command.getPlugin() == ess || command.getPlugin().getClass().getName().startsWith("com.earth2me.essentials"))
|
||||
&& (ess.getSettings().isCommandOverridden(label) || (ess.getAlternativeCommandsHandler().getAlternative(label) == null));
|
||||
&& (command.getPlugin() == ess || command.getPlugin().getClass().getName().startsWith("com.earth2me.essentials") || command.getPlugin().getClass().getName().startsWith("net.essentialsx"))
|
||||
&& (ess.getSettings().isCommandOverridden(label) || (ess.getAlternativeCommandsHandler().getAlternative(label) == null));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,30 @@
|
||||
package net.ess3.provider;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A provider for 1.13+ command send listeners.
|
||||
* <p>
|
||||
* Note to maintainers: this doesn't extend {@link ProviderListener} because it doesn't make sense here.
|
||||
*/
|
||||
public abstract class CommandSendListenerProvider implements Provider, Listener {
|
||||
private final Filter commandFilter;
|
||||
|
||||
protected CommandSendListenerProvider(Filter commandFilter) {
|
||||
this.commandFilter = commandFilter;
|
||||
}
|
||||
|
||||
protected final Predicate<String> filter(final Player player) {
|
||||
return commandFilter.apply(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that returns a predicate to test whether commands should be hidden from the given player.
|
||||
*/
|
||||
public interface Filter extends Function<Player, Predicate<String>> {
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package net.ess3.provider.providers;
|
||||
|
||||
import net.ess3.provider.CommandSendListenerProvider;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.player.PlayerCommandSendEvent;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class BukkitCommandSendListenerProvider extends CommandSendListenerProvider {
|
||||
public BukkitCommandSendListenerProvider(Filter commandFilter) {
|
||||
super(commandFilter);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onCommandSend(PlayerCommandSendEvent event) {
|
||||
final Predicate<String> filter = filter(event.getPlayer());
|
||||
event.getCommands().removeIf(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Bukkit synchronous command send listener";
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ plugins {
|
||||
dependencies {
|
||||
implementation project(':providers:BaseProviders')
|
||||
compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT'
|
||||
compileOnly 'com.destroystokyo.paper:paper-mojangapi:1.16.5-R0.1-SNAPSHOT'
|
||||
}
|
||||
|
||||
essentials {
|
||||
|
@ -0,0 +1,35 @@
|
||||
package net.ess3.provider.providers;
|
||||
|
||||
import com.destroystokyo.paper.event.brigadier.AsyncPlayerSendCommandsEvent;
|
||||
import com.mojang.brigadier.tree.CommandNode;
|
||||
import net.ess3.provider.CommandSendListenerProvider;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class PaperCommandSendListenerProvider extends CommandSendListenerProvider {
|
||||
|
||||
public PaperCommandSendListenerProvider(Filter commandFilter) {
|
||||
super(commandFilter);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public void onAsyncCommandSend(@SuppressWarnings("deprecation") AsyncPlayerSendCommandsEvent<?> event) {
|
||||
if (!event.isAsynchronous() && event.hasFiredAsync()) {
|
||||
// this has already fired once async
|
||||
return;
|
||||
}
|
||||
|
||||
final Collection<? extends CommandNode<?>> children = event.getCommandNode().getChildren();
|
||||
final Predicate<String> filter = filter(event.getPlayer());
|
||||
|
||||
children.removeIf(node -> filter.test(node.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Paper async Brigadier command send listener";
|
||||
}
|
||||
}
|
@ -14,6 +14,9 @@ dependencyResolutionManagement {
|
||||
maven("https://repo.extendedclip.com/content/repositories/placeholderapi/") {
|
||||
content { includeGroup("me.clip") }
|
||||
}
|
||||
maven("https://libraries.minecraft.net/") {
|
||||
content { includeGroup("com.mojang") }
|
||||
}
|
||||
mavenCentral {
|
||||
content { includeGroup("net.kyori") }
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user