Compare commits

..
30 Commits
Author SHA1 Message Date
rayzsyt b53678764a Update version 2026-09-20 03:14:07 +02:00
rayzsyt 1f7743d089 Removed debug messages 2026-09-20 03:13:04 +02:00
rayzsyt a60b6896f7 Fixed that KICK_ON_FAILURE wasn't listened at anymore 2026-08-31 06:17:26 +02:00
rayzsyt 34c33df136 Add sanity check just in case 2026-08-25 22:37:13 +02:00
rayzsyt ef63674b0c Changed approach to detect commands for tab-completion 2026-08-21 19:11:06 +02:00
rayzsyt 130af1547d Ignore IgnoreStarPermission feature and instead made PAT able to recognise negated PAT permissions 2026-08-20 19:47:52 +02:00
rayzsyt cdb17c1ea8 Add option for PAT to ignore the Star permission 2026-08-19 22:32:55 +02:00
rayzsyt 8f4f4b6438 Remove debug message 2026-08-19 20:44:55 +02:00
rayzsyt 3a0fc6e579 Add feature to show non-existing commands in tab-completion when whitelisted, no matter if they exist or not. (Only for proxies in PAT groups) 2026-08-19 20:44:42 +02:00
rayzsyt e0747a5101 Fixed incompatibility issue with Skript commands 2026-08-15 23:48:46 +02:00
rayzsyt 5741dab763 Small logical change to improve performance by a tiny bit 2026-08-15 23:34:17 +02:00
rayzsyt 5d7a8bb4c5 Improved implementation of cached commands 2026-08-15 23:34:04 +02:00
rayzsyt 786b2fa560 Fixed logic when to send warning message 2026-08-15 23:33:51 +02:00
rayzsyt 5cf51052d2 Fixed exception when loading or reading list 2026-08-15 23:33:40 +02:00
rayzsyt 22eaecb17f Update version 2026-08-15 15:46:39 +02:00
rayzsyt 816354bb92 Implemented warning message when trying to use 'custom-unknown-command' feature while PAT is running in WHITELIST mode anyway 2026-08-15 15:43:27 +02:00
rayzsyt 2fc6d96bd9 Small adjustments 2026-08-15 15:43:00 +02:00
rayzsyt 3f472b0bf5 Moved REGISTER_CHANNELS to appropriate config section instead 2026-08-15 15:21:16 +02:00
rayzsyt 41417893be Implement hide-plugin-channels feature for Bungeecord 2026-08-15 15:20:54 +02:00
rayzsyt 64a7b80ec5 Implement hide-plugin-channels feature for Velocity 2026-08-15 15:04:05 +02:00
rayzsyt 65f136f2b8 Just moved a line bit further down lol 2026-08-15 15:03:15 +02:00
rayzsyt 618bee5e9b Implement plugin-spoofing fix via plugin-channels 2026-08-15 04:29:06 +02:00
rayzsyt ea377e4841 Update version 2026-08-13 17:00:58 +02:00
rayzsyt 6e1aa252c2 Switched List -> HashSet for better performance 2026-08-13 17:00:14 +02:00
rayzsyt 733f73a9b2 Register LuckPermsWarning Listener 2026-08-13 16:59:32 +02:00
rayzsyt 89b3fb65a2 Small logic changes 2026-08-12 15:29:49 +02:00
rayzsyt 148f24f516 Implemented notice message when trying to apply permissions using contexts 2026-08-12 00:00:10 +02:00
rayzsyt b80ad195ca Improved performance 2026-08-11 15:49:42 +02:00
rayzsyt 6e33bed086 Fixed BLACKLIST sub-argument filtering 2026-08-11 15:49:34 +02:00
rayzsyt 245e433ab9 Removed debug message 2026-08-10 22:21:56 +02:00
52 changed files with 1011 additions and 279 deletions

No files matched your search

+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>de.rayzs.pat</groupId>
<artifactId>ProAntiTab</artifactId>
<version>2.4.2</version>
<version>2.5.1</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
@@ -22,7 +22,7 @@ public class PATEventHandler {
return event;
}
public static FilteredSuggestionEvent callFilteredSuggestionEvents(CommandSender player, List<String> suggestions) {
public static FilteredSuggestionEvent callFilteredSuggestionEvents(CommandSender player, HashSet<String> suggestions) {
FilteredSuggestionEvent event = EmptyEvent.createEmptyFilteredSuggestionEvent(player, suggestions);
for (PATEvent patEvent : EVENTS) {
@@ -70,7 +70,7 @@ public class PATEventHandler {
return event;
}
public static UpdatePlayerCommandsEvent callUpdatePlayerCommandsEvents(CommandSender player, List<String> commands, boolean serverBased) {
public static UpdatePlayerCommandsEvent callUpdatePlayerCommandsEvents(CommandSender player, HashSet<String> commands, boolean serverBased) {
UpdatePlayerCommandsEvent event = EmptyEvent.createEmptyUpdatePlayerCommandsEvent(player, commands, serverBased);
for (PATEvent patEvent : EVENTS) {
@@ -143,7 +143,7 @@ public class PATEventHandler {
};
}
public static UpdatePlayerCommandsEvent createEmptyUpdatePlayerCommandsEvent(CommandSender player, List<String> commands, boolean serverBased) {
public static UpdatePlayerCommandsEvent createEmptyUpdatePlayerCommandsEvent(CommandSender player, HashSet<String> commands, boolean serverBased) {
return new UpdatePlayerCommandsEvent(player, commands, serverBased) {
@Override
public void handle(UpdatePlayerCommandsEvent event) {
@@ -170,7 +170,7 @@ public class PATEventHandler {
};
}
public static FilteredSuggestionEvent createEmptyFilteredSuggestionEvent(CommandSender player, List<String> suggestions) {
public static FilteredSuggestionEvent createEmptyFilteredSuggestionEvent(CommandSender player, HashSet<String> suggestions) {
return new FilteredSuggestionEvent(player, suggestions) {
@Override
public void handle(FilteredSuggestionEvent event) {
@@ -7,24 +7,24 @@ import java.util.*;
public abstract class FilteredSuggestionEvent extends PATEvent<FilteredSuggestionEvent> {
private List<String> suggestions;
private HashSet<String> suggestions;
public FilteredSuggestionEvent() {
super(null);
this.suggestions = null;
}
public FilteredSuggestionEvent(CommandSender player, List<String> suggestions) {
public FilteredSuggestionEvent(CommandSender player, HashSet<String> suggestions) {
super(player);
this.suggestions = suggestions;
}
public List<String> getSuggestions() {
public HashSet<String> getSuggestions() {
return suggestions;
}
public void setSuggestions(List<String> suggestions) {
public void setSuggestions(HashSet<String> suggestions) {
this.suggestions = suggestions;
}
}
@@ -3,25 +3,25 @@ package de.rayzs.pat.api.event.events;
import de.rayzs.pat.api.event.PATEvent;
import de.rayzs.pat.utils.sender.CommandSender;
import java.util.List;
import java.util.HashSet;
public abstract class UpdatePlayerCommandsEvent extends PATEvent<UpdatePlayerCommandsEvent> {
private List<String> commands;
private HashSet<String> commands;
private boolean serverBased;
public UpdatePlayerCommandsEvent() {
super(null);;
}
public UpdatePlayerCommandsEvent(CommandSender player, List<String> commands, boolean serverBased) {
public UpdatePlayerCommandsEvent(CommandSender player, HashSet<String> commands, boolean serverBased) {
super(player);
this.commands = commands;
this.serverBased = serverBased;
}
public List<String> getCommands() {
public HashSet<String> getCommands() {
return commands;
}
@@ -213,13 +213,13 @@ public class Storage {
associatedServers.forEach(serverName -> {
final List<UUID> playerIds = Storage.getLoader().getPlayerIdsByServer(serverName);
final List<String> commands = Blacklist.Collector.collectAllServerCommands(serverName);
final HashSet<String> commands = Blacklist.Collector.collectAllServerCommands(serverName);
playerIds.forEach(playerId -> {
final CommandSender sender = CommandSender.from(playerId);
final List<String> playerCommands = new ArrayList<>(commands);
final List<String> groupCommands = Blacklist.Collector.collectAllPlayerGroupCommands(sender, serverName);
final HashSet<String> playerCommands = new HashSet<>(commands);
final HashSet<String> groupCommands = Blacklist.Collector.collectAllPlayerGroupCommands(sender, serverName);
playerCommands.addAll(groupCommands);
@@ -236,9 +236,9 @@ public class Storage {
playerIds.forEach(playerId -> {
final CommandSender sender = CommandSender.from(playerId);
final List<String> serverCommands = Blacklist.Collector.collectAllServerCommands(sender.getServerName());
final List<String> playerCommands = new ArrayList<>(serverCommands);
final List<String> groupCommands = Blacklist.Collector.collectAllPlayerGroupCommands(sender, sender.getServerName());
final HashSet<String> serverCommands = Blacklist.Collector.collectAllServerCommands(sender.getServerName());
final HashSet<String> playerCommands = new HashSet<>(serverCommands);
final HashSet<String> groupCommands = Blacklist.Collector.collectAllPlayerGroupCommands(sender, sender.getServerName());
playerCommands.addAll(groupCommands);
@@ -304,13 +304,12 @@ public class Storage {
return false;
}
public static boolean isServer(String originServer, String targetServer) {
originServer = originServer.toLowerCase();
targetServer = targetServer.toLowerCase();
public static boolean isServer(final String originServer, final String targetServer) {
if (originServer.endsWith("*")) {
originServer = originServer.substring(0, originServer.length() - 2);
return targetServer.startsWith(originServer);
return StringUtils.startsWithIgnoreCase(
originServer.substring(0, originServer.length() - 2),
targetServer
);
}
return originServer.equalsIgnoreCase(targetServer);
@@ -336,8 +335,11 @@ public class Storage {
public static final AllowGroupOverrulingSection ALLOW_GROUP_OVERRULING = new AllowGroupOverrulingSection();
public static final AutoLowercaseCommandsSection AUTO_LOWERCASE_COMMANDS = new AutoLowercaseCommandsSection();
public static final TurnBlacklistToWhitelistSection TURN_BLACKLIST_TO_WHITELIST = new TurnBlacklistToWhitelistSection();
public static final BlockNamespaceCommandsSection BLOCK_NAMESPACE_COMMANDS = new BlockNamespaceCommandsSection();
public static final HandleThroughProxySection HANDLE_THROUGH_PROXY = new HandleThroughProxySection();
public static final HidePluginChannelsSection HIDE_PLUGIN_CHANNELS = new HidePluginChannelsSection();
public static final TabCompletionForNotExistingCommandsSection TAB_COMPLETION_FOR_NOT_EXISTING_COMMANDS = new TabCompletionForNotExistingCommandsSection();
public static final InjectionFailedSection INJECTION_FAILED = new InjectionFailedSection();
public static final PatchExploitSection PATCH_EXPLOITS = new PatchExploitSection();
public static final CustomBrandSection CUSTOM_BRAND = new CustomBrandSection();
@@ -349,7 +351,6 @@ public class Storage {
public static final ForwardLuckPermsChangesSection FORWARD_LUCK_PERMS_CHANGES_SECTION = new ForwardLuckPermsChangesSection();
public static final CustomProtocolPingSection CUSTOM_PROTOCOL_PING = new CustomProtocolPingSection();
public static final CustomUnknownCommandSection CUSTOM_UNKNOWN_COMMAND = new CustomUnknownCommandSection();
public static final TurnBlacklistToWhitelistSection TURN_BLACKLIST_TO_WHITELIST = new TurnBlacklistToWhitelistSection();
public static final BaseCommandCaseSensitiveSection BASE_COMMAND_CASE_SENSITIVE = new BaseCommandCaseSensitiveSection();
public static final UpdateGroupsPerWorldSection UPDATE_GROUPS_PER_WORLD = new UpdateGroupsPerWorldSection();
public static final UpdateGroupsPerServerSection UPDATE_GROUPS_PER_SERVER = new UpdateGroupsPerServerSection();
@@ -450,8 +451,8 @@ public class Storage {
* @param serverName Target server name.
* @return List of collected commands.
*/
public static List<String> collectAllServerCommands(String serverName) {
List<String> commands = new ArrayList<>(Blacklist.getBlacklist().getCommands());
public static HashSet<String> collectAllServerCommands(String serverName) {
HashSet<String> commands = new HashSet<>(Blacklist.getBlacklist().getCommands());
if (!Reflection.isProxyServer())
return commands;
@@ -473,9 +474,9 @@ public class Storage {
* @param serverName Target server name.
* @return List of collected commands.
*/
public static List<String> collectAllPlayerGroupCommands(CommandSender sender, String serverName) {
final List<String> commands = new ArrayList<>();
final List<Group> groups = GroupManager.getPlayerGroups(sender);
public static HashSet<String> collectAllPlayerGroupCommands(CommandSender sender, String serverName) {
final HashSet<String> commands = new HashSet<>();
final List<Group> groups = GroupManager.getPlayerGroups(sender, sender.isOperator());
if (serverName == null) {
groups.forEach(group -> commands.addAll(group.getCommands()));
@@ -608,28 +609,63 @@ public class Storage {
return IGNORED_SERVERS.isListed(server);
}
public static boolean canPlayerAccess(CommandSender sender, List<Group> groups, String command, BlockType type) {
return canPlayerAccess(sender, groups, command, type, null);
public static boolean canPlayerAccess(
final CommandSender sender,
final List<Group> groups,
final String command,
final BlockType type,
final boolean isOperator
) {
return canPlayerAccess(sender, groups, command, type, null, isOperator);
}
public static boolean canPlayerAccessChat(CommandSender sender, List<Group> groups, String command) {
return canPlayerAccess(sender, groups, command, BlockType.CHAT, null);
public static boolean canPlayerAccessChat(
final CommandSender sender,
final List<Group> groups,
final String command,
final boolean isOperator
) {
return canPlayerAccess(sender, groups, command, BlockType.CHAT, null, isOperator);
}
public static boolean canPlayerAccessChat(CommandSender sender, List<Group> groups, String command, String server) {
return canPlayerAccess(sender, groups, command, BlockType.CHAT, server);
public static boolean canPlayerAccessChat(
final CommandSender sender,
final List<Group> groups,
final String command,
final String server,
final boolean isOperator
) {
return canPlayerAccess(sender, groups, command, BlockType.CHAT, server, isOperator);
}
public static boolean canPlayerAccessTab(CommandSender sender, List<Group> groups, String command) {
return canPlayerAccess(sender, groups, command, BlockType.TAB, null);
public static boolean canPlayerAccessTab(
final CommandSender sender,
final List<Group> groups,
final String command,
final boolean isOperator
) {
return canPlayerAccess(sender, groups, command, BlockType.TAB, null, isOperator);
}
public static boolean canPlayerAccessTab(CommandSender sender, List<Group> groups, String command, String server) {
return canPlayerAccess(sender, groups, command, BlockType.TAB, server);
public static boolean canPlayerAccessTab(
final CommandSender sender,
final List<Group> groups,
final String command,
final String server,
final boolean isOperator
) {
return canPlayerAccess(sender, groups, command, BlockType.TAB, server, isOperator);
}
public static boolean canPlayerAccess(CommandSender sender, List<Group> groups, String command, BlockType type, String server) {
public static boolean canPlayerAccess(
final CommandSender sender,
final List<Group> groups,
final String command,
final BlockType type,
final String server,
final boolean isOperator
) {
final boolean allowGroupOverruling = ConfigSections.Settings.ALLOW_GROUP_OVERRULING.ENABLED;
final boolean blocked = isBlocked(command, type, server);
@@ -644,7 +680,7 @@ public class Storage {
}
if (Storage.getPermissionPlugin() != PermissionPlugin.NONE) {
if (PermissionUtil.hasBypassPermission(sender, command)) {
if (PermissionUtil.hasBypassPermission(sender, command, isOperator)) {
return true;
}
}
@@ -658,7 +694,7 @@ public class Storage {
}
if (Storage.getPermissionPlugin() != PermissionPlugin.NONE) {
if (PermissionUtil.hasBypassPermission(sender, command)) {
if (PermissionUtil.hasBypassPermission(sender, command, isOperator)) {
return true;
}
}
@@ -30,10 +30,10 @@ public class BlockNamespaceCommandsSection extends ConfigStorage {
return false;
}
return StringUtils.getFirstArg(command).contains(":");
return StringUtils.getFirstArg(command).indexOf(':') != -1;
}
public boolean doesBypass(CommandSender sender) {
return !ENABLED || PermissionUtil.hasPermission(sender, "namespace");
public boolean doesBypass(final CommandSender sender, final boolean isOperator) {
return !ENABLED || PermissionUtil.hasPermission(sender, "namespace", isOperator);
}
}
@@ -38,6 +38,7 @@ public class CustomPluginsSection extends ConfigStorage {
if (currentCommand.equalsIgnoreCase(command))
return true;
}
return false;
}
}
@@ -1,6 +1,7 @@
package de.rayzs.pat.api.storage.config.settings;
import de.rayzs.pat.api.storage.storages.ConfigStorage;
import de.rayzs.pat.plugin.logger.Logger;
import de.rayzs.pat.utils.configuration.helper.*;
import de.rayzs.pat.api.storage.Storage;
import java.util.Collections;
@@ -18,8 +19,15 @@ public class CustomUnknownCommandSection extends ConfigStorage {
public void load() {
super.load();
if(Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) return;
if (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) return;
ENABLED = new ConfigSectionHelper<Boolean>(this, "enabled", true).getOrSet();
MESSAGE = new MultipleMessagesHelper(this, "message", Collections.singletonList("&cThis command does not exist!"));
if (ENABLED && Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED) {
Logger.warning("It's not recommended to use the 'custom-unknown-command' feature when you are already using ProAntiTab in WHITELIST mode! Since in this mode, all commands except the once you specifically allow, are blocked anyway. So instead, change the 'blocked' message to your desired message. It has the same effect.");
}
}
}
@@ -0,0 +1,37 @@
package de.rayzs.pat.api.storage.config.settings;
import de.rayzs.pat.api.storage.storages.ConfigStorage;
import de.rayzs.pat.utils.configuration.helper.ConfigSectionHelper;
import de.rayzs.pat.utils.configuration.helper.MultipleMessagesHelper;
import java.util.Arrays;
import java.util.HashSet;
public class HidePluginChannelsSection extends ConfigStorage {
public boolean ENABLED;
public MultipleMessagesHelper WHITELISTED_CHANNELS;
private final HashSet<String> REGISTER_CHANNELS = new HashSet<>(
Arrays.asList("register", "unregister", "minecraft:register", "minecraft:unregister")
);
public HidePluginChannelsSection() {
super("plugin-channels-hider");
}
@Override
public void load() {
super.load();
ENABLED = new ConfigSectionHelper<Boolean>(this, "enabled", false).getOrSet();
WHITELISTED_CHANNELS = new MultipleMessagesHelper(this, "whitelisted-channels", Arrays.asList(
"minecraft:brand",
"bungeecord:main",
"velocity:main"
));
}
public boolean isRegisterChannel(final String channelId) {
return REGISTER_CHANNELS.contains(channelId);
}
}
@@ -0,0 +1,22 @@
package de.rayzs.pat.api.storage.config.settings;
import de.rayzs.pat.api.storage.storages.ConfigStorage;
import de.rayzs.pat.utils.Reflection;
import de.rayzs.pat.utils.configuration.helper.ConfigSectionHelper;
public class TabCompletionForNotExistingCommandsSection extends ConfigStorage {
public boolean ENABLED;
public TabCompletionForNotExistingCommandsSection() {
super("tab-completion-for-not-existing-commands");
}
@Override
public void load() {
super.load();
if (!Reflection.isProxyServer()) return;
ENABLED = new ConfigSectionHelper<Boolean>(this, null, false).getOrSet();
}
}
@@ -9,7 +9,7 @@ import java.util.*;
public class BlacklistStorage extends StorageTemplate implements Serializable {
private List<String> commands = new ArrayList<>();
private Set<String> hiddenCommands = new HashSet<>();
private HashSet<String> hiddenCommands = new HashSet<>();
public BlacklistStorage(String navigatePath) {
super(Storage.Files.STORAGE, navigatePath);
@@ -80,7 +80,7 @@ public class BlacklistStorage extends StorageTemplate implements Serializable {
commands = (ArrayList<String>) getConfig().getOrSet(getNavigatePath(), commands);
final List<String> tmpCommands = commands != null ? new ArrayList<>(commands) : new ArrayList<>();
final Set<String> pluginListCommands = new HashSet<>(), negatedPluginListCommands = new HashSet<>();
final HashSet<String> pluginListCommands = new HashSet<>(), negatedPluginListCommands = new HashSet<>();
final String pluginCommandPrefix = "plugin=";
final String negatedPluginCommandPrefix = Storage.Blacklist.BlockType.NEGATE + pluginCommandPrefix;
@@ -45,9 +45,9 @@ import java.util.stream.Collectors;
public class BukkitLoader extends JavaPlugin implements PluginLoader {
private static List<String> commands = new ArrayList<>(),
allowedCommands = new ArrayList<>(),
disallowedCommands = new ArrayList<>();
private static List<String> allCommands = new ArrayList<>(),
allowedCommands = new ArrayList<>(),
disallowedCommands = new ArrayList<>();
private static Plugin plugin;
private static java.util.logging.Logger logger;
@@ -55,6 +55,7 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
private final CommandsCache commandsCache = new CommandsCache();
private final List<String> offlinePlayerNames = new ArrayList<>();
private HashSet<String> registeredCommands = new HashSet<>();
private Map<String, Command> commandsMap = null;
private BukkitAntiTabListener bukkitAntiTabListener = null;
@@ -124,6 +125,8 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
startUpdaterTask();
if (getServer().getPluginManager().getPlugin("LuckPerms") != null) {
manager.registerEvents(new BukkitLuckPermsWarning(), this);
LuckPermsHook.initialize();
Bukkit.getOnlinePlayers().forEach(player -> PermissionUtil.setPlayerPermissions(player.getUniqueId()));
} else {
@@ -233,9 +236,7 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
if (commandsMap == null)
return false;
loadAllCommands();
return getAllCommands().contains(command);
return registeredCommands.contains(command);
}
@Override
@@ -353,12 +354,10 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
}
public static List<String> getAllCommands() {
return new ArrayList<>(commands);
return allCommands;
}
public static List<String> getAllowedCommands() {
return new ArrayList<>(allowedCommands);
}
public static List<String> getAllowedCommands() { return allowedCommands; }
public static List<String> getDisallowedCommands() {
return disallowedCommands;
@@ -440,50 +439,47 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
}
private void loadAllCommands() {
if (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) return;
if (lastCommandsLoad != -1 && System.currentTimeMillis() - lastCommandsLoad < 1000)
return;
List<String> result = new ArrayList<>();
final HashSet<String> tmpCommands = new HashSet<>(Bukkit.getHelpMap().getHelpTopics().stream()
.map(topic -> {
String name = topic.getName();
if (commandsMap == null) {
result.addAll(
Bukkit.getHelpMap().getHelpTopics().stream()
.map(topic -> {
String name = topic.getName();
if (name.startsWith("/"))
name = name.substring(1);
if (name.startsWith("/"))
name = name.substring(1);
return name;
}).toList()
);
return;
}
return name;
}).toList());
commandsMap.entrySet().forEach(entry -> {
String key = entry.getKey();
Command command = entry.getValue();
final String key = entry.getKey();
final Command command = entry.getValue();
result.add(key);
tmpCommands.add(key);
if (!command.getAliases().isEmpty()) {
result.addAll(command.getAliases());
tmpCommands.addAll(command.getAliases());
}
});
boolean turn = Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED;
List<String> allowedCommands = new ArrayList<>(result).stream().filter(command -> {
boolean contains = Storage.Blacklist.getBlacklist().getCommands().contains(command);
final boolean turn = Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED;
final List<String> tmpAllowedCommands = tmpCommands.stream().filter(command -> {
final boolean contains = Storage.Blacklist.getBlacklist().getCommands().contains(command);
return turn == contains;
}).toList();
final List<String> tmpDisallowedCommands = tmpCommands.stream().filter(command ->
!allowedCommands.contains(command)
).toList();
lastCommandsLoad = System.currentTimeMillis();
BukkitLoader.commands = result;
BukkitLoader.allowedCommands = allowedCommands;
BukkitLoader.disallowedCommands = commands.stream().filter(command -> !allowedCommands.contains(command)).toList();
registeredCommands = tmpCommands;
allowedCommands = tmpAllowedCommands;
disallowedCommands = tmpDisallowedCommands;
}
public static Plugin getPlugin() {
@@ -85,8 +85,10 @@ public class BungeeLoader extends Plugin implements PluginLoader {
startUpdaterTask();
if (manager.getPlugin("LuckPerms") != null)
if (manager.getPlugin("LuckPerms") != null) {
manager.registerListener(this, new BungeeLuckPermsWarning());
LuckPermsHook.initialize();
}
if(manager.getPlugin("PAPIProxyBridge") != null) {
Storage.USE_PAPIPROXYBRIDGE = true;
@@ -42,7 +42,7 @@ import java.util.*;
@Plugin(name = "ProAntiTab",
id = "proantitab",
version = "2.4.2",
version = "2.5.1",
authors = "Rayzs_YT",
description = "Hides more than just your plugins.",
url = "https://www.rayzs.de/products/proantitab/page",
@@ -104,8 +104,10 @@ public class VelocityLoader implements PluginLoader {
startUpdaterTask();
if (server.getPluginManager().getPlugin("luckperms").isPresent())
if (server.getPluginManager().getPlugin("luckperms").isPresent()) {
server.getEventManager().register(this, new VelocityLuckPermsWarning(server));
LuckPermsHook.initialize();
}
if (server.getPluginManager().getPlugin("papiproxybridge").isPresent()) {
Storage.USE_PAPIPROXYBRIDGE = true;
@@ -66,9 +66,10 @@ public class CommandProcess {
}
public static void handleCommand(Object senderObj, String[] args, String label) {
CommandSender sender = CommandSender.from(senderObj);
final CommandSender sender = CommandSender.from(senderObj);
final boolean isOperator = sender.isOperator();
if (!PermissionUtil.hasPermissionWithResponse(sender, "use"))
if (!PermissionUtil.hasPermissionWithResponse(sender, "use", isOperator))
return;
if (args.length == 0) {
@@ -109,7 +110,7 @@ public class CommandProcess {
}
ProCommand command = optCommand.get();
if (!PermissionUtil.hasPermissionWithResponse(sender, command.getName()))
if (!PermissionUtil.hasPermissionWithResponse(sender, command.getName(), isOperator))
return;
if (!command.execute(sender, commandArgs)) {
@@ -137,7 +138,7 @@ public class CommandProcess {
}
ProCommand command = optCommand.get();
if (!PermissionUtil.hasPermissionWithResponse(sender, command.getName()))
if (!PermissionUtil.hasPermissionWithResponse(sender, command.getName(), isOperator))
return;
if (!command.execute(sender, commandArgs)) {
@@ -147,10 +148,11 @@ public class CommandProcess {
}
public static List<String> handleTabComplete(Object senderObj, String[] args) {
CommandSender sender = CommandSender.from(senderObj);
List<String> result = new ArrayList<>();
final CommandSender sender = CommandSender.from(senderObj);
final boolean isOperator = sender.isOperator();
final List<String> result = new ArrayList<>();
if (!PermissionUtil.hasPermission(sender, "use"))
if (!PermissionUtil.hasPermission(sender, "use", isOperator))
return result;
if (args.length <= 1) {
@@ -164,7 +166,7 @@ public class CommandProcess {
if (!Reflection.isProxyServer() && cmd.isProxyOnly())
return false;
return PermissionUtil.hasPermission(sender, cmd.getName());
return PermissionUtil.hasPermission(sender, cmd.getName(), isOperator);
})
.forEach(cmd -> {
result.add(cmd.getName());
@@ -185,7 +187,7 @@ public class CommandProcess {
.filter(cmd -> {
if (Reflection.isProxyServer() && cmd.isServerCommand())
return PermissionUtil.hasPermission(sender, cmd.getName());
return PermissionUtil.hasPermission(sender, cmd.getName(), isOperator);
return false;
})
@@ -206,7 +208,7 @@ public class CommandProcess {
optCommand = COMMANDS.stream().filter(cmd -> {
if (Reflection.isProxyServer() && cmd.isServerCommand()) {
return cmd.isCommand(servCommandName) && PermissionUtil.hasPermission(sender, cmd.getName());
return cmd.isCommand(servCommandName) && PermissionUtil.hasPermission(sender, cmd.getName(), isOperator);
}
return false;
@@ -231,7 +233,7 @@ public class CommandProcess {
if (optCommand.isPresent()) {
ProCommand command = optCommand.get();
if (PermissionUtil.hasPermission(sender, command.getName())) {
if (PermissionUtil.hasPermission(sender, command.getName(), isOperator)) {
List<String> cmdCompletions = command.tabComplete(sender, commandArgs);
result.addAll(cmdCompletions != null ? cmdCompletions : List.of());
}
@@ -24,15 +24,17 @@ public class BukkitAntiTabListener implements Listener {
@EventHandler (priority = EventPriority.LOWEST)
public void onPlayerCommandSend(PlayerCommandSendEvent event) {
final Player player = event.getPlayer();
final CommandSender sender = CommandSender.from(player);
final UUID uuid = player.getUniqueId();
if (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) {
return;
}
final Player player = event.getPlayer();
final CommandSender sender = CommandSender.from(player);
final UUID uuid = player.getUniqueId();
final boolean isOperator = player.isOp();
if (player.isOp()) {
if (!knownOperators.contains(uuid)) {
knownOperators.add(uuid);
@@ -50,12 +52,12 @@ public class BukkitAntiTabListener implements Listener {
: BukkitLoader.getAllCommands()
);
if (!player.isOp() && knownOperators.contains(uuid)) {
if (!isOperator && knownOperators.contains(uuid)) {
knownOperators.remove(uuid);
PermissionUtil.reloadPermissions(sender);
}
if (PermissionUtil.hasBypassPermission(sender)) {
if (PermissionUtil.hasBypassPermission(sender, isOperator)) {
return;
}
@@ -66,17 +68,16 @@ public class BukkitAntiTabListener implements Listener {
return;
}
final List<Group> groups = GroupManager.getPlayerGroups(sender);
final List<String> playerCommands = Storage.getLoader().getBukkitCommandsCacheMap().getPlayerCommands(new ArrayList<>(event.getCommands()), sender, groups);
final List<Group> groups = GroupManager.getPlayerGroups(sender, isOperator);
final HashSet<String> playerCommands = Storage.getLoader().getBukkitCommandsCacheMap().getPlayerCommands(new ArrayList<>(event.getCommands()), sender, groups, isOperator);
final FilteredSuggestionEvent filteredSuggestionEvent = PATEventHandler.callFilteredSuggestionEvents(sender, playerCommands);
event.getCommands().clear();
if (filteredSuggestionEvent.isCancelled()) {
event.getCommands().clear();
return;
}
event.getCommands().addAll(filteredSuggestionEvent.getSuggestions());
event.getCommands().removeIf(command -> !filteredSuggestionEvent.getSuggestions().contains(command));
if (Storage.ConfigSections.Settings.CUSTOM_PLUGIN.ALWAYS_TAB_COMPLETABLE) {
event.getCommands().addAll(Storage.ConfigSections.Settings.CUSTOM_PLUGIN.COMMANDS.getLines());
@@ -30,23 +30,18 @@ public class BukkitBlockCommandListener implements Listener {
final Player player = event.getPlayer();
final CommandSender sender = CommandSender.from(player);
final World world = player.getWorld();
final boolean isOperator = player.isOp();
String rawCommand = StringUtils.getFirstArg(event.getMessage()),
command = rawCommand.substring(1);
if (!Storage.ConfigSections.Settings.CUSTOM_UNKNOWN_COMMAND.ENABLED || event.isCancelled()) return;
if (PermissionUtil.hasBypassPermission(sender))
if (PermissionUtil.hasBypassPermission(sender, isOperator))
return;
/* Removed since not necessary and only takes up unnecessary performance.
if (Storage.getLoader().doesCommandExist(command))
return;
*/
if (Bukkit.getHelpMap().getHelpTopic(rawCommand) != null)
return;
event.setCancelled(true);
MessageTranslator.send(player, Storage.ConfigSections.Settings.CUSTOM_UNKNOWN_COMMAND.MESSAGE, "%command%", command, "%world%", world.getName());
@@ -56,6 +51,7 @@ public class BukkitBlockCommandListener implements Listener {
public void onPlayerCommandProcess(PlayerCommandPreprocessEvent event) {
final Player player = event.getPlayer();
final CommandSender sender = CommandSender.from(player);
final boolean isOperator = player.isOp();
final String commandFirstArg = StringUtils.getFirstArg(event.getMessage());
@@ -88,7 +84,7 @@ public class BukkitBlockCommandListener implements Listener {
return;
}
if (PermissionUtil.hasBypassPermission(sender, command)) {
if (PermissionUtil.hasBypassPermission(sender, command, isOperator)) {
return;
}
@@ -145,12 +141,12 @@ public class BukkitBlockCommandListener implements Listener {
}
final boolean cancelBlockedCommand = Storage.ConfigSections.Settings.CANCEL_COMMAND.ENABLED;
final List<Group> groups = GroupManager.getPlayerGroups(sender);
final List<Group> groups = GroupManager.getPlayerGroups(sender, isOperator);
boolean allowed = Storage.Blacklist.canPlayerAccessChat(sender, groups, command);
boolean allowed = Storage.Blacklist.canPlayerAccessChat(sender, groups, command, isOperator);
boolean blockedNamespace = false;
if (!Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesBypass(sender)) {
if (!Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesBypass(sender, isOperator)) {
blockedNamespace = cancelBlockedCommand
? Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.isCommand(command)
: Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesAlwaysBlock(command);
@@ -0,0 +1,51 @@
package de.rayzs.pat.plugin.listeners.bukkit;
import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.utils.LuckPermsWarning;
import de.rayzs.pat.utils.scheduler.PATScheduler;
import de.rayzs.pat.utils.sender.CommandSender;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.server.ServerCommandEvent;
public class BukkitLuckPermsWarning implements Listener {
@EventHandler
public void onConsoleCommandExecution(final ServerCommandEvent event) {
if (LuckPermsWarning.alreadyAnnounced()) return;
if (Storage.ConfigSections.Settings.UPDATE_GROUPS_PER_WORLD.ENABLED || Storage.ConfigSections.Settings.UPDATE_GROUPS_PER_SERVER.ENABLED) {
return;
}
final CommandSender sender = CommandSender.from(event.getSender());
final String command = event.getCommand();
if (LuckPermsWarning.shouldSendLuckPermsWarning(sender, command)) {
PATScheduler.createScheduler(() -> {
LuckPermsWarning.sendAnnouncement(sender);
}, 20);
}
}
@EventHandler
public void onPlayerCommandExecution(final PlayerCommandPreprocessEvent event) {
if (LuckPermsWarning.alreadyAnnounced()) return;
if (Storage.ConfigSections.Settings.UPDATE_GROUPS_PER_WORLD.ENABLED || Storage.ConfigSections.Settings.UPDATE_GROUPS_PER_SERVER.ENABLED) {
return;
}
final CommandSender sender = CommandSender.from(event.getPlayer());
final String command = event.getMessage();
if (LuckPermsWarning.shouldSendLuckPermsWarning(sender, command.substring(1))) {
PATScheduler.createScheduler(() -> {
LuckPermsWarning.sendAnnouncement(sender);
}, 20);
}
}
}
@@ -25,6 +25,7 @@ public class BukkitPlayerListener implements Listener {
public void onPlayerJoin(PlayerJoinEvent event) {
final Player player = event.getPlayer();
final CommandSender sender = CommandSender.from(player);
final boolean isOperator = player.isOp();
PATEventHandler.callServerPlayersChangeEvents(sender, ServerPlayersChangeEvent.Type.JOINED);
SubArgument.get().updateCachedPlayerNames();
@@ -74,7 +75,7 @@ public class BukkitPlayerListener implements Listener {
}, 10);
}
if (Storage.OUTDATED && PermissionUtil.hasPermission(sender, "joinupdate")) {
if (Storage.OUTDATED && PermissionUtil.hasPermission(sender, "joinupdate", isOperator)) {
PATScheduler.createScheduler(() -> {
if (player.isOnline()) {
MessageTranslator.send(player, Storage.ConfigSections.Settings.UPDATE.OUTDATED.getLines());
@@ -50,13 +50,13 @@ public class BungeeAntiTabListener implements Listener {
if (Storage.Blacklist.isDisabledServer(serverName))
return;
if (PermissionUtil.hasBypassPermission(sender))
if (PermissionUtil.hasBypassPermission(sender, false))
return;
final List<Group> groups = GroupManager.getPlayerGroups(sender);
final boolean doesBypassNamespace = Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesBypass(sender);
final List<Group> groups = GroupManager.getPlayerGroups(sender, false);
final boolean doesBypassNamespace = Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesBypass(sender, false);
final boolean spaces = cursor.contains(" ");
boolean cancelsBeforeHand = false;
@@ -66,7 +66,7 @@ public class BungeeAntiTabListener implements Listener {
}
if (!cancelsBeforeHand && !cursor.isEmpty()) {
cancelsBeforeHand = !Storage.Blacklist.canPlayerAccessTab(sender, groups, StringUtils.getFirstArg(cursor), serverName);
cancelsBeforeHand = !Storage.Blacklist.canPlayerAccessTab(sender, groups, StringUtils.getFirstArg(cursor), serverName, false);
}
if (!cancelsBeforeHand) {
@@ -100,7 +100,7 @@ public class BungeeAntiTabListener implements Listener {
return false;
}
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, cpy, serverName);
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, cpy, serverName, false);
});
}
@@ -36,7 +36,7 @@ public class BungeeBlockCommandListener implements Listener {
String command = event.getMessage();
if (PermissionUtil.hasBypassPermission(sender, command) || Storage.Blacklist.isDisabledServer(serverName))
if (PermissionUtil.hasBypassPermission(sender, command, false) || Storage.Blacklist.isDisabledServer(serverName))
return;
command = command.startsWith("/") ? command.substring(1) : command;
@@ -104,13 +104,13 @@ public class BungeeBlockCommandListener implements Listener {
return;
}
final List<Group> groups = GroupManager.getPlayerGroups(sender);
final List<Group> groups = GroupManager.getPlayerGroups(sender, false);
final boolean cancelBlockedCommand = Storage.ConfigSections.Settings.CANCEL_COMMAND.ENABLED;
boolean allowed = Storage.Blacklist.canPlayerAccessChat(sender, groups, command, serverName);
boolean allowed = Storage.Blacklist.canPlayerAccessChat(sender, groups, command, serverName, false);
boolean blockedNamespace = false;
if (!Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesBypass(sender)) {
if (!Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesBypass(sender, false)) {
blockedNamespace = cancelBlockedCommand
? Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.isCommand(command)
: Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesAlwaysBlock(command);
@@ -0,0 +1,40 @@
package de.rayzs.pat.plugin.listeners.bungee;
import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.plugin.BukkitLoader;
import de.rayzs.pat.plugin.BungeeLoader;
import de.rayzs.pat.utils.LuckPermsWarning;
import de.rayzs.pat.utils.sender.CommandSender;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.event.ChatEvent;
import net.md_5.bungee.api.plugin.Listener;
import net.md_5.bungee.event.EventHandler;
import java.util.concurrent.TimeUnit;
public class BungeeLuckPermsWarning implements Listener {
@EventHandler
public void onPlayerCommandExecution(final ChatEvent event) {
if (LuckPermsWarning.alreadyAnnounced()) return;
if (Storage.ConfigSections.Settings.UPDATE_GROUPS_PER_WORLD.ENABLED || Storage.ConfigSections.Settings.UPDATE_GROUPS_PER_SERVER.ENABLED) {
return;
}
if (! (event.getSender() instanceof ProxiedPlayer player)) return;
final CommandSender sender = CommandSender.from(player);
final String command = event.getMessage();
if (LuckPermsWarning.shouldSendLuckPermsWarning(sender, command.substring(1))) {
ProxyServer.getInstance().getScheduler().schedule(
BungeeLoader.getPlugin(),
() -> LuckPermsWarning.sendAnnouncement(sender),
1, TimeUnit.SECONDS
);
}
}
}
@@ -36,7 +36,7 @@ public class BungeePlayerConnectionListener implements Listener {
PermissionUtil.setPlayerPermissions(sender);
if (Storage.OUTDATED && PermissionUtil.hasPermission(sender, "joinupdate")) {
if (Storage.OUTDATED && PermissionUtil.hasPermission(sender, "joinupdate", false)) {
ProxyServer.getInstance().getScheduler().schedule(BungeeLoader.getPlugin(), () -> {
if (player.isConnected()) {
MessageTranslator.send(player, Storage.ConfigSections.Settings.UPDATE.OUTDATED, "%player%", player.getName());
@@ -1,9 +1,6 @@
package de.rayzs.pat.plugin.listeners.bungee;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import de.rayzs.pat.api.event.PATEventHandler;
import de.rayzs.pat.api.event.events.FilteredSuggestionEvent;
@@ -32,11 +29,11 @@ public class WaterfallAntiTabListener implements Listener {
final CommandSender sender = CommandSender.from(player);
final String serverName = player.getServer().getInfo().getName();
if (Storage.Blacklist.isDisabledServer(serverName) || PermissionUtil.hasBypassPermission(sender)) {
if (Storage.Blacklist.isDisabledServer(serverName) || PermissionUtil.hasBypassPermission(sender, false)) {
return;
}
final List<Group> groups = GroupManager.getPlayerGroups(sender);
final List<Group> groups = GroupManager.getPlayerGroups(sender, false);
final Map<String, CommandsCache> cache = Storage.getLoader().getPerServerCommandsCacheMap();
if (!cache.containsKey(serverName)) {
@@ -50,7 +47,7 @@ public class WaterfallAntiTabListener implements Listener {
event.getCommands().forEach((key, value) -> commandsAsString.add(key));
commandsCache.handleCommands(commandsAsString, serverName);
List<String> playerCommands = commandsCache.getPlayerCommands(commandsAsString, sender, groups, serverName);
HashSet<String> playerCommands = commandsCache.getPlayerCommands(commandsAsString, sender, groups, serverName, false);
event.getCommands().entrySet().removeIf(command -> {
if (Storage.ConfigSections.Settings.CUSTOM_PLUGIN.isTabCompletable(command.getKey()) || Storage.ConfigSections.Settings.CUSTOM_VERSION.isTabCompletable(command.getKey())) {
@@ -60,7 +57,7 @@ public class WaterfallAntiTabListener implements Listener {
return playerCommands.contains(command.getKey());
});
FilteredSuggestionEvent filteredSuggestionEvent = PATEventHandler.callFilteredSuggestionEvents(sender, new ArrayList<>(event.getCommands().keySet()));
FilteredSuggestionEvent filteredSuggestionEvent = PATEventHandler.callFilteredSuggestionEvents(sender, new HashSet<>(event.getCommands().keySet()));
if (filteredSuggestionEvent.isCancelled()) event.getCommands().clear();
for (String commandName : filteredSuggestionEvent.getSuggestions()) {
@@ -1,6 +1,7 @@
package de.rayzs.pat.plugin.listeners.velocity;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -23,10 +24,10 @@ import de.rayzs.pat.utils.sender.CommandSender;
public class VelocityAntiTabListener {
private static ProxyServer server;
private final ProxyServer server;
public VelocityAntiTabListener(ProxyServer server) {
VelocityAntiTabListener.server = server;
this.server = server;
}
@Subscribe (order = PostOrder.LAST)
@@ -45,21 +46,21 @@ public class VelocityAntiTabListener {
final CommandSender sender = CommandSender.from(player);
if (PermissionUtil.hasBypassPermission(sender) || event.getSuggestions().isEmpty() || player.getCurrentServer().isEmpty()) {
if (PermissionUtil.hasBypassPermission(sender, false) || event.getSuggestions().isEmpty() || player.getCurrentServer().isEmpty()) {
return;
}
final List<Group> groups = GroupManager.getPlayerGroups(sender);
final List<Group> groups = GroupManager.getPlayerGroups(sender, false);
event.getSuggestions().removeIf(command -> {
if (Storage.ConfigSections.Settings.CUSTOM_PLUGIN.isTabCompletable(command) || Storage.ConfigSections.Settings.CUSTOM_VERSION.isTabCompletable(command)) {
return false;
}
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, command, serverName);
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, command, serverName, false);
});
FilteredSuggestionEvent filteredSuggestionEvent = PATEventHandler.callFilteredSuggestionEvents(sender, event.getSuggestions());
FilteredSuggestionEvent filteredSuggestionEvent = PATEventHandler.callFilteredSuggestionEvents(sender, new HashSet<>(event.getSuggestions()));
if(filteredSuggestionEvent.isCancelled()) event.getSuggestions().clear();
}
@@ -74,7 +75,7 @@ public class VelocityAntiTabListener {
final CommandSender sender = CommandSender.from(player);
if (PermissionUtil.hasBypassPermission(sender)) {
if (PermissionUtil.hasBypassPermission(sender, false)) {
return;
}
@@ -91,7 +92,7 @@ public class VelocityAntiTabListener {
}
final CommandsCache commandsCache = cache.get(serverName);
final List<Group> groups = GroupManager.getPlayerGroups(sender);
final List<Group> groups = GroupManager.getPlayerGroups(sender, false);
final List<String> commandsAsString = new ArrayList<>();
event.getRootNode().getChildren().stream()
@@ -101,7 +102,7 @@ public class VelocityAntiTabListener {
commandsCache.handleCommands(commandsAsString, serverName);
final boolean newer = player.getProtocolVersion().getProtocol() > 340, argsChildrenExist = event.getRootNode().getChild("args") != null;
final List<String> playerCommands = commandsCache.getPlayerCommands(commandsAsString, sender, groups, serverName);
final HashSet<String> playerCommands = commandsCache.getPlayerCommands(commandsAsString, sender, groups, serverName, false);
if (event.getRootNode().getChildren().size() == 1
&& newer && argsChildrenExist
@@ -7,6 +7,7 @@ import de.rayzs.pat.plugin.logger.Logger;
import de.rayzs.pat.plugin.system.communication.Communicator;
import de.rayzs.pat.api.event.events.ExecuteCommandEvent;
import de.rayzs.pat.plugin.system.subargument.SubArgument;
import de.rayzs.pat.plugin.system.subargument.argument.Arguments;
import de.rayzs.pat.utils.group.Group;
import de.rayzs.pat.utils.group.GroupManager;
import de.rayzs.pat.utils.message.MessageTranslator;
@@ -57,7 +58,7 @@ public class VelocityBlockCommandListener {
final String command = tmpCommand;
if (PermissionUtil.hasBypassPermission(sender, command) || Storage.Blacklist.isDisabledServer(serverName))
if (PermissionUtil.hasBypassPermission(sender, command, false) || Storage.Blacklist.isDisabledServer(serverName))
return event;
final String displayCommand = StringUtils.replaceTriggers(command, "", "\\", "<", ">", "&");
@@ -119,13 +120,13 @@ public class VelocityBlockCommandListener {
}
final boolean cancelBlockedCommand = Storage.ConfigSections.Settings.CANCEL_COMMAND.ENABLED;
final List<Group> groups = GroupManager.getPlayerGroups(sender);
final List<Group> groups = GroupManager.getPlayerGroups(sender, false);
boolean allowed = Storage.Blacklist.canPlayerAccessChat(sender, groups, command, serverName);
boolean allowed = Storage.Blacklist.canPlayerAccessChat(sender, groups, command, serverName, false);
boolean blockedNamespace = false;
if (!Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesBypass(sender)) {
if (!Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesBypass(sender, false)) {
blockedNamespace = cancelBlockedCommand
? Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.isCommand(command)
: Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesAlwaysBlock(command);
@@ -140,7 +141,6 @@ public class VelocityBlockCommandListener {
if (!allowed) {
ExecuteCommandEvent executeCommandEvent = PATEventHandler.callExecuteCommandEvents(
sender,
event.getCommand(),
@@ -191,6 +191,22 @@ public class VelocityBlockCommandListener {
);
if (executeCommandEvent.isBlocked()) {
/*
if (event.getCommand().toLowerCase().contains("discord")) {
Logger.info("Blocked for " + player.getUsername() + " (" + command + " -> " + event.getCommand() + ")");
Logger.info("Groups: " + (groups.isEmpty() ? "None" : String.join(", ", groups.stream().map(Group::getGroupName).toList())));
Logger.info("Server: " + serverName + " (" + sender.getServerName() + ")");
Arguments argument = SubArgument.get().getPlayerArgument(sender);
if (argument != null) {
Logger.info("Chat Arguments: " + String.join(", ", argument.CHAT_ARGUMENTS.getAllInputs()));
Logger.info("Tab Arguments: " + String.join(", ", argument.TAB_ARGUMENTS.getAllInputs()));
} else Logger.info("Arguments: /");
}
*/
event.setResult(CommandExecuteEvent.CommandResult.denied());
MessageTranslator.send(
@@ -52,7 +52,7 @@ public class VelocityConnectionListener {
PermissionUtil.setPlayerPermissions(sender);
if (Storage.OUTDATED && PermissionUtil.hasPermission(sender, "joinupdate")) {
if (Storage.OUTDATED && PermissionUtil.hasPermission(sender, "joinupdate", false)) {
server.getScheduler().buildTask(loader, () -> {
if (player.isActive())
MessageTranslator.send(player, Storage.ConfigSections.Settings.UPDATE.OUTDATED, "%player%", player.getUsername());
@@ -0,0 +1,45 @@
package de.rayzs.pat.plugin.listeners.velocity;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.command.CommandExecuteEvent;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.plugin.VelocityLoader;
import de.rayzs.pat.utils.LuckPermsWarning;
import de.rayzs.pat.utils.sender.CommandSender;
import java.util.concurrent.TimeUnit;
public class VelocityLuckPermsWarning {
private final ProxyServer server;
public VelocityLuckPermsWarning(ProxyServer server) {
this.server = server;
}
@Subscribe
public void onCommandExecute(final CommandExecuteEvent event) {
if (LuckPermsWarning.alreadyAnnounced()) return;
if (Storage.ConfigSections.Settings.UPDATE_GROUPS_PER_WORLD.ENABLED || Storage.ConfigSections.Settings.UPDATE_GROUPS_PER_SERVER.ENABLED) {
return;
}
final CommandSource commandSource = event.getCommandSource();
if(! (commandSource instanceof Player player)) return;
final CommandSender sender = CommandSender.from(player);
final String command = event.getCommand();
if (LuckPermsWarning.shouldSendLuckPermsWarning(sender, command)) {
server.getScheduler().buildTask(
VelocityLoader.getInstance(),
() -> LuckPermsWarning.sendAnnouncement(sender)
).delay(1, TimeUnit.SECONDS).schedule();
}
}
}
@@ -13,11 +13,11 @@ import java.util.UUID;
public class VelocityPingListener {
private static ProxyServer server;
private static final UUID RANDOM_UUID = UUID.randomUUID();
private ProxyServer server;
public VelocityPingListener(ProxyServer server) {
VelocityPingListener.server = server;
this.server = server;
}
@Subscribe
@@ -5,6 +5,10 @@ import de.rayzs.pat.plugin.packetanalyzer.bukkit.handlers.LegacyPacketHandler;
import de.rayzs.pat.plugin.packetanalyzer.bukkit.handlers.ModernCommandsNodeHandler;
import de.rayzs.pat.plugin.packetanalyzer.bukkit.handlers.ModernPacketHandler;
import de.rayzs.pat.utils.permission.PermissionUtil;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ConcurrentHashMap;
import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.utils.ExpireCache;
@@ -16,6 +20,7 @@ import org.bukkit.entity.Player;
import io.netty.channel.*;
import org.bukkit.Bukkit;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
public class BukkitPacketAnalyzer {
@@ -49,7 +54,7 @@ public class BukkitPacketAnalyzer {
}
public static boolean inject(Player player) {
if (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED)
if (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED && !Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.ENABLED)
return true;
try {
@@ -81,6 +86,11 @@ public class BukkitPacketAnalyzer {
return success;
} catch (NoSuchFieldException noSuchFieldException) {
if (!Storage.ConfigSections.Settings.INJECTION_FAILED.ENABLED) {
return true;
}
Logger.warning("Failed to inject into " + player.getName() + " and kicked the player as result, to avoid any security risks.");
Logger.warning("You can read more about it here: https://www.rayzs.de/products/proantitab/pkafi");
Logger.warning("Error details: " + noSuchFieldException.getMessage());
@@ -110,7 +120,7 @@ public class BukkitPacketAnalyzer {
}
public static void uninject(Channel channel) {
if (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED)
if (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED && !Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.ENABLED)
return;
if (channel != null) {
@@ -138,64 +148,103 @@ public class BukkitPacketAnalyzer {
private final Player player;
private final CommandSender sender;
private long lastCheckedForOperatorPermission = System.currentTimeMillis();
private boolean operatorStatus;
private PacketDecoder(Player player) {
this.player = player;
this.sender = CommandSender.from(player);
this.operatorStatus = player.isOp();
}
@Override
public void channelRead(ChannelHandlerContext channel, Object packetObj) {
try {
if (packetObj.getClass() == null || Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) {
if (packetObj.getClass() == null) {
super.channelRead(channel, packetObj);
return;
}
String packetName = packetObj.getClass().getSimpleName();
if (Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.ENABLED && packetName.equalsIgnoreCase("ServerboundCustomPayloadPacket")) {
final Object newPacketObj = handlePluginChannelPacket(packetObj);
if (newPacketObj != null)
super.channelRead(channel, newPacketObj);
return;
}
if (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) {
super.channelRead(channel, packetObj);
return;
}
if (!packetName.equals("PacketPlayInTabComplete") && !packetName.equals("ServerboundCommandSuggestionPacket")) {
super.channelRead(channel, packetObj);
return;
}
if (!PermissionUtil.hasBypassPermission(sender)) {
if (!PACKET_HANDLER.handleIncomingPacket(player, sender, packetObj))
return;
if (!hasBypassPermission() && !PACKET_HANDLER.handleIncomingPacket(player, sender, packetObj, false)) {
return;
}
super.channelRead(channel, packetObj);
} catch (Throwable exception) { exception.printStackTrace(); }
} catch (Throwable exception) {
exception.printStackTrace();
}
}
@Override
public void write(ChannelHandlerContext channel, Object packetObj, ChannelPromise promise) {
try {
if(packetObj.getClass() == null || Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) {
if(packetObj.getClass() == null) {
super.write(channel, packetObj, promise);
return;
}
final String packetName = packetObj.getClass().getSimpleName();
if (Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.ENABLED && packetName.equalsIgnoreCase("ClientboundCustomPayloadPacket")) {
final Object newPacketObj = handlePluginChannelPacket(packetObj);
if (newPacketObj != null)
super.write(channel, newPacketObj, promise);
return;
}
if (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) {
super.write(channel, packetObj, promise);
return;
}
final boolean isCommandsPacket = packetName.equals("ClientboundCommandsPacket");
final boolean isTabCompletePacket = packetName.equals("PacketPlayOutTabComplete") || packetName.equals("ClientboundCommandSuggestionsPacket");
if (!isCommandsPacket && !isTabCompletePacket || PermissionUtil.hasBypassPermission(sender)) {
if (!isCommandsPacket && !isTabCompletePacket || hasBypassPermission()) {
super.write(channel, packetObj, promise);
return;
}
if (isCommandsPacket) {
COMMANDS_NODE_HANDLER.handleOutgoingPacket(player, sender, packetObj);
COMMANDS_NODE_HANDLER.handleOutgoingPacket(player, sender, packetObj, false);
super.write(channel, packetObj, promise);
return;
}
UUID uuid = player.getUniqueId();
Object sentPacketObj = SENT_PACKET.get(uuid);
final UUID uuid = sender.getUniqueId();
final Object sentPacketObj = SENT_PACKET.get(uuid);
if (sentPacketObj != null) {
if (sentPacketObj == packetObj) {
@@ -205,8 +254,9 @@ public class BukkitPacketAnalyzer {
}
}
if (!PACKET_HANDLER.handleOutgoingPacket(player, sender, packetObj))
if (!PACKET_HANDLER.handleOutgoingPacket(player, sender, packetObj, false)) {
return;
}
super.write(channel, packetObj, promise);
@@ -214,5 +264,89 @@ public class BukkitPacketAnalyzer {
exception.printStackTrace();
}
}
private boolean hasBypassPermission() {
if (PermissionUtil.hasBypassPermission(sender, false)) {
return true;
}
if (System.currentTimeMillis() - this.lastCheckedForOperatorPermission >= 2000) {
this.lastCheckedForOperatorPermission = System.currentTimeMillis();
this.operatorStatus = player.isOp();
return this.operatorStatus;
}
return this.operatorStatus;
}
private Object handlePluginChannelPacket(Object packet) throws NoSuchFieldException, IllegalAccessException {
final Field payloadField = packet.getClass().getDeclaredField("payload");
payloadField.setAccessible(true);
final Object payloadObj = payloadField.get(packet);
Field channelField;
try {
channelField = payloadObj.getClass().getDeclaredField("id");
} catch (NoSuchFieldException noSuchFieldException) {
return packet;
}
channelField.setAccessible(true);
final Object channelIdObj = channelField.get(payloadObj);
final String channelId = channelIdObj.toString();
channelField.setAccessible(false);
if (!Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.isRegisterChannel(channelId)) {
return packet;
}
final Field dataField = payloadObj.getClass().getDeclaredField("data");
dataField.setAccessible(true);
final byte[] data = (byte[]) dataField.get(payloadObj);
dataField.setAccessible(true);
final String dataStr = new String(data, StandardCharsets.UTF_8);
final String[] channels = dataStr.split("\u0000");
final List<String> filteredChannels = new ArrayList<>(Arrays.asList(channels));
final AtomicBoolean changedAnything = new AtomicBoolean(false);
filteredChannels.removeIf(channel -> {
if (!Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.WHITELISTED_CHANNELS.getLines().contains(channel)) {
changedAnything.set(true);
return true;
}
return false;
});
if (!changedAnything.get()) {
return packet;
}
try {
final Class<?> customPayloadClass = packet.getClass().getConstructors()[0].getParameterTypes()[0];
final Class<?> discardPayloadClass = payloadObj.getClass();
final Constructor<?> discardPayloadConstr = discardPayloadClass.getConstructor(channelIdObj.getClass(), byte[].class);
final Object newDiscardPayloadObj = discardPayloadConstr.newInstance(
channelIdObj,
String.join("\u0000", filteredChannels).getBytes()
);
final Constructor<?> newPacketConstr = packet.getClass().getConstructor(customPayloadClass);
return newPacketConstr.newInstance(newDiscardPayloadObj);
} catch (Exception exception) {
exception.printStackTrace();
}
return packet;
}
}
}
@@ -4,6 +4,17 @@ import de.rayzs.pat.utils.sender.CommandSender;
import org.bukkit.entity.Player;
public interface BukkitPacketHandler {
boolean handleIncomingPacket(Player player, CommandSender sender, Object packetObj) throws Exception;
boolean handleOutgoingPacket(Player player, CommandSender sender, Object packetObj) throws Exception;
boolean handleIncomingPacket(
final Player player,
final CommandSender sender,
final Object packetObj,
final boolean isOperator
) throws Exception;
boolean handleOutgoingPacket(
final Player player,
final CommandSender sender,
final Object packetObj,
final boolean isOperator
) throws Exception;
}
@@ -23,7 +23,12 @@ import de.rayzs.pat.utils.Reflection;
public class LegacyPacketHandler implements BukkitPacketHandler {
@Override
public boolean handleIncomingPacket(Player player, CommandSender sender, Object packetObj) throws Exception {
public boolean handleIncomingPacket(
final Player player,
final CommandSender sender,
final Object packetObj,
final boolean isOperator
) throws Exception {
Field stringField = Reflection.getFirstFieldByType(packetObj.getClass(), "String", Reflection.SearchOption.ENDS);
if(stringField == null) {
Logger.warning("Failed PacketAnalyze process! (#1)");
@@ -36,14 +41,19 @@ public class LegacyPacketHandler implements BukkitPacketHandler {
}
@Override
public boolean handleOutgoingPacket(Player player, CommandSender sender, Object packetObj) throws Exception {
public boolean handleOutgoingPacket(
final Player player,
final CommandSender sender,
final Object packetObj,
final boolean isOperator
) throws Exception {
final String rawInput = BukkitPacketAnalyzer.getPlayerInput(player);
if(rawInput == null) {
return false;
}
final List<Group> groups = GroupManager.getPlayerGroups(sender);
final List<Group> groups = GroupManager.getPlayerGroups(sender, isOperator);
String input = rawInput;
boolean cancelsBeforeHand = false;
@@ -54,7 +64,7 @@ public class LegacyPacketHandler implements BukkitPacketHandler {
input = input.substring(1);
final boolean doesBypassNamespace = Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesBypass(sender);
final boolean doesBypassNamespace = Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesBypass(sender, isOperator);
final boolean spaces = input.contains(" ");
if (Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.isCommand(input) && !doesBypassNamespace) {
@@ -62,7 +72,7 @@ public class LegacyPacketHandler implements BukkitPacketHandler {
}
if (!cancelsBeforeHand && !input.isEmpty()) {
cancelsBeforeHand = !Storage.Blacklist.canPlayerAccessTab(sender, groups, StringUtils.getFirstArg(input));
cancelsBeforeHand = !Storage.Blacklist.canPlayerAccessTab(sender, groups, StringUtils.getFirstArg(input), isOperator);
}
if (!cancelsBeforeHand) {
@@ -117,7 +127,7 @@ public class LegacyPacketHandler implements BukkitPacketHandler {
return false;
}
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, cpy);
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, cpy, isOperator);
});
}
@@ -5,18 +5,33 @@ import de.rayzs.pat.plugin.system.subargument.SubArgument;
import de.rayzs.pat.utils.node.BukkitCommandNodeHelper;
import de.rayzs.pat.utils.sender.CommandSender;
import org.bukkit.entity.Player;
public class ModernCommandsNodeHandler implements BukkitPacketHandler {
public boolean handleIncomingPacket(Player player, CommandSender sender, Object packetObj) throws Exception {
public boolean handleIncomingPacket(
final Player player,
final CommandSender sender,
final Object packetObj,
final boolean isOperator
) {
// Ignored
return true;
}
@Override
public boolean handleOutgoingPacket(Player player, CommandSender sender, Object packetObj) throws Exception {
public boolean handleOutgoingPacket(
final Player player,
final CommandSender sender,
final Object packetObj,
final boolean isOperator
) throws Exception {
final BukkitCommandNodeHelper helper = new BukkitCommandNodeHelper(packetObj);
SubArgument.get().getCommandNodeHandler().handleCommandNode(helper, SubArgument.get().getPlayerArgument(sender));
SubArgument.get().getCommandNodeHandler().handleCommandNode(
helper,
SubArgument.get().getPlayerArgument(sender)
);
return true;
}
}
@@ -31,10 +31,15 @@ public class ModernPacketHandler implements BukkitPacketHandler {
private static boolean modifiable = true;
@Override
public boolean handleIncomingPacket(Player player, CommandSender sender, Object packetObj) throws Exception {
public boolean handleIncomingPacket(
final Player player,
final CommandSender sender,
final Object packetObj,
final boolean isOperator
) throws Exception {
Field stringField = Reflection.getFirstFieldByType(packetObj.getClass(), "String", Reflection.SearchOption.ENDS);
if(stringField == null) {
if (stringField == null) {
Logger.warning("Failed PacketAnalyze process! (#1)");
return false;
}
@@ -62,7 +67,12 @@ public class ModernPacketHandler implements BukkitPacketHandler {
}
@Override
public boolean handleOutgoingPacket(Player player, CommandSender sender, Object packetObj) throws Exception {
public boolean handleOutgoingPacket(
final Player player,
final CommandSender sender,
final Object packetObj,
final boolean isOperator
) throws Exception {
Object suggestionObj;
String rawInput = BukkitPacketAnalyzer.getPlayerInput(player), input = rawInput;
@@ -70,10 +80,10 @@ public class ModernPacketHandler implements BukkitPacketHandler {
return false;
}
final List<Group> groups = GroupManager.getPlayerGroups(sender);
final boolean is121Packet = packetObj.getClass().getSimpleName().equals("ClientboundCommandSuggestionsPacket");
final List<Group> groups = GroupManager.getPlayerGroups(sender, isOperator);
boolean is121Packet = packetObj.getClass().getSimpleName().equals("ClientboundCommandSuggestionsPacket"),
cancelsBeforeHand = false;
boolean cancelsBeforeHand = false;
int spaces = 0;
if(input.startsWith("/") || is121Packet) {
@@ -85,7 +95,7 @@ public class ModernPacketHandler implements BukkitPacketHandler {
if (spaces > 0) input = split[0];
}
cancelsBeforeHand = !Storage.Blacklist.canPlayerAccessTab(sender, groups, input);
cancelsBeforeHand = !Storage.Blacklist.canPlayerAccessTab(sender, groups, input, isOperator);
if (!cancelsBeforeHand)
cancelsBeforeHand = Storage.ConfigSections.Settings.CUSTOM_VERSION.isTabCompletable(input) || Storage.ConfigSections.Settings.CUSTOM_PLUGIN.isTabCompletable(input);
@@ -114,7 +124,7 @@ public class ModernPacketHandler implements BukkitPacketHandler {
if (spaces == 0) {
suggestions.removeIf(suggestion -> {
String command = getSuggestionFromEntry(suggestion);
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, command);
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, command, isOperator);
});
return true;
@@ -190,7 +200,7 @@ public class ModernPacketHandler implements BukkitPacketHandler {
suggestions.getList().removeIf(suggestion -> {
String command = suggestion.getText();
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, command);
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, command, isOperator);
});
return true;
@@ -1,9 +1,11 @@
package de.rayzs.pat.plugin.packetanalyzer.proxy;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import com.mojang.brigadier.tree.CommandNode;
@@ -144,18 +146,19 @@ public class BungeePacketAnalyzer {
private static void modifyCommands(ProxiedPlayer player, CommandSender sender, Commands commands) {
String serverName = sender.getServerName();
final boolean ignore = PermissionUtil.hasBypassPermission(sender) || Storage.Blacklist.isDisabledServer(serverName);
final boolean ignore = PermissionUtil.hasBypassPermission(sender, false) || Storage.Blacklist.isDisabledServer(serverName);
ProxyCommandNodeHelper helper = new ProxyCommandNodeHelper<CommandNode>(commands.getRoot());
List<String> commandsAsString = new ArrayList<>(PROXY_COMMANDS);
final ProxyCommandNodeHelper helper = new ProxyCommandNodeHelper<CommandNode>(commands.getRoot());
final List<String> commandsAsString = new ArrayList<>(PROXY_COMMANDS);
commandsAsString.addAll(helper.getChildrenNames());
List<String> playerCommands = new ArrayList<>();
final List<Group> groups = ignore
? Collections.emptyList()
: GroupManager.getPlayerGroups(sender, false);
HashSet<String> playerCommands = new HashSet<>();
if (!ignore) {
final List<Group> groups = GroupManager.getPlayerGroups(sender);
final Map<String, CommandsCache> cache = Storage.getLoader().getPerServerCommandsCacheMap();
if (!cache.containsKey(serverName)) {
cache.put(serverName, new CommandsCache());
@@ -164,7 +167,7 @@ public class BungeePacketAnalyzer {
final CommandsCache commandsCache = cache.get(serverName);
commandsCache.handleCommands(commandsAsString, serverName);
final List<String> tmpPlayerCommands = commandsCache.getPlayerCommands(commandsAsString, sender, groups, serverName);
final HashSet<String> tmpPlayerCommands = commandsCache.getPlayerCommands(commandsAsString, sender, groups, serverName, false);
if (commands.getRoot().getChildren().size() != 0) {
helper.removeIf(str -> !tmpPlayerCommands.contains(str));
@@ -216,6 +219,14 @@ public class BungeePacketAnalyzer {
}
}
if (Storage.ConfigSections.Settings.TAB_COMPLETION_FOR_NOT_EXISTING_COMMANDS.ENABLED) {
for (Group group : groups) {
for (String groupCommands : group.getAllCommands(serverName)) {
helper.add(groupCommands, true);
}
}
}
if (!ignore) {
SubArgument.get().getCommandNodeHandler().handleCommandNode(helper, SubArgument.get().getPlayerArgument(sender));
}
@@ -240,6 +251,7 @@ public class BungeePacketAnalyzer {
}
}
private static class PacketDecoder extends MessageToMessageDecoder<PacketWrapper> {
private final ProxiedPlayer player;
@@ -262,6 +274,31 @@ public class BungeePacketAnalyzer {
if (CustomServerBrand.get().isEnabled() && CustomServerBrand.get().isBrandTag(pluginMessage.getTag())) {
return;
} else if (Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.ENABLED) {
final String channelId = pluginMessage.getTag();
if (Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.isRegisterChannel(channelId)) {
final String dataStr = new String(pluginMessage.getData(), StandardCharsets.UTF_8);
final String[] channels = dataStr.split("\u0000");
final List<String> filteredChannels = new ArrayList<>(Arrays.asList(channels));
final AtomicBoolean changedAnything = new AtomicBoolean(false);
filteredChannels.removeIf(channel -> {
if (!Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.WHITELISTED_CHANNELS.getLines().contains(channel)) {
changedAnything.set(true);
return true;
}
return false;
});
if (changedAnything.get()) {
pluginMessage.setData(String.join("\u0000", filteredChannels).getBytes());
player.unsafe().sendPacket(pluginMessage);
return;
}
}
}
} else if (wrapper.packet instanceof Commands response) {
@@ -1,17 +1,16 @@
package de.rayzs.pat.plugin.packetanalyzer.proxy;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import com.mojang.brigadier.suggestion.SuggestionProvider;
import com.velocitypowered.api.command.CommandSource;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.proxy.protocol.MinecraftPacket;
import com.velocitypowered.proxy.protocol.packet.AvailableCommandsPacket;
import com.velocitypowered.proxy.protocol.packet.PluginMessagePacket;
import com.velocitypowered.proxy.protocol.packet.TabCompleteRequestPacket;
import com.velocitypowered.proxy.protocol.packet.TabCompleteResponsePacket;
import com.velocitypowered.proxy.protocol.packet.*;
import com.velocitypowered.proxy.protocol.packet.chat.session.UnsignedPlayerCommandPacket;
import de.rayzs.pat.plugin.system.serverbrand.CustomServerBrand;
@@ -32,6 +31,8 @@ import de.rayzs.pat.utils.message.MessageTranslator;
import de.rayzs.pat.utils.node.ProxyCommandNodeHelper;
import de.rayzs.pat.utils.permission.PermissionUtil;
import de.rayzs.pat.utils.sender.CommandSender;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
@@ -177,7 +178,7 @@ public class VelocityPacketAnalyzer {
final String serverName = sender.getServerName();
final boolean ignore = PermissionUtil.hasBypassPermission(sender) || Storage.Blacklist.isDisabledServer(serverName);
final boolean ignore = PermissionUtil.hasBypassPermission(sender, false) || Storage.Blacklist.isDisabledServer(serverName);
final ProxyCommandNodeHelper<CommandSource> helper = new ProxyCommandNodeHelper<>(commands.getRootNode());
final List<String> commandsAsString = new ArrayList<>();
@@ -187,7 +188,7 @@ public class VelocityPacketAnalyzer {
return;
}
final List<Group> groups = GroupManager.getPlayerGroups(sender);
final List<Group> groups = GroupManager.getPlayerGroups(sender, false);
final Map<String, CommandsCache> cache = Storage.getLoader().getPerServerCommandsCacheMap();
if (!cache.containsKey(serverName)) {
@@ -197,7 +198,7 @@ public class VelocityPacketAnalyzer {
final CommandsCache commandsCache = cache.get(serverName);
commandsCache.handleCommands(commandsAsString, serverName);
final List<String> playerCommands = commandsCache.getPlayerCommands(commandsAsString, sender, groups, serverName);
final HashSet<String> playerCommands = commandsCache.getPlayerCommands(commandsAsString, sender, groups, serverName, false);
helper.removeIf(str -> {
if (str.equals("args")) {
return false;
@@ -206,6 +207,18 @@ public class VelocityPacketAnalyzer {
return !playerCommands.contains(str);
});
if (Storage.ConfigSections.Settings.TAB_COMPLETION_FOR_NOT_EXISTING_COMMANDS.ENABLED) {
for (Group group : groups) {
for (String groupServerName : group.getBlacklistServerNames(serverName)) {
if (Storage.isServer(groupServerName, serverName)) {
for (String groupCommands : group.getAllCommands(groupServerName)) {
helper.add(groupCommands, true);
}
}
}
}
}
if (Storage.ConfigSections.Settings.CUSTOM_VERSION.ALWAYS_TAB_COMPLETABLE) {
Storage.ConfigSections.Settings.CUSTOM_VERSION.COMMANDS.getLines().forEach(input -> helper.add(input, false));
}
@@ -217,6 +230,37 @@ public class VelocityPacketAnalyzer {
SubArgument.get().getCommandNodeHandler().handleCommandNode(helper, SubArgument.get().getPlayerArgument(sender));
}
private static void handlePluginMessageChannelsPacket(final PluginMessagePacket packet) {
final String channelId = packet.getChannel();
if (Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.isRegisterChannel(channelId)) {
final ByteBuf buf = packet.content();
final byte[] data = new byte[buf.readableBytes()];
buf.getBytes(buf.readerIndex(), data);
final String dataStr = new String(data, StandardCharsets.UTF_8);
final String[] channels = dataStr.split("\u0000");
final List<String> filteredChannels = new ArrayList<>(Arrays.asList(channels));
final AtomicBoolean changedAnything = new AtomicBoolean(false);
filteredChannels.removeIf(channel -> {
if (!Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.WHITELISTED_CHANNELS.getLines().contains(channel)) {
changedAnything.set(true);
return true;
}
return false;
});
if (changedAnything.get()) {
final ByteBuf newBuf = Unpooled.wrappedBuffer(String.join("\u0000", filteredChannels).getBytes());
packet.replace(newBuf);
}
}
}
private static class PacketDecoder extends ChannelDuplexHandler {
private final Player player;
@@ -253,6 +297,10 @@ public class VelocityPacketAnalyzer {
}
}
if (packet instanceof PluginMessagePacket pluginMessagePacket && Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.ENABLED) {
handlePluginMessageChannelsPacket(pluginMessagePacket);
}
if (packet instanceof UnsignedPlayerCommandPacket unsignedPlayerCommandPacket) {
if (!VelocityBlockCommandListener.handleCommand(player, unsignedPlayerCommandPacket.getCommand()).getResult().isAllowed())
return;
@@ -282,11 +330,13 @@ public class VelocityPacketAnalyzer {
MinecraftPacket packet = (MinecraftPacket) msg;
if (packet instanceof PluginMessagePacket pluginMessagePacket) {
if(CustomServerBrand.get().isEnabled() && CustomServerBrand.get().isBrandTag(pluginMessagePacket.getChannel()) && !player.getCurrentServer().isPresent()) {
if (CustomServerBrand.get().isEnabled() && CustomServerBrand.get().isBrandTag(pluginMessagePacket.getChannel()) && !player.getCurrentServer().isPresent()) {
final PacketUtils.BrandManipulate brandManipulatePacket = CustomServerBrand.get().createBrandPacket(player);
super.write(ctx, new PluginMessagePacket(pluginMessagePacket.getChannel(), brandManipulatePacket.getByteBuf()), promise);
return;
} else if (Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.ENABLED) {
handlePluginMessageChannelsPacket(pluginMessagePacket);
}
} else if (packet instanceof TabCompleteResponsePacket response) {
@@ -298,8 +348,8 @@ public class VelocityPacketAnalyzer {
return;
}
if (!PermissionUtil.hasBypassPermission(sender) && player.getCurrentServer().isPresent()) {
final List<Group> groups = GroupManager.getPlayerGroups(sender);
if (!PermissionUtil.hasBypassPermission(sender, false) && player.getCurrentServer().isPresent()) {
final List<Group> groups = GroupManager.getPlayerGroups(sender, false);
boolean cancelsBeforeHand = false;
String playerInput = getPlayerInput(player), rawPlayerInput = playerInput, server = player.getCurrentServer().get().getServerInfo().getName();
@@ -312,7 +362,7 @@ public class VelocityPacketAnalyzer {
}
if (!playerInput.equals("/")) {
cancelsBeforeHand = !Storage.Blacklist.canPlayerAccessTab(sender, groups, StringUtils.replaceFirst(playerInput, "/", ""), server);
cancelsBeforeHand = !Storage.Blacklist.canPlayerAccessTab(sender, groups, StringUtils.replaceFirst(playerInput, "/", ""), server, false);
if (!cancelsBeforeHand) {
cancelsBeforeHand = Storage.ConfigSections.Settings.CUSTOM_VERSION.isTabCompletable(StringUtils.replaceFirst(playerInput, "/", "")) || Storage.ConfigSections.Settings.CUSTOM_PLUGIN.isTabCompletable(StringUtils.replaceFirst(playerInput, "/", ""));
@@ -336,7 +386,7 @@ public class VelocityPacketAnalyzer {
return false;
}
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, command, player.getCurrentServer().get().getServerInfo().getName());
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, command, player.getCurrentServer().get().getServerInfo().getName(), false);
});
} else {
@@ -98,6 +98,8 @@ public class CommandNodeHandler extends SubArgumentHandler {
break;
}
if (input == null) continue;
final Storage.Blacklist.BlockType type = Storage.Blacklist.BlockTypeFetcher.getType(input);
if (type == Storage.Blacklist.BlockType.CHAT) {
continue;
@@ -1,6 +1,7 @@
package de.rayzs.pat.plugin.system.subargument.handler.impl;
import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.plugin.logger.Logger;
import de.rayzs.pat.plugin.system.subargument.handler.SubArgumentHandler;
import de.rayzs.pat.plugin.system.subargument.SubArgument;
import de.rayzs.pat.utils.StringUtils;
@@ -67,6 +68,16 @@ public class ExecuteHandler extends SubArgumentHandler {
listed = !turn;
}
/*
final boolean blocked = turn != listed;
if (blocked && command.contains("discord")) {
Logger.info("Yes, sub-argument was blocked! (" + sender.getName() + ", " + command + ")");
Logger.info("-> " + turn + ", " + listed + ", " + negated);
}
return blocked;
*/
return turn != listed;
}
@@ -4,6 +4,7 @@ import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.plugin.system.subargument.handler.SubArgumentHandler;
import de.rayzs.pat.plugin.system.subargument.SubArgument;
import de.rayzs.pat.utils.NumberUtils;
import de.rayzs.pat.utils.StringUtils;
import de.rayzs.pat.utils.sender.CommandSender;
import de.rayzs.pat.plugin.system.subargument.argument.Arguments;
@@ -133,13 +134,18 @@ public class TabCompleteHandler extends SubArgumentHandler {
possibilities.removeIf(possibility -> getInstance().getCachedOnlinePlayerNames().contains(possibility));
possibilities.removeIf(s -> {
if (negated.contains(s)) {
return false;
}
if (!arguments.getResultTab(StringUtils.getFirstArg(cursor)).isEmpty() && result.isEmpty()) {
possibilities.clear();
possibilities.add("///////////");
} else {
possibilities.removeIf(s -> {
if (negated.contains(s)) {
return false;
}
return result.contains(s);
});
return result.contains(s);
});
}
}
if (turn && possibilities.isEmpty()) {
@@ -1,14 +1,13 @@
package de.rayzs.pat.plugin.system.subargument.handler.impl;
import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.plugin.logger.Logger;
import de.rayzs.pat.plugin.system.subargument.handler.SubArgumentHandler;
import de.rayzs.pat.plugin.system.subargument.SubArgument;
import de.rayzs.pat.utils.Reflection;
import de.rayzs.pat.utils.sender.CommandSender;
import de.rayzs.pat.plugin.system.subargument.argument.Arguments;
import java.util.List;
import java.util.HashSet;
public class UpdateArgumentsHandler extends SubArgumentHandler {
@@ -16,7 +15,7 @@ public class UpdateArgumentsHandler extends SubArgumentHandler {
super(instance);
}
public void updatePlayerArguments(CommandSender sender, List<String> commands, List<String> serverCommands, List<String> groupCommands) {
public void updatePlayerArguments(CommandSender sender, HashSet<String> commands, HashSet<String> serverCommands, HashSet<String> groupCommands) {
final Arguments arguments = getInstance().getPlayerArgument(sender);
arguments.clearArguments();
@@ -83,14 +83,25 @@ public class CommandsCache {
filteredCommands = tmpFilteredCommands;
}
public List<String> getPlayerCommands(Collection<String> unfilteredCommands, CommandSender sender, List<Group> groups) {
return getPlayerCommands(unfilteredCommands, sender, groups, null);
public HashSet<String> getPlayerCommands(
final Collection<String> unfilteredCommands,
final CommandSender sender,
final List<Group> groups,
final boolean isOperator
) {
return getPlayerCommands(unfilteredCommands, sender, groups, null, isOperator);
}
public List<String> getPlayerCommands(Collection<String> unfilteredCommands, CommandSender sender, List<Group> groups, String serverName) {
List<String> playerCommands = new LinkedList<>(unfilteredCommands);
List<String> localFilteredCommands = filteredCommands == null ? null : Reflection.isProxyServer()
? new ArrayList<>() : new ArrayList<>(filteredCommands);
public HashSet<String> getPlayerCommands(
final Collection<String> unfilteredCommands,
final CommandSender sender,
final List<Group> groups,
final String serverName,
final boolean isOperator
) {
final HashSet<String> playerCommands = new HashSet<>(unfilteredCommands);
final HashSet<String> localFilteredCommands = filteredCommands == null ? null : Reflection.isProxyServer()
? new HashSet<>() : new HashSet<>(filteredCommands);
if (localFilteredCommands == null)
return playerCommands;
@@ -105,15 +116,15 @@ public class CommandsCache {
String command = filteredCommands.get(i);
localFilteredCommands.add(command);
} catch (IndexOutOfBoundsException indexOutOfBoundsException) {
Logger.warning("Array is out of bounds " + i + "/" + max + "! " + indexOutOfBoundsException.getMessage());
//Logger.warning("Array is out of bounds " + i + "/" + max + "! " + indexOutOfBoundsException.getMessage());
break;
}
}
}
if (!PermissionUtil.hasBypassPermission(sender)) {
boolean hasNamespaceBypass = Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesBypass(sender);
if (!PermissionUtil.hasBypassPermission(sender, isOperator)) {
boolean hasNamespaceBypass = Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.doesBypass(sender, isOperator);
playerCommands.removeIf(command -> {
if (!hasNamespaceBypass && Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.isCommand(command)) {
@@ -124,12 +135,12 @@ public class CommandsCache {
return false;
}
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, command, serverName);
return !Storage.Blacklist.canPlayerAccessTab(sender, groups, command, serverName, isOperator);
});
}
final List<String> serverCommands = Storage.Blacklist.Collector.collectAllServerCommands(serverName);
final HashSet<String> serverCommands = Storage.Blacklist.Collector.collectAllServerCommands(serverName);
SubArgument.get().getUpdateArgumentsHandler().updatePlayerArguments(
sender,
@@ -144,7 +155,7 @@ public class CommandsCache {
serverName != null
);
return playerCommands.stream().map(command -> {
return new HashSet<>(playerCommands.stream().map(command -> {
command = StringUtils.getFirstArg(command);
Storage.Blacklist.BlockType type = Storage.Blacklist.BlockTypeFetcher.getType(command);
@@ -152,7 +163,7 @@ public class CommandsCache {
return command;
return Storage.Blacklist.BlockTypeFetcher.modify(command, type);
}).toList();
}).toList());
}
@@ -0,0 +1,106 @@
package de.rayzs.pat.utils;
import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.plugin.logger.Logger;
import de.rayzs.pat.utils.permission.PermissionPlugin;
import de.rayzs.pat.utils.permission.PermissionUtil;
import de.rayzs.pat.utils.sender.CommandSender;
import java.util.Set;
public class LuckPermsWarning {
private static boolean ALREADY_ANNOUNCED = false;
private static final Set<String> LUCKPERMS_PREFIXES = Set.of(
"luckperms", "lp",
"luckpermsbungee", "lpb",
"luckpermsvelocity", "lpv"
);
private static final Set<String> LUCKPERMS_COMMANDS_SET = Set.of(
"set", "unset",
"settemp", "unsettemp"
);
private static final String LUCKPERMS_WARNING = "&6&l[ProAntiTab] " +
"&e&lHey! &eYou just set a ProAntiTab permission using a world/server as context. " +
"However, PAT won't be able to detect this as of now. To fix this, please go to your &6&oplugins/ProAntiTab/config.yml&e and set the option &6&o'%s'&e to &a&ltrue&e. " +
"Afterwards, just execute '&6/%s reload'&e to apply the changes.";
public static boolean shouldSendLuckPermsWarning(final CommandSender sender, final String command) {
if (ALREADY_ANNOUNCED) {
return false;
}
if (Storage.getPermissionPlugin() != PermissionPlugin.LUCKPERMS) {
return false;
}
if (!LUCKPERMS_PREFIXES.contains(StringUtils.getFirstArg(command))) {
return false;
}
if (!sender.isConsole() && !PermissionUtil.hasPermission(sender, "*", false) && !sender.isOperator()) {
return false;
}
final String[] commandArgs = command.split(" ");
final String fth = getStrAtIndex(commandArgs, 5);
if (!StringUtils.startsWithIgnoreCase("proantitab.", fth)) {
return false;
}
final String thd = getStrAtIndex(commandArgs, 3);
if (!thd.equalsIgnoreCase("permission")) {
return false;
}
final String fst = getStrAtIndex(commandArgs, 1);
if (!fst.equalsIgnoreCase("group") && !fst.equalsIgnoreCase("user")) {
return false;
}
if (!LUCKPERMS_COMMANDS_SET.contains(getStrAtIndex(commandArgs, 4))) {
return false;
}
for (int i = 6; i < commandArgs.length; i++) {
final String context = getStrAtIndex(commandArgs, i);
final boolean res = StringUtils.startsWithIgnoreCase("server=", context)
|| StringUtils.startsWithIgnoreCase("world=", context);
if (res) {
return true;
}
}
return false;
}
public static void sendAnnouncement(final CommandSender sender) {
if (ALREADY_ANNOUNCED) return;
ALREADY_ANNOUNCED = true;
final String message = LUCKPERMS_WARNING.formatted(
Reflection.isProxyServer() ? "update-groups-per-server" : "update-groups-per-world",
Reflection.isProxyServer() ? "bpat" : "pat"
);
if (!sender.isConsole()) Logger.info(message);
sender.sendMessage(message);
}
public static boolean alreadyAnnounced() {
return ALREADY_ANNOUNCED;
}
private static String getStrAtIndex(final String[] args, final int index) {
if (index < 0 || index >= args.length) return "";
return args[index];
}
}
@@ -14,8 +14,6 @@ public class StringUtils {
return false;
}
System.out.println("\"" + str.substring(0, strCutLength) + "\"startsWith(\"" + startingWithSource + "\")");
return startingWithSource.equalsIgnoreCase(str.substring(0, strCutLength));
}
@@ -6,21 +6,21 @@ import java.util.*;
public class MultipleMessagesHelper implements Serializable {
private final ArrayList<String> lines;
private final List<String> lines;
public MultipleMessagesHelper(ConfigStorage config, String path, List<String> input) {
ConfigSectionHelper<ArrayList<String>> sectionHelper = new ConfigSectionHelper<>(config, path, input);
final ConfigSectionHelper<ArrayList<String>> sectionHelper = new ConfigSectionHelper<>(config, path, input);
final Object resultObj = sectionHelper.getOrSet();
if(!sectionHelper.exist()) {
lines = new ArrayList<>(input);
sectionHelper.set(lines);
if (resultObj instanceof List list) {
lines = (List<String>) list;
return;
}
lines = sectionHelper.get();
lines = input;
}
public ArrayList<String> getLines() {
public List<String> getLines() {
return lines;
}
}
@@ -156,12 +156,12 @@ public class Group implements Serializable {
this.priority = priority;
}
public boolean hasPermission(CommandSender sender) {
return PermissionUtil.hasPermission(sender, "group." + this.groupName);
public boolean hasPermission(final CommandSender sender, final boolean isOperator) {
return PermissionUtil.hasPermission(sender, "group." + this.groupName, isOperator);
}
public boolean hasPermission(UUID uuid) {
return PermissionUtil.hasPermission(uuid, "group." + this.groupName);
public boolean hasPermission(final UUID uuid, final boolean isOperator) {
return PermissionUtil.hasPermission(uuid, "group." + this.groupName, isOperator);
}
public boolean contains(String command) {
@@ -45,8 +45,8 @@ public class GroupManager {
});
}
public static List<Group> getPlayerGroups(UUID uuid) {
List<Group> playerGroups = new ArrayList<>(GroupManager.getGroups().stream().filter(group -> group.hasPermission(uuid)).toList());
public static List<Group> getPlayerGroups(final UUID uuid, final boolean isOperator) {
List<Group> playerGroups = new ArrayList<>(GroupManager.getGroups().stream().filter(group -> group.hasPermission(uuid, isOperator)).toList());
int priority = playerGroups.stream()
.mapToInt(Group::getPriority)
@@ -58,8 +58,8 @@ public class GroupManager {
return playerGroups;
}
public static List<Group> getPlayerGroups(CommandSender sender) {
List<Group> playerGroups = new ArrayList<>(GroupManager.getGroups().stream().filter(group -> group.hasPermission(sender)).toList());
public static List<Group> getPlayerGroups(final CommandSender sender, final boolean isOperator) {
List<Group> playerGroups = new ArrayList<>(GroupManager.getGroups().stream().filter(group -> group.hasPermission(sender, isOperator)).toList());
int priority = playerGroups.stream()
.mapToInt(Group::getPriority)
@@ -192,10 +192,10 @@ public class LuckPermsHook {
if (Reflection.isProxyServer()) {
final String serverName = sender.getServerName();
final List<String> serverCommands = Storage.Blacklist.Collector.collectAllServerCommands(serverName);
final List<String> groupCommands = Storage.Blacklist.Collector.collectAllPlayerGroupCommands(sender, serverName);
final HashSet<String> serverCommands = Storage.Blacklist.Collector.collectAllServerCommands(serverName);
final HashSet<String> groupCommands = Storage.Blacklist.Collector.collectAllPlayerGroupCommands(sender, serverName);
final List<String> playerCommands = new ArrayList<>(serverCommands);
final HashSet<String> playerCommands = new HashSet<>(serverCommands);
playerCommands.addAll(groupCommands);
SubArgument.get().getUpdateArgumentsHandler().updatePlayerArguments(sender, playerCommands, serverCommands, groupCommands);
@@ -209,8 +209,9 @@ public class LuckPermsHook {
private static boolean isRelevantPermission(Node node) {
final String key = node.getKey();
return key.startsWith("group.")
return key.equals("*")
|| key.startsWith("group.")
|| key.startsWith("proantitab.")
|| key.equals("*");
|| key.startsWith("-proantitab.");
}
}
@@ -65,7 +65,8 @@ public class PermissionUtil {
} else if (Storage.getPermissionPlugin() == PermissionPlugin.GROUPMANAGER) {
GroupManagerHook.setPermissions(sender.getUniqueId());
} else {
GroupManager.getGroups().forEach(group -> group.hasPermission(sender));
final boolean isOperator = sender.isOperator();
GroupManager.getGroups().forEach(group -> group.hasPermission(sender, isOperator));
}
}
@@ -75,7 +76,11 @@ public class PermissionUtil {
} else if (Storage.getPermissionPlugin() == PermissionPlugin.GROUPMANAGER) {
GroupManagerHook.setPermissions(uuid);
} else {
GroupManager.getGroups().forEach(group -> group.hasPermission(uuid));
final CommandSender sender = CommandSender.from(uuid);
if (sender == null) return;
final boolean isOperator = sender.isOperator();
GroupManager.getGroups().forEach(group -> group.hasPermission(uuid, isOperator));
}
}
@@ -87,19 +92,38 @@ public class PermissionUtil {
}
public static void setPermission(UUID uuid, String permission, boolean permitted) {
PermissionMap permissionMap;
PermissionMap permissionMap = MAP.get(uuid);
if(!MAP.containsKey(uuid)) {
if(permissionMap == null) {
permissionMap = new PermissionMap(uuid);
MAP.put(uuid, permissionMap);
} else permissionMap = MAP.get(uuid);
}
final boolean isNegatedPermission = permission.charAt(0) == '-';
// Ignore because set permission is negated.
if (!isNegatedPermission && permissionMap.isPermitted("-" + permission)) {
return;
}
if (isNegatedPermission) {
final String nonNegatedPermission = permission.substring(1);
if (permissionMap.isPermitted(nonNegatedPermission)) {
permissionMap.setState(nonNegatedPermission, false);
return;
}
}
permissionMap.setState(permission, permitted);
}
public static boolean hasPermission(Object targetObj, String permission) {
PermissionMap permissionMap;
public static boolean hasPermission(final Object targetObj, final String permission, final boolean isOperator) {
if (isOperator) return true;
PermissionMap permissionMap;
CommandSender sender = null;
UUID uuid = null;
@@ -127,8 +151,7 @@ public class PermissionUtil {
return true;
}
return sender.isOperator()
|| sender.hasPermission("*")
return sender.hasPermission("*")
|| sender.hasPermission("proantitab.*")
|| sender.hasPermission("proantitab." + permission);
}
@@ -161,31 +184,33 @@ public class PermissionUtil {
permissionMap.setState("proantitab." + permission, sender.hasPermission("proantitab." + permission));
}
if (sender.isOperator()) {
return true;
}
}
return permissionMap.isPermitted("*") || permissionMap.isPermitted("proantitab.*") || permissionMap.isPermitted("proantitab." + permission);
return permissionMap.isPermitted("*")
|| permissionMap.isPermitted("proantitab.*")
|| permissionMap.isPermitted("proantitab." + permission);
}
public static boolean hasBypassPermission(Object targetObj) {
public static boolean hasBypassPermission(Object targetObj, final boolean isOperator) {
if (!Reflection.isProxyServer() && Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) {
return false;
}
return hasPermission(targetObj, "bypass");
return hasPermission(targetObj, "bypass", isOperator);
}
public static boolean hasBypassPermission(Object targetObj, String command) {
public static boolean hasBypassPermission(
final Object targetObj,
final String command,
final boolean isOperator
) {
if (!Reflection.isProxyServer() && Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) {
return false;
}
if (hasBypassPermission(targetObj)) {
if (hasBypassPermission(targetObj, isOperator)) {
return true;
}
@@ -193,11 +218,15 @@ public class PermissionUtil {
return false;
}
return hasPermission(targetObj, "bypass." + command);
return hasPermission(targetObj, "bypass." + command, isOperator);
}
public static boolean hasPermissionWithResponse(Object targetObj, String command) {
boolean permitted = hasPermission(targetObj, command);
public static boolean hasPermissionWithResponse(
final Object targetObj,
final String command,
final boolean isOperator
) {
boolean permitted = hasPermission(targetObj, command, isOperator);
if (!permitted && targetObj instanceof CommandSender) {
String message = Storage.ConfigSections.Messages.NO_PERMISSION.MESSAGE;
+1 -1
View File
@@ -3,7 +3,7 @@ description: Hides more than just your plugins.
website: https://www.rayzs.de/products/proantitab/page
author: Rayzs_YT
version: 2.4.2
version: 2.5.1
main: de.rayzs.pat.plugin.BungeeLoader
softDepends: [LuckPerms, PAPIProxyBridge]
@@ -101,6 +101,28 @@ update-groups-per-world: false
# of the player accordingly.
auto-forward-luckperms-changes: false
# This option here works as a whitelist and hides certain plugins channels
# from the user, if they are not supposed to be able to register for any
# of the non-mentioned plugin channels below. This prevents modern plugin
# spoofing attempts that are now trying to find plugins via their plugin
# channel.
#
# (!) Warning:
# Currently only works on standalone Spigot servers >=1.20
# and proxies like Bungeecord/Velocity. It's also not
# recommended to enable this feature, unless you know
# what plugin channels are and which may be needed
# for your server, in case your server supports a specific
# minecraft client that relies on plugin channels for identification!
plugin-channels-hider:
enabled: false
whitelisted-channels:
- "minecraft:brand"
- "bungeecord:main"
- "velocity:main"
# Here you can customize the server version that is displayed on a ping. (The text at the player-count)
# (!) Warning: It's required to use Paper or Purpur to use this feature!
# (!) Supported server versions: 1.12.2 - latest
+26
View File
@@ -64,11 +64,37 @@ allow-group-overruling: false
# lpv (...) permission set proantitab.group.<group> server=<server>
update-groups-per-server: false
# If you whitelist a command using PAT that does not exist, it would still
# make the command tab-completable, even though it doesn't exist.
# (!) WARNING: Only works with PAT groups!
tab-completion-for-not-existing-commands: false
# Enabling this forwards the notification message to the backend
# server so it will be displayed there as well. (Only in console)
forward-console-notification-alerts: false
# This option here works as a whitelist and hides certain plugins channels
# from the user, if they are not supposed to be able to register for any
# of the non-mentioned plugin channels below. This prevents modern plugin
# spoofing attempts that are now trying to find plugins via their plugin
# channel.
#
# (!) Warning:
# Currently only works on standalone Spigot servers >=1.20
# and proxies like Bungeecord/Velocity. It's also not
# recommended to enable this feature, unless you know
# what plugin channels are and which may be needed
# for your server, in case your server supports a specific
# minecraft client that relies on plugin channels for identification!
plugin-channels-hider:
enabled: false
whitelisted-channels:
- "minecraft:brand"
- "bungeecord:main"
- "velocity:main"
# Here you can customize the server version that is displayed on a ping. (The text at the player-count)
custom-protocol-ping:
enabled: true
+1 -1
View File
@@ -3,7 +3,7 @@ description: Hides more than just your plugins.
website: https://www.rayzs.de/products/proantitab/page
author: Rayzs_YT
version: 2.4.2
version: 2.5.1
api-version: 1.13
folia-supported: true
main: de.rayzs.pat.plugin.BukkitLoader