mirror of
https://github.com/RayzsYT/ProAntiTab.git
synced 2026-11-05 09:10:29 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11ee68fa3f | ||
|
|
2c3d3fac92 | ||
|
|
e524f898da | ||
|
|
c181cfbbc4 | ||
|
|
1110466235 | ||
|
|
a965dd231b | ||
|
|
6418e4f42a | ||
|
|
e71909fcd7 | ||
|
|
c6f9fc8d3e | ||
|
|
88cb03c82e | ||
|
|
b53678764a | ||
|
|
1f7743d089 | ||
|
|
a60b6896f7 | ||
|
|
34c33df136 | ||
|
|
ef63674b0c | ||
|
|
130af1547d | ||
|
|
cdb17c1ea8 | ||
|
|
8f4f4b6438 | ||
|
|
3a0fc6e579 | ||
|
|
e0747a5101 | ||
|
|
5741dab763 | ||
|
|
5d7a8bb4c5 | ||
|
|
786b2fa560 | ||
|
|
5cf51052d2 | ||
|
|
22eaecb17f | ||
|
|
816354bb92 | ||
|
|
2fc6d96bd9 | ||
|
|
3f472b0bf5 | ||
|
|
41417893be | ||
|
|
64a7b80ec5 | ||
|
|
65f136f2b8 | ||
|
|
618bee5e9b |
No files matched your search
+29
@@ -0,0 +1,29 @@
|
||||
# Maven
|
||||
/target/
|
||||
|
||||
# IntelliJ IDEA
|
||||
/.idea/
|
||||
*.iml
|
||||
*.iws
|
||||
*.ipr
|
||||
|
||||
# Eclipse
|
||||
/.classpath
|
||||
/.project
|
||||
/.settings/
|
||||
|
||||
# VS Code
|
||||
/.vscode/
|
||||
|
||||
# Local environment and logs
|
||||
.env
|
||||
.env.*
|
||||
*.log
|
||||
*.tmp
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Maven Shade Plugin
|
||||
dependency-reduced-pom.xml
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>de.rayzs.pat</groupId>
|
||||
<artifactId>ProAntiTab</artifactId>
|
||||
<version>2.4.3</version>
|
||||
<version>2.5.1</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
@@ -14,6 +14,11 @@
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>papermc</id>
|
||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
@@ -24,14 +29,15 @@
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>papermc</id>
|
||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
<releases>
|
||||
<enabled>true</enabled>
|
||||
</releases>
|
||||
<snapshots>
|
||||
<enabled>false</enabled>
|
||||
</snapshots>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
@@ -77,17 +83,14 @@
|
||||
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
|
||||
</repository>
|
||||
|
||||
<repository>
|
||||
<id>AlessioDP</id>
|
||||
<url>https://repo.alessiodp.com/releases/</url>
|
||||
</repository>
|
||||
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.folia</groupId>
|
||||
<artifactId>folia-api</artifactId>
|
||||
<version>1.20.1-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
@@ -95,20 +98,6 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.19-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.2.0.Final</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-api</artifactId>
|
||||
@@ -116,77 +105,6 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.md-5</groupId>
|
||||
<artifactId>bungeecord-protocol</artifactId>
|
||||
<version>1.16-R0.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>com.mojang</groupId>
|
||||
<artifactId>authlib</artifactId>
|
||||
<version>4.0.43</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.ElgarL</groupId>
|
||||
<artifactId>groupmanager</artifactId>
|
||||
<version>3.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.mojang</groupId>
|
||||
<artifactId>brigadier</artifactId>
|
||||
<version>1.1.8</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.mojang</groupId>
|
||||
<artifactId>datafixerupper</artifactId>
|
||||
<version>6.0.8</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.mojang</groupId>
|
||||
<artifactId>logging</artifactId>
|
||||
<version>1.1.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-resolver-provider</artifactId>
|
||||
<version>3.8.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.resolver</groupId>
|
||||
<artifactId>maven-resolver-connector-basic</artifactId>
|
||||
<version>1.7.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.maven.resolver</groupId>
|
||||
<artifactId>maven-resolver-transport-http</artifactId>
|
||||
<version>1.7.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.18.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.github.waterfallmc</groupId>
|
||||
<artifactId>waterfall-api</artifactId>
|
||||
@@ -194,13 +112,6 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.william278</groupId>
|
||||
<artifactId>papiproxybridge</artifactId>
|
||||
<version>1.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.velocitypowered</groupId>
|
||||
<artifactId>velocity-api</artifactId>
|
||||
@@ -221,56 +132,64 @@
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.sonatype.sisu</groupId>
|
||||
<artifactId>sisu-guice</artifactId>
|
||||
<version>2.1.7</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.spongepowered</groupId>
|
||||
<artifactId>configurate-hocon</artifactId>
|
||||
<version>4.1.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-minimessage</artifactId>
|
||||
<version>5.2.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-api</artifactId>
|
||||
<version>5.2.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-platform-api</artifactId>
|
||||
<version>4.4.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-platform-bungeecord</artifactId>
|
||||
<version>4.4.1</version>
|
||||
<scope>compile</scope>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-platform-bukkit</artifactId>
|
||||
<version>4.4.1</version>
|
||||
<scope>compile</scope>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-serializer-legacy</artifactId>
|
||||
<version>5.2.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.2.0.Final</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.11.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- PLUGIN COMPATIBILITIES -->
|
||||
|
||||
|
||||
<!-- Permission plugins -->
|
||||
|
||||
<dependency>
|
||||
<groupId>net.luckperms</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>5.5</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.ElgarL</groupId>
|
||||
<artifactId>groupmanager</artifactId>
|
||||
<version>3.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- PAPI -->
|
||||
|
||||
<dependency>
|
||||
<groupId>me.clip</groupId>
|
||||
<artifactId>placeholderapi</artifactId>
|
||||
@@ -279,12 +198,15 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.luckperms</groupId>
|
||||
<artifactId>api</artifactId>
|
||||
<version>5.5</version>
|
||||
<groupId>net.william278</groupId>
|
||||
<artifactId>papiproxybridge</artifactId>
|
||||
<version>1.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Extras -->
|
||||
|
||||
<dependency>
|
||||
<groupId>com.viaversion</groupId>
|
||||
<artifactId>viaversion-api</artifactId>
|
||||
@@ -294,50 +216,5 @@
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>IgnoreThisJar</finalName>
|
||||
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<excludes>
|
||||
<exclude>*.txt</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<finalName>ProAntiTab</finalName>
|
||||
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||
<shadedClassifierName>shaded</shadedClassifierName>
|
||||
<artifactSet>
|
||||
<excludes/>
|
||||
</artifactSet>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>17</source>
|
||||
<target>17</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
</project>
|
||||
@@ -1,5 +1,6 @@
|
||||
package de.rayzs.pat.api.storage;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@@ -61,7 +62,7 @@ public class Storage {
|
||||
|
||||
public static final List<UUID> NOTIFY_PLAYERS = new ArrayList<>();
|
||||
|
||||
public static String TOKEN = "", HASHED_TOKEN = "", CENSORED_TOKEN = "", SERVER_NAME = null, CURRENT_VERSION = "", NEWER_VERSION = "";
|
||||
public static String TOKEN = "", CENSORED_TOKEN = "", SERVER_NAME = null, CURRENT_VERSION = "", NEWER_VERSION = "";
|
||||
public static boolean OUTDATED = false, SEND_CONSOLE_NOTIFICATION = true;
|
||||
public static boolean USE_PLACEHOLDERAPI = false, USE_PAPIPROXYBRIDGE = false, USE_VIAVERSION = false;
|
||||
|
||||
@@ -91,6 +92,12 @@ public class Storage {
|
||||
Logger.warning("Read more about it here: https://rayzs.de/products/proantitab/nkppf");
|
||||
}
|
||||
|
||||
private static String generateToken() {
|
||||
byte[] bytes = new byte[32];
|
||||
new SecureRandom().nextBytes(bytes);
|
||||
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
|
||||
}
|
||||
|
||||
public static PermissionPlugin getPermissionPlugin() {
|
||||
return PERMISSION_PLUGIN;
|
||||
}
|
||||
@@ -140,11 +147,9 @@ public class Storage {
|
||||
|
||||
if (useDefaultToken) {
|
||||
TOKEN = Reflection.isProxyServer()
|
||||
? (String) Files.TOKEN.getOrSet("token", UUID.randomUUID().toString())
|
||||
? (String) Files.TOKEN.getOrSet("token", generateToken())
|
||||
: ConfigSections.Settings.HANDLE_THROUGH_PROXY.TOKEN;
|
||||
}
|
||||
|
||||
HASHED_TOKEN = Objects.requireNonNullElse(StringUtils.hashString(TOKEN, "SHA-256"), TOKEN);
|
||||
}
|
||||
|
||||
public static void loadConfig() {
|
||||
@@ -335,8 +340,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();
|
||||
@@ -348,7 +356,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();
|
||||
@@ -412,7 +419,7 @@ public class Storage {
|
||||
public static String findAndReplace(Player player, String request) {
|
||||
String result = null, param = "";
|
||||
|
||||
if(USE_PLACEHOLDERAPI) {
|
||||
if (USE_PLACEHOLDERAPI) {
|
||||
for (PlaceholderStorage storage : PLACEHOLDERS) {
|
||||
if (!storage.getRequest().startsWith(request)) continue;
|
||||
|
||||
@@ -428,7 +435,7 @@ public class Storage {
|
||||
|
||||
// Second time because of nested placeholders
|
||||
if (result != null && result.contains("%")) {
|
||||
result = PlaceholderReplacer.replace(player, result);
|
||||
result = PlaceholderReplacer.applyPlaceholders(CommandSender.from(player), result);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
-1
@@ -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);
|
||||
}
|
||||
}
|
||||
+22
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import de.rayzs.pat.utils.group.Group;
|
||||
import de.rayzs.pat.utils.hooks.GroupManagerHook;
|
||||
import de.rayzs.pat.utils.configuration.Configurator;
|
||||
import de.rayzs.pat.utils.configuration.updater.ConfigUpdater;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.permission.PermissionUtil;
|
||||
import de.rayzs.pat.utils.hooks.ViaVersionHook;
|
||||
import de.rayzs.pat.plugin.system.communication.Communicator;
|
||||
@@ -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;
|
||||
@@ -94,7 +95,7 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
|
||||
if (Bukkit.getServer().getPluginManager().getPlugin("PlaceholderAPI") != null)
|
||||
new PlaceholderHook().register();
|
||||
|
||||
MessageTranslator.initialize();
|
||||
MessageHelper.initialize();
|
||||
|
||||
Communicator.initialize(new BukkitPluginMessageClient(), new BukkitCommunicationHandler());
|
||||
BackendUpdater.initialize();
|
||||
@@ -158,6 +159,11 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
|
||||
});
|
||||
|
||||
|
||||
|
||||
// Register permissions for LuckPerms to recognise.
|
||||
|
||||
addPermission("bypass");
|
||||
|
||||
for (final ProCommand command : CommandProcess.getCommands()) {
|
||||
addPermission(command.getName());
|
||||
}
|
||||
@@ -189,7 +195,7 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
|
||||
public void onDisable() {
|
||||
BackendUpdater.get().stop();
|
||||
BukkitPacketAnalyzer.uninjectAll();
|
||||
MessageTranslator.closeAudiences();
|
||||
MessageHelper.closeAudiences();
|
||||
}
|
||||
|
||||
public void registerCommand(String... commands) {
|
||||
@@ -235,9 +241,7 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
|
||||
if (commandsMap == null)
|
||||
return false;
|
||||
|
||||
loadAllCommands();
|
||||
|
||||
return getAllCommands().contains(command);
|
||||
return registeredCommands.contains(command);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -355,12 +359,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;
|
||||
@@ -442,50 +444,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() {
|
||||
|
||||
@@ -11,7 +11,7 @@ import de.rayzs.pat.plugin.packetanalyzer.proxy.BungeePacketAnalyzer;
|
||||
import de.rayzs.pat.plugin.system.subargument.SubArgument;
|
||||
import de.rayzs.pat.utils.configuration.Configurator;
|
||||
import de.rayzs.pat.utils.configuration.updater.ConfigUpdater;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.hooks.LuckPermsHook;
|
||||
import de.rayzs.pat.plugin.system.communication.Communicator;
|
||||
import de.rayzs.pat.utils.response.ResponseHandler;
|
||||
@@ -64,7 +64,7 @@ public class BungeeLoader extends Plugin implements PluginLoader {
|
||||
|
||||
Storage.loadAll(true);
|
||||
|
||||
MessageTranslator.initialize();
|
||||
MessageHelper.initialize();
|
||||
GroupManager.initialize();
|
||||
|
||||
bStats.initialize(this);
|
||||
@@ -121,7 +121,7 @@ public class BungeeLoader extends Plugin implements PluginLoader {
|
||||
@Override
|
||||
public void onDisable() {
|
||||
BungeePacketAnalyzer.uninjectAll();
|
||||
MessageTranslator.closeAudiences();
|
||||
MessageHelper.closeAudiences();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,7 +18,7 @@ import com.velocitypowered.api.scheduler.ScheduledTask;
|
||||
import de.rayzs.pat.utils.configuration.Configurator;
|
||||
import de.rayzs.pat.utils.configuration.updater.ConfigUpdater;
|
||||
import de.rayzs.pat.plugin.command.impl.VelocityCommand;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.plugin.system.communication.Communicator;
|
||||
import de.rayzs.pat.utils.hooks.LuckPermsHook;
|
||||
import com.velocitypowered.api.proxy.ProxyServer;
|
||||
@@ -40,16 +40,6 @@ import de.rayzs.pat.utils.sender.CommandSender;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Plugin(name = "ProAntiTab",
|
||||
id = "proantitab",
|
||||
version = "2.4.3",
|
||||
authors = "Rayzs_YT",
|
||||
description = "Hides more than just your plugins.",
|
||||
url = "https://www.rayzs.de/products/proantitab/page",
|
||||
dependencies = {
|
||||
@Dependency(id = "luckperms", optional = true),
|
||||
@Dependency(id = "papiproxybridge", optional = true)
|
||||
})
|
||||
public class VelocityLoader implements PluginLoader {
|
||||
|
||||
private static VelocityLoader instance;
|
||||
@@ -91,7 +81,7 @@ public class VelocityLoader implements PluginLoader {
|
||||
VersionComparer.get().setCurrentVersion(Storage.CURRENT_VERSION);
|
||||
|
||||
Storage.loadAll(true);
|
||||
MessageTranslator.initialize();
|
||||
MessageHelper.initialize();
|
||||
GroupManager.initialize();
|
||||
|
||||
metricsFactory.make(this, 21638);
|
||||
|
||||
@@ -24,16 +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();
|
||||
final boolean isOperator = player.isOp();
|
||||
|
||||
|
||||
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);
|
||||
@@ -60,7 +61,7 @@ public class BukkitAntiTabListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Reflection.isCraftbukkit() && !Bukkit.getOnlinePlayers().contains(player)) {
|
||||
if (Reflection.isBukkit() && !Bukkit.getOnlinePlayers().contains(player)) {
|
||||
event.getCommands().clear();
|
||||
|
||||
PATScheduler.createScheduler(player::updateCommands, 10);
|
||||
|
||||
+17
-23
@@ -20,7 +20,7 @@ import de.rayzs.pat.api.event.events.ExecuteCommandEvent;
|
||||
import de.rayzs.pat.api.storage.Storage;
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.permission.PermissionUtil;
|
||||
|
||||
public class BukkitBlockCommandListener implements Listener {
|
||||
@@ -40,17 +40,11 @@ public class BukkitBlockCommandListener implements Listener {
|
||||
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());
|
||||
MessageHelper.sendMessage(sender, Storage.ConfigSections.Settings.CUSTOM_UNKNOWN_COMMAND.MESSAGE, "%command%", command, "%world%", world.getName());
|
||||
}
|
||||
|
||||
@EventHandler (priority = EventPriority.LOWEST)
|
||||
@@ -95,17 +89,16 @@ public class BukkitBlockCommandListener implements Listener {
|
||||
}
|
||||
|
||||
final String displayCommand = StringUtils.replaceTriggers(command, "", "\\", "<", ">", "&");
|
||||
|
||||
List<String> notificationMessage = MessageTranslator.replaceMessageList(
|
||||
Storage.ConfigSections.Messages.NOTIFICATION.ALERT,
|
||||
final String notificationMessage = StringUtils.replace(
|
||||
Storage.ConfigSections.Messages.NOTIFICATION.ALERT.getLines(),
|
||||
"%player%", player.getName(),
|
||||
"%command%", displayCommand,
|
||||
"%world%", worldName);
|
||||
|
||||
if (Storage.ConfigSections.Settings.CUSTOM_PLUGIN.isCommand(command)) {
|
||||
|
||||
MessageTranslator.send(
|
||||
player,
|
||||
MessageHelper.sendMessage(
|
||||
sender,
|
||||
Storage.ConfigSections.Settings.CUSTOM_PLUGIN.MESSAGE,
|
||||
"%command%", StringUtils.getFirstArg(displayCommand)
|
||||
);
|
||||
@@ -114,9 +107,9 @@ public class BukkitBlockCommandListener implements Listener {
|
||||
Logger.info(notificationMessage);
|
||||
|
||||
Storage.NOTIFY_PLAYERS.forEach(uuid -> {
|
||||
Object p = Storage.getLoader().getPlayerObjByUUID(uuid);
|
||||
if (p != null) {
|
||||
MessageTranslator.send(p, notificationMessage);
|
||||
final CommandSender otherSender = CommandSender.from(uuid);
|
||||
if (otherSender != null) {
|
||||
MessageHelper.sendMessage(otherSender, notificationMessage);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -126,8 +119,8 @@ public class BukkitBlockCommandListener implements Listener {
|
||||
|
||||
if (Storage.ConfigSections.Settings.CUSTOM_VERSION.isCommand(command)) {
|
||||
|
||||
MessageTranslator.send(
|
||||
player,
|
||||
MessageHelper.sendMessage(
|
||||
sender,
|
||||
Storage.ConfigSections.Settings.CUSTOM_VERSION.MESSAGE,
|
||||
"%command%", StringUtils.getFirstArg(displayCommand)
|
||||
);
|
||||
@@ -138,7 +131,7 @@ public class BukkitBlockCommandListener implements Listener {
|
||||
Storage.NOTIFY_PLAYERS.forEach(uuid -> {
|
||||
Object p = Storage.getLoader().getPlayerObjByUUID(uuid);
|
||||
if (p != null) {
|
||||
MessageTranslator.send(p, notificationMessage);
|
||||
MessageHelper.sendMessage(sender, notificationMessage);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -175,7 +168,8 @@ public class BukkitBlockCommandListener implements Listener {
|
||||
if (executeCommandEvent.isBlocked()) {
|
||||
event.setCancelled(true);
|
||||
|
||||
MessageTranslator.send(
|
||||
|
||||
MessageHelper.sendMessage(
|
||||
sender,
|
||||
ResponseHandler.getResponse(
|
||||
sender.getUniqueId(),
|
||||
@@ -193,8 +187,8 @@ public class BukkitBlockCommandListener implements Listener {
|
||||
Logger.info(notificationMessage);
|
||||
|
||||
Storage.NOTIFY_PLAYERS.stream().filter(uuid -> Bukkit.getServer().getPlayer(uuid) != null).forEach(uuid -> {
|
||||
Player target = Bukkit.getServer().getPlayer(uuid);
|
||||
MessageTranslator.send(target, notificationMessage);
|
||||
final CommandSender otherSender = CommandSender.from(uuid);
|
||||
MessageHelper.sendMessage(otherSender, notificationMessage);
|
||||
});
|
||||
|
||||
}
|
||||
@@ -213,7 +207,7 @@ public class BukkitBlockCommandListener implements Listener {
|
||||
if (executeCommandEvent.isBlocked()) {
|
||||
event.setCancelled(true);
|
||||
|
||||
MessageTranslator.send(
|
||||
MessageHelper.sendMessage(
|
||||
sender,
|
||||
ResponseHandler.getResponse(
|
||||
sender.getUniqueId(),
|
||||
|
||||
@@ -7,7 +7,8 @@ import de.rayzs.pat.plugin.packetanalyzer.bukkit.BukkitPacketAnalyzer;
|
||||
import de.rayzs.pat.plugin.system.communication.BackendUpdater;
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.plugin.system.subargument.SubArgument;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import de.rayzs.pat.utils.permission.PermissionPlugin;
|
||||
import de.rayzs.pat.utils.permission.PermissionUtil;
|
||||
import de.rayzs.pat.api.storage.Storage;
|
||||
@@ -52,19 +53,23 @@ public class BukkitPlayerListener implements Listener {
|
||||
}, 20);
|
||||
}
|
||||
|
||||
if (!BukkitPacketAnalyzer.inject(player)) {
|
||||
|
||||
final BukkitPacketAnalyzer.InjectionState injectionState = BukkitPacketAnalyzer.inject(player);
|
||||
|
||||
|
||||
if (injectionState == BukkitPacketAnalyzer.InjectionState.FAILED) {
|
||||
PATScheduler.createScheduler(() -> {
|
||||
if (player.isOnline()) {
|
||||
if (!BukkitPacketAnalyzer.inject(player)) {
|
||||
if (BukkitPacketAnalyzer.inject(player) == BukkitPacketAnalyzer.InjectionState.FAILED) {
|
||||
|
||||
if (Storage.ConfigSections.Settings.INJECTION_FAILED.ENABLED) {
|
||||
|
||||
Logger.info(MessageTranslator.replaceMessage(
|
||||
Logger.info(PlaceholderReplacer.applyPlaceholders(
|
||||
sender,
|
||||
Storage.ConfigSections.Settings.INJECTION_FAILED.CONSOLE_MESSAGE
|
||||
));
|
||||
|
||||
player.kickPlayer(MessageTranslator.replaceMessage(
|
||||
player.kickPlayer(PlaceholderReplacer.applyPlaceholders(
|
||||
sender,
|
||||
Storage.ConfigSections.Settings.INJECTION_FAILED.KICK_MESSAGE
|
||||
));
|
||||
@@ -73,12 +78,14 @@ public class BukkitPlayerListener implements Listener {
|
||||
}
|
||||
}
|
||||
}, 10);
|
||||
} else if (injectionState == BukkitPacketAnalyzer.InjectionState.SKIPPED) {
|
||||
Logger.warning("Skipped injection for " + player.getName() + ". Player seems to have a corrupted pipeline. (A fake player?)");
|
||||
}
|
||||
|
||||
if (Storage.OUTDATED && PermissionUtil.hasPermission(sender, "joinupdate", isOperator)) {
|
||||
PATScheduler.createScheduler(() -> {
|
||||
if (player.isOnline()) {
|
||||
MessageTranslator.send(player, Storage.ConfigSections.Settings.UPDATE.OUTDATED.getLines());
|
||||
MessageHelper.sendMessage(sender, Storage.ConfigSections.Settings.UPDATE.OUTDATED.getLines());
|
||||
}
|
||||
}, 20);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import de.rayzs.pat.api.storage.Storage;
|
||||
import de.rayzs.pat.utils.ExpireCache;
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
import org.bukkit.event.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.profile.PlayerTextures;
|
||||
@@ -105,7 +106,9 @@ public class PaperServerListPing implements Listener {
|
||||
.replace("%online%", String.valueOf(online))
|
||||
.replace("%max%", String.valueOf(max));
|
||||
|
||||
return replaced.contains("%") ? PlaceholderReplacer.replace(null, replaced) : replaced;
|
||||
return replaced.contains("%")
|
||||
? PlaceholderReplacer.applyPlaceholders(CommandSender.from(Bukkit.getConsoleSender()), replaced)
|
||||
: replaced;
|
||||
}
|
||||
|
||||
private static class ProtocolHoverLine implements PlayerProfile {
|
||||
@@ -218,7 +221,7 @@ public class PaperServerListPing implements Listener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public org.bukkit.profile.@NotNull PlayerProfile clone() {
|
||||
public PlayerProfile clone() {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
+20
-18
@@ -6,7 +6,7 @@ import de.rayzs.pat.plugin.system.subargument.SubArgument;
|
||||
import de.rayzs.pat.utils.group.Group;
|
||||
import de.rayzs.pat.utils.group.GroupManager;
|
||||
import de.rayzs.pat.utils.permission.PermissionUtil;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.response.ResponseHandler;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
import net.md_5.bungee.api.event.ChatEvent;
|
||||
@@ -50,8 +50,8 @@ public class BungeeBlockCommandListener implements Listener {
|
||||
final String displayCommand = StringUtils.replaceTriggers(command, "", "\\", "<", ">", "&");
|
||||
|
||||
|
||||
final List<String> notificationMessage = MessageTranslator.replaceMessageList(
|
||||
Storage.ConfigSections.Messages.NOTIFICATION.ALERT,
|
||||
final String notificationMessage = StringUtils.replace(
|
||||
Storage.ConfigSections.Messages.NOTIFICATION.ALERT.getLines(),
|
||||
"%player%", player.getName(),
|
||||
"%command%", displayCommand,
|
||||
"%server%", serverName);
|
||||
@@ -60,8 +60,8 @@ public class BungeeBlockCommandListener implements Listener {
|
||||
|
||||
Communicator.Proxy2Backend.sendNotification(player.getUniqueId(), serverName, displayCommand);
|
||||
|
||||
MessageTranslator.send(
|
||||
player,
|
||||
MessageHelper.sendMessage(
|
||||
sender,
|
||||
Storage.ConfigSections.Settings.CUSTOM_PLUGIN.MESSAGE,
|
||||
"%command%", StringUtils.getFirstArg(displayCommand)
|
||||
);
|
||||
@@ -70,9 +70,10 @@ public class BungeeBlockCommandListener implements Listener {
|
||||
Logger.info(notificationMessage);
|
||||
|
||||
Storage.NOTIFY_PLAYERS.stream().forEach(uuid -> {
|
||||
Object p = Storage.getLoader().getPlayerObjByUUID(uuid);
|
||||
if (p != null) {
|
||||
MessageTranslator.send(p, notificationMessage);
|
||||
final CommandSender otherSender = CommandSender.from(uuid);
|
||||
|
||||
if (otherSender != null) {
|
||||
MessageHelper.sendMessage(otherSender, notificationMessage);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -84,8 +85,8 @@ public class BungeeBlockCommandListener implements Listener {
|
||||
|
||||
Communicator.Proxy2Backend.sendNotification(player.getUniqueId(), serverName, displayCommand);
|
||||
|
||||
MessageTranslator.send(
|
||||
player,
|
||||
MessageHelper.sendMessage(
|
||||
sender,
|
||||
Storage.ConfigSections.Settings.CUSTOM_VERSION.MESSAGE,
|
||||
"%command%", StringUtils.getFirstArg(displayCommand)
|
||||
);
|
||||
@@ -94,9 +95,10 @@ public class BungeeBlockCommandListener implements Listener {
|
||||
Logger.info(notificationMessage);
|
||||
|
||||
Storage.NOTIFY_PLAYERS.forEach(uuid -> {
|
||||
Object p = Storage.getLoader().getPlayerObjByUUID(uuid);
|
||||
if (p != null) {
|
||||
MessageTranslator.send(p, notificationMessage);
|
||||
final CommandSender otherSender = CommandSender.from(uuid);
|
||||
|
||||
if (otherSender != null) {
|
||||
MessageHelper.sendMessage(otherSender, notificationMessage);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -133,7 +135,7 @@ public class BungeeBlockCommandListener implements Listener {
|
||||
if (executeCommandEvent.isBlocked()) {
|
||||
event.setCancelled(true);
|
||||
|
||||
MessageTranslator.send(
|
||||
MessageHelper.sendMessage(
|
||||
sender,
|
||||
ResponseHandler.getResponse(
|
||||
sender.getUniqueId(),
|
||||
@@ -153,10 +155,10 @@ public class BungeeBlockCommandListener implements Listener {
|
||||
Logger.info(notificationMessage);
|
||||
|
||||
Storage.NOTIFY_PLAYERS.forEach(uuid -> {
|
||||
Object p = Storage.getLoader().getPlayerObjByUUID(uuid);
|
||||
final CommandSender otherSender = CommandSender.from(uuid);
|
||||
|
||||
if (p != null) {
|
||||
MessageTranslator.send(p, notificationMessage);
|
||||
if (otherSender != null) {
|
||||
MessageHelper.sendMessage(otherSender, notificationMessage);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -176,7 +178,7 @@ public class BungeeBlockCommandListener implements Listener {
|
||||
if (executeCommandEvent.isBlocked()) {
|
||||
event.setCancelled(true);
|
||||
|
||||
MessageTranslator.send(
|
||||
MessageHelper.sendMessage(
|
||||
sender,
|
||||
ResponseHandler.getResponse(
|
||||
sender.getUniqueId(),
|
||||
|
||||
+2
-2
@@ -6,7 +6,7 @@ import de.rayzs.pat.api.event.events.ServerPlayersChangeEvent;
|
||||
import de.rayzs.pat.plugin.packetanalyzer.proxy.BungeePacketAnalyzer;
|
||||
import de.rayzs.pat.plugin.system.subargument.SubArgument;
|
||||
import de.rayzs.pat.utils.permission.PermissionUtil;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
@@ -39,7 +39,7 @@ public class BungeePlayerConnectionListener implements Listener {
|
||||
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());
|
||||
MessageHelper.sendMessage(sender, Storage.ConfigSections.Settings.UPDATE.OUTDATED, "%player%", player.getName());
|
||||
}
|
||||
}, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
+41
-23
@@ -8,7 +8,7 @@ import de.rayzs.pat.api.event.events.ExecuteCommandEvent;
|
||||
import de.rayzs.pat.plugin.system.subargument.SubArgument;
|
||||
import de.rayzs.pat.utils.group.Group;
|
||||
import de.rayzs.pat.utils.group.GroupManager;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.permission.PermissionUtil;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import de.rayzs.pat.api.storage.Storage;
|
||||
@@ -36,7 +36,7 @@ public class VelocityBlockCommandListener {
|
||||
}
|
||||
|
||||
final CommandSource commandSource = event.getCommandSource();
|
||||
final Object consoleSender = Storage.getLoader().getConsoleSender();
|
||||
final CommandSender consoleSender = CommandSender.from(Storage.getLoader().getConsoleSender());
|
||||
|
||||
if(! (commandSource instanceof Player))
|
||||
return event;
|
||||
@@ -62,8 +62,8 @@ public class VelocityBlockCommandListener {
|
||||
final String displayCommand = StringUtils.replaceTriggers(command, "", "\\", "<", ">", "&");
|
||||
|
||||
|
||||
final List<String> notificationMessage = MessageTranslator.replaceMessageList(
|
||||
Storage.ConfigSections.Messages.NOTIFICATION.ALERT,
|
||||
final String notificationMessage = StringUtils.replace(
|
||||
Storage.ConfigSections.Messages.NOTIFICATION.ALERT.getLines(),
|
||||
"%player%", player.getUsername(),
|
||||
"%command%", displayCommand,
|
||||
"%server%", serverName
|
||||
@@ -73,19 +73,20 @@ public class VelocityBlockCommandListener {
|
||||
|
||||
Communicator.Proxy2Backend.sendNotification(player.getUniqueId(), serverName, displayCommand);
|
||||
|
||||
MessageTranslator.send(
|
||||
player,
|
||||
MessageHelper.sendMessage(
|
||||
sender,
|
||||
Storage.ConfigSections.Settings.CUSTOM_PLUGIN.MESSAGE,
|
||||
"%command%", StringUtils.getFirstArg(displayCommand)
|
||||
);
|
||||
|
||||
if (Storage.SEND_CONSOLE_NOTIFICATION)
|
||||
MessageTranslator.send(consoleSender, notificationMessage);
|
||||
MessageHelper.sendMessage(consoleSender, notificationMessage);
|
||||
|
||||
Storage.NOTIFY_PLAYERS.forEach(uuid -> {
|
||||
Object p = Storage.getLoader().getPlayerObjByUUID(uuid);
|
||||
if (p != null) {
|
||||
MessageTranslator.send(p, notificationMessage);
|
||||
final CommandSender otherSender = CommandSender.from(uuid);
|
||||
|
||||
if (otherSender != null) {
|
||||
MessageHelper.sendMessage(otherSender, notificationMessage);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -97,19 +98,20 @@ public class VelocityBlockCommandListener {
|
||||
|
||||
Communicator.Proxy2Backend.sendNotification(player.getUniqueId(), serverName, displayCommand);
|
||||
|
||||
MessageTranslator.send(
|
||||
player,
|
||||
MessageHelper.sendMessage(
|
||||
sender,
|
||||
Storage.ConfigSections.Settings.CUSTOM_VERSION.MESSAGE,
|
||||
"%command%", StringUtils.getFirstArg(displayCommand)
|
||||
);
|
||||
|
||||
if (Storage.SEND_CONSOLE_NOTIFICATION)
|
||||
MessageTranslator.send(consoleSender, notificationMessage);
|
||||
MessageHelper.sendMessage(consoleSender, notificationMessage);
|
||||
|
||||
Storage.NOTIFY_PLAYERS.forEach(uuid -> {
|
||||
Object p = Storage.getLoader().getPlayerObjByUUID(uuid);
|
||||
if (p != null) {
|
||||
MessageTranslator.send(p, notificationMessage);
|
||||
final CommandSender otherSender = CommandSender.from(uuid);
|
||||
|
||||
if (otherSender != null) {
|
||||
MessageHelper.sendMessage(otherSender, notificationMessage);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -139,7 +141,6 @@ public class VelocityBlockCommandListener {
|
||||
|
||||
|
||||
if (!allowed) {
|
||||
|
||||
ExecuteCommandEvent executeCommandEvent = PATEventHandler.callExecuteCommandEvents(
|
||||
sender,
|
||||
event.getCommand(),
|
||||
@@ -150,7 +151,7 @@ public class VelocityBlockCommandListener {
|
||||
if (executeCommandEvent.isBlocked()) {
|
||||
event.setResult(CommandExecuteEvent.CommandResult.denied());
|
||||
|
||||
MessageTranslator.send(
|
||||
MessageHelper.sendMessage(
|
||||
sender,
|
||||
ResponseHandler.getResponse(
|
||||
sender.getUniqueId(),
|
||||
@@ -167,12 +168,13 @@ public class VelocityBlockCommandListener {
|
||||
Communicator.Proxy2Backend.sendNotification(player.getUniqueId(), serverName, displayCommand);
|
||||
|
||||
if (Storage.SEND_CONSOLE_NOTIFICATION)
|
||||
MessageTranslator.send(consoleSender, notificationMessage);
|
||||
MessageHelper.sendMessage(consoleSender, notificationMessage);
|
||||
|
||||
Storage.NOTIFY_PLAYERS.forEach(uuid -> {
|
||||
Object p = Storage.getLoader().getPlayerObjByUUID(uuid);
|
||||
if (p != null) {
|
||||
MessageTranslator.send(p, notificationMessage);
|
||||
final CommandSender otherSender = CommandSender.from(uuid);
|
||||
|
||||
if (otherSender != null) {
|
||||
MessageHelper.sendMessage(otherSender, notificationMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -190,9 +192,25 @@ 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(
|
||||
MessageHelper.sendMessage(
|
||||
sender,
|
||||
ResponseHandler.getResponse(
|
||||
sender.getUniqueId(),
|
||||
|
||||
+8
-7
@@ -8,7 +8,8 @@ import de.rayzs.pat.api.event.events.ServerPlayersChangeEvent;
|
||||
import de.rayzs.pat.plugin.packetanalyzer.proxy.VelocityPacketAnalyzer;
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.plugin.system.subargument.SubArgument;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import de.rayzs.pat.utils.permission.PermissionUtil;
|
||||
import com.velocitypowered.api.event.Subscribe;
|
||||
import com.velocitypowered.api.event.player.*;
|
||||
@@ -55,7 +56,7 @@ public class VelocityConnectionListener {
|
||||
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());
|
||||
MessageHelper.sendMessage(sender, Storage.ConfigSections.Settings.UPDATE.OUTDATED, "%player%", player.getUsername());
|
||||
}).delay(1, TimeUnit.SECONDS).schedule();
|
||||
}
|
||||
}
|
||||
@@ -63,6 +64,7 @@ public class VelocityConnectionListener {
|
||||
@Subscribe
|
||||
public void onServerSwitch(ServerConnectedEvent event) {
|
||||
final Player player = event.getPlayer();
|
||||
final CommandSender sender = CommandSender.from(player);
|
||||
|
||||
if (!VelocityPacketAnalyzer.isInjected(player)) {
|
||||
|
||||
@@ -71,14 +73,14 @@ public class VelocityConnectionListener {
|
||||
if (!VelocityPacketAnalyzer.inject(player)) {
|
||||
if (Storage.ConfigSections.Settings.INJECTION_FAILED.ENABLED) {
|
||||
|
||||
Logger.info(MessageTranslator.replaceMessage(
|
||||
player,
|
||||
Logger.info(PlaceholderReplacer.applyPlaceholders(
|
||||
sender,
|
||||
Storage.ConfigSections.Settings.INJECTION_FAILED.CONSOLE_MESSAGE
|
||||
));
|
||||
|
||||
player.disconnect(Component.text(
|
||||
MessageTranslator.replaceMessage(
|
||||
player,
|
||||
PlaceholderReplacer.applyPlaceholders(
|
||||
sender,
|
||||
Storage.ConfigSections.Settings.INJECTION_FAILED.KICK_MESSAGE
|
||||
)
|
||||
));
|
||||
@@ -93,7 +95,6 @@ public class VelocityConnectionListener {
|
||||
final ServerInfo serverInfo = event.getServer().getServerInfo();
|
||||
if (serverInfo != null) Storage.tempCachePlayerToServer(player.getUniqueId(), serverInfo.getName());
|
||||
|
||||
CommandSender sender = CommandSender.from(player);
|
||||
Objects.requireNonNull(sender);
|
||||
PermissionUtil.reloadPermissions(sender);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package de.rayzs.pat.plugin.logger.impl;
|
||||
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.plugin.BukkitLoader;
|
||||
import de.rayzs.pat.plugin.logger.*;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
import org.bukkit.Bukkit;
|
||||
import java.util.*;
|
||||
|
||||
public class BukkitLogger implements LoggerTemplate {
|
||||
|
||||
private final CommandSender console = CommandSender.from(Bukkit.getServer().getConsoleSender());
|
||||
private final java.util.logging.Logger logger = BukkitLoader.getPluginLogger();
|
||||
|
||||
@Override
|
||||
@@ -37,10 +40,10 @@ public class BukkitLogger implements LoggerTemplate {
|
||||
|
||||
@Override
|
||||
public void send(LoggerPriority priority, String message) {
|
||||
message = MessageTranslator.replaceMessage(message);
|
||||
message = PlaceholderReplacer.applyPlaceholders(null, message);
|
||||
|
||||
if (message.contains("§")) {
|
||||
MessageTranslator.send(Bukkit.getServer().getConsoleSender(), message);
|
||||
MessageHelper.sendMessage(console, message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
package de.rayzs.pat.plugin.logger.impl;
|
||||
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.plugin.BungeeLoader;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import de.rayzs.pat.plugin.logger.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class BungeeLogger implements LoggerTemplate {
|
||||
|
||||
private final CommandSender console = CommandSender.from(ProxyServer.getInstance().getConsole());
|
||||
private final java.util.logging.Logger logger = BungeeLoader.getPluginLogger();
|
||||
|
||||
@Override
|
||||
@@ -37,10 +41,10 @@ public class BungeeLogger implements LoggerTemplate {
|
||||
|
||||
@Override
|
||||
public void send(LoggerPriority priority, String message) {
|
||||
message = MessageTranslator.replaceMessage(message);
|
||||
message = PlaceholderReplacer.applyPlaceholders(null, message);
|
||||
|
||||
if (message.contains("§")) {
|
||||
MessageTranslator.send(ProxyServer.getInstance().getConsole(), message);
|
||||
MessageHelper.sendMessage(console, message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
package de.rayzs.pat.plugin.logger.impl;
|
||||
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.plugin.VelocityLoader;
|
||||
import de.rayzs.pat.plugin.logger.*;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
import org.slf4j.Logger;
|
||||
import java.util.*;
|
||||
|
||||
public class VelocityLogger implements LoggerTemplate {
|
||||
|
||||
private final CommandSender console = CommandSender.from(VelocityLoader.getServer().getConsoleCommandSource());
|
||||
private final Logger logger = VelocityLoader.getPluginLogger();
|
||||
|
||||
@Override
|
||||
@@ -37,10 +40,10 @@ public class VelocityLogger implements LoggerTemplate {
|
||||
|
||||
@Override
|
||||
public void send(LoggerPriority priority, String message) {
|
||||
message = MessageTranslator.replaceMessage(message);
|
||||
message = PlaceholderReplacer.applyPlaceholders(null, message);
|
||||
|
||||
if (message.contains("§")) {
|
||||
MessageTranslator.send(VelocityLoader.getServer().getConsoleCommandSource(), message);
|
||||
MessageHelper.sendMessage(console, message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+133
-15
@@ -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 {
|
||||
|
||||
@@ -48,15 +53,15 @@ public class BukkitPacketAnalyzer {
|
||||
channel.pipeline().writeAndFlush(object);
|
||||
}
|
||||
|
||||
public static boolean inject(Player player) {
|
||||
if (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED)
|
||||
return true;
|
||||
public static InjectionState inject(Player player) {
|
||||
if (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED && !Storage.ConfigSections.Settings.HIDE_PLUGIN_CHANNELS.ENABLED)
|
||||
return InjectionState.SKIPPED;
|
||||
|
||||
try {
|
||||
Channel channel = Reflection.getPlayerChannel(player);
|
||||
|
||||
if (channel == null) {
|
||||
return false;
|
||||
if (channel == null || !channel.pipeline().names().contains(PIPELINE_NAME)) {
|
||||
return InjectionState.SKIPPED;
|
||||
}
|
||||
|
||||
if (channel.pipeline().names().contains(BukkitPacketAnalyzer.HANDLER_NAME))
|
||||
@@ -72,31 +77,36 @@ public class BukkitPacketAnalyzer {
|
||||
// changed the compilation and therefore the variables again.
|
||||
|
||||
Reflection.toggleInjectionMethod();
|
||||
final boolean success = inject(player);
|
||||
final InjectionState state = inject(player);
|
||||
|
||||
if (!success) {
|
||||
if (state == InjectionState.FAILED) {
|
||||
Logger.warning("Both injection methods failed! Please report this back to me on my Discord! (https://www.rayzs.de/discord)");
|
||||
}
|
||||
|
||||
return success;
|
||||
return state;
|
||||
|
||||
} catch (NoSuchFieldException noSuchFieldException) {
|
||||
|
||||
if (!Storage.ConfigSections.Settings.INJECTION_FAILED.ENABLED) {
|
||||
return InjectionState.SUCCESS;
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
return false;
|
||||
return InjectionState.FAILED;
|
||||
|
||||
} catch (Exception exception) {
|
||||
if (!Storage.ConfigSections.Settings.INJECTION_FAILED.SUPPRESS_EXCEPTIONS) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
return InjectionState.FAILED;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
return InjectionState.SUCCESS;
|
||||
}
|
||||
|
||||
public static void uninject(UUID uuid) {
|
||||
@@ -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) {
|
||||
@@ -123,6 +133,10 @@ public class BukkitPacketAnalyzer {
|
||||
}
|
||||
}
|
||||
|
||||
public enum InjectionState {
|
||||
SUCCESS, FAILED, SKIPPED
|
||||
}
|
||||
|
||||
public static String getPlayerInput(Player player) {
|
||||
String input = PLAYER_INPUT_CACHE.get(player);
|
||||
PLAYER_INPUT_CACHE.remove(player);
|
||||
@@ -151,13 +165,30 @@ public class BukkitPacketAnalyzer {
|
||||
@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;
|
||||
@@ -177,13 +208,30 @@ public class BukkitPacketAnalyzer {
|
||||
@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");
|
||||
|
||||
@@ -234,5 +282,75 @@ public class BukkitPacketAnalyzer {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -23,7 +23,7 @@ import de.rayzs.pat.api.storage.Storage;
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.utils.Reflection;
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.scheduler.PATScheduler;
|
||||
|
||||
public class ModernPacketHandler implements BukkitPacketHandler {
|
||||
@@ -48,8 +48,8 @@ public class ModernPacketHandler implements BukkitPacketHandler {
|
||||
if (!text.isBlank() && text.charAt(0) != '/') text = '/' + text;
|
||||
|
||||
if (Storage.ConfigSections.Settings.PATCH_EXPLOITS.isMalicious(text)) {
|
||||
MessageTranslator.send(
|
||||
Bukkit.getConsoleSender(),
|
||||
MessageHelper.sendMessage(
|
||||
CommandSender.from(Bukkit.getConsoleSender()),
|
||||
Storage.ConfigSections.Settings.PATCH_EXPLOITS.ALERT_MESSAGE.get().replace("%player%", player.getName())
|
||||
);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -146,16 +148,17 @@ public class BungeePacketAnalyzer {
|
||||
|
||||
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());
|
||||
|
||||
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, false);
|
||||
|
||||
final Map<String, CommandsCache> cache = Storage.getLoader().getPerServerCommandsCacheMap();
|
||||
if (!cache.containsKey(serverName)) {
|
||||
cache.put(serverName, new CommandsCache());
|
||||
@@ -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;
|
||||
@@ -28,10 +27,12 @@ import de.rayzs.pat.utils.Reflection;
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import de.rayzs.pat.utils.group.Group;
|
||||
import de.rayzs.pat.utils.group.GroupManager;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
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;
|
||||
@@ -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;
|
||||
@@ -262,7 +310,7 @@ public class VelocityPacketAnalyzer {
|
||||
if (request.getCommand() != null) {
|
||||
|
||||
if (Storage.ConfigSections.Settings.PATCH_EXPLOITS.isMalicious(request.getCommand())) {
|
||||
MessageTranslator.send(VelocityLoader.getServer().getConsoleCommandSource(), Storage.ConfigSections.Settings.PATCH_EXPLOITS.ALERT_MESSAGE.get().replace("%player%", player.getUsername()));
|
||||
MessageHelper.sendMessage(CommandSender.from(VelocityLoader.getServer().getConsoleCommandSource()), Storage.ConfigSections.Settings.PATCH_EXPLOITS.ALERT_MESSAGE.get().replace("%player%", player.getUsername()));
|
||||
player.disconnect(LegacyComponentSerializer.legacyAmpersand().deserialize(Storage.ConfigSections.Settings.PATCH_EXPLOITS.KICK_MESSAGE.get()));
|
||||
} else {
|
||||
insertPlayerInput(player, request.getCommand());
|
||||
@@ -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) {
|
||||
|
||||
@@ -186,10 +186,6 @@ public class Communicator {
|
||||
|
||||
// BACKEND -> PROXY
|
||||
public void handleB2PPacket(String serverName, CommunicationPackets.PATPacket incomingPacket) {
|
||||
if (!incomingPacket.tokenMatches(Storage.TOKEN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (incomingPacket instanceof CommunicationPackets.Backend2Proxy.KeepAlivePacket packet) {
|
||||
final Client client = clients.get(serverName);
|
||||
if (client == null) return;
|
||||
@@ -253,10 +249,6 @@ public class Communicator {
|
||||
|
||||
// PROXY -> BACKEND
|
||||
public void handleP2BPacket(CommunicationPackets.PATPacket incomingPacket) {
|
||||
if (!incomingPacket.tokenMatches(Storage.TOKEN)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (incomingPacket instanceof CommunicationPackets.Proxy2Backend.KeepAliveResponsePacket packet) {
|
||||
|
||||
lastReceivedKeepAliveResponse = System.currentTimeMillis();
|
||||
|
||||
+6
-4
@@ -6,7 +6,8 @@ import de.rayzs.pat.plugin.system.communication.cph.CommunicationPacketHandler;
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.utils.CommunicationPackets;
|
||||
import de.rayzs.pat.utils.Reflection;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.scheduler.PATScheduler;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -59,12 +60,13 @@ public class BukkitCommunicationHandler implements CommunicationPacketHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<String> notificationMessage = MessageTranslator.replaceMessageList(
|
||||
Storage.ConfigSections.Messages.NOTIFICATION.ALERT,
|
||||
final String notificationMessage = StringUtils.replace(
|
||||
Storage.ConfigSections.Messages.NOTIFICATION.ALERT.getLines(),
|
||||
"%player%", player.getName(),
|
||||
"%command%", packet.command(),
|
||||
"%server%", Storage.SERVER_NAME,
|
||||
"%world%", player.getWorld().getName());
|
||||
"%world%", player.getWorld().getName()
|
||||
);
|
||||
|
||||
Logger.info(notificationMessage);
|
||||
}
|
||||
|
||||
+6
-1
@@ -80,7 +80,12 @@ public class BungeePluginMessageClient implements PluginMessageClient, Listener
|
||||
return;
|
||||
}
|
||||
|
||||
final Server server = (Server) event.getSender();
|
||||
// Private channel: never forward matching traffic between a player and backend.
|
||||
event.setCancelled(true);
|
||||
|
||||
if (!(event.getSender() instanceof Server server)) {
|
||||
return;
|
||||
}
|
||||
final String serverName = server.getInfo().getName();
|
||||
final UUID clientId = Communicator.get().getClientId(serverName);
|
||||
|
||||
|
||||
+8
-2
@@ -76,11 +76,17 @@ public class VelocityPluginMessageClient implements PluginMessageClient {
|
||||
|
||||
@Subscribe
|
||||
public void onQueryReceive(PluginMessageEvent event) {
|
||||
if (event.getIdentifier() != IDENTIFIER) {
|
||||
if (!IDENTIFIER.equals(event.getIdentifier())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ServerConnection server = (ServerConnection) event.getSource();
|
||||
// This is a private proxy/backend channel. Mark it handled before inspecting
|
||||
// the source so player-originated messages are never forwarded downstream.
|
||||
event.setResult(PluginMessageEvent.ForwardResult.handled());
|
||||
|
||||
if (!(event.getSource() instanceof ServerConnection server)) {
|
||||
return;
|
||||
}
|
||||
final String serverName = server.getServerInfo().getName();
|
||||
final UUID clientId = Communicator.get().getClientId(serverName);
|
||||
|
||||
|
||||
@@ -2,12 +2,15 @@ package de.rayzs.pat.plugin.system.serverbrand.impl;
|
||||
|
||||
import de.rayzs.pat.plugin.packetanalyzer.bukkit.BukkitPacketAnalyzer;
|
||||
import de.rayzs.pat.plugin.system.serverbrand.ServerBrand;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.api.storage.Storage;
|
||||
import de.rayzs.pat.plugin.BukkitLoader;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import de.rayzs.pat.utils.scheduler.PATScheduler;
|
||||
import de.rayzs.pat.utils.scheduler.PATSchedulerTask;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
import io.netty.channel.Channel;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import de.rayzs.pat.utils.*;
|
||||
@@ -137,7 +140,7 @@ public class BukkitServerBrand implements ServerBrand {
|
||||
|
||||
if (!Reflection.isWeird()) {
|
||||
final PacketUtils.BrandManipulate serverBrand = new PacketUtils.BrandManipulate(
|
||||
MessageTranslator.replaceMessage(player, customBrand)
|
||||
PlaceholderReplacer.applyPlaceholders(CommandSender.from(player), customBrand)
|
||||
);
|
||||
|
||||
player.sendPluginMessage(
|
||||
@@ -158,7 +161,7 @@ public class BukkitServerBrand implements ServerBrand {
|
||||
|
||||
final Object brandPayloadObj = brandPayloadClass
|
||||
.getDeclaredConstructor(String.class)
|
||||
.newInstance(MessageTranslator.replaceMessage(player, customBrand));
|
||||
.newInstance(PlaceholderReplacer.applyPlaceholders(CommandSender.from(player), customBrand));
|
||||
|
||||
final Object customPacketPayloadPacket = clientBoundCustomPacketPayloadPacketClass
|
||||
.getDeclaredConstructor(customPacketPayloadPacketClass)
|
||||
|
||||
@@ -2,7 +2,8 @@ package de.rayzs.pat.plugin.system.serverbrand.impl;
|
||||
|
||||
import de.rayzs.pat.plugin.system.serverbrand.ServerBrand;
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import net.md_5.bungee.api.scheduler.ScheduledTask;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
import net.md_5.bungee.api.connection.*;
|
||||
@@ -29,7 +30,7 @@ public class BungeeServerBrand implements ServerBrand {
|
||||
}
|
||||
|
||||
if (Storage.ConfigSections.Settings.CUSTOM_BRAND.REPEAT_DELAY == -1) {
|
||||
BRAND = MessageTranslator.replaceMessage(
|
||||
BRAND = PlaceholderReplacer.applyPlaceholders(null,
|
||||
Storage.ConfigSections.Settings.CUSTOM_BRAND.BRANDS.getLines().get(0)
|
||||
) + "§r";
|
||||
|
||||
@@ -46,7 +47,7 @@ public class BungeeServerBrand implements ServerBrand {
|
||||
public void run() {
|
||||
animationPos = (++animationPos) % length;
|
||||
|
||||
BRAND = MessageTranslator.replaceMessage(
|
||||
BRAND = PlaceholderReplacer.applyPlaceholders(null,
|
||||
Storage.ConfigSections.Settings.CUSTOM_BRAND.BRANDS.getLines().get(animationPos)
|
||||
) + "§r";
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@ package de.rayzs.pat.plugin.system.serverbrand.impl;
|
||||
|
||||
import com.velocitypowered.api.scheduler.ScheduledTask;
|
||||
import de.rayzs.pat.plugin.system.serverbrand.ServerBrand;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
import de.rayzs.pat.plugin.VelocityLoader;
|
||||
import de.rayzs.pat.api.storage.Storage;
|
||||
@@ -49,7 +50,7 @@ public class VelocityServerBrand implements ServerBrand {
|
||||
}
|
||||
|
||||
if (Storage.ConfigSections.Settings.CUSTOM_BRAND.REPEAT_DELAY == -1) {
|
||||
BRAND = MessageTranslator.replaceMessage(Storage.ConfigSections.Settings.CUSTOM_BRAND.BRANDS.getLines().get(0)) + "§r";
|
||||
BRAND = PlaceholderReplacer.applyPlaceholders(null, Storage.ConfigSections.Settings.CUSTOM_BRAND.BRANDS.getLines().get(0)) + "§r";
|
||||
SERVER.getAllPlayers().forEach(this::send);
|
||||
} else {
|
||||
TASK = SERVER.getScheduler().buildTask(VelocityLoader.getInstance(), new Runnable() {
|
||||
@@ -61,7 +62,7 @@ public class VelocityServerBrand implements ServerBrand {
|
||||
public void run() {
|
||||
animationPos = (++animationPos) % length;
|
||||
|
||||
BRAND = MessageTranslator.replaceMessage(
|
||||
BRAND = PlaceholderReplacer.applyPlaceholders(null,
|
||||
Storage.ConfigSections.Settings.CUSTOM_BRAND.BRANDS.getLines().get(animationPos)
|
||||
) + "§r";
|
||||
|
||||
|
||||
+2
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -116,7 +116,7 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,50 +1,93 @@
|
||||
package de.rayzs.pat.utils;
|
||||
|
||||
import de.rayzs.pat.plugin.system.communication.Communicator;
|
||||
import de.rayzs.pat.api.storage.Storage;
|
||||
import de.rayzs.pat.plugin.system.communication.Communicator;
|
||||
import de.rayzs.pat.utils.configuration.helper.MultipleMessagesHelper;
|
||||
|
||||
import java.util.*;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Wire codec for communication between proxy and backend servers.
|
||||
*
|
||||
* <p>Packets are explicitly encoded and protected with AES-256-GCM before
|
||||
* transmission. Encryption keys are derived from {@link Storage#TOKEN},
|
||||
* using backend UUIDs only as derivation context.
|
||||
*
|
||||
* <p>The codec does not use native Java deserialization for network data,
|
||||
* and all variable-length fields are bounded before allocation.
|
||||
*/
|
||||
public class CommunicationPackets {
|
||||
|
||||
|
||||
public static final byte PROTOCOL_VERSION = 1;
|
||||
private static final byte INIT_PACKET = 0;
|
||||
private static final byte NOT_INIT_PACKET = 1;
|
||||
|
||||
private static final int HEADER_LENGTH = 2;
|
||||
private static final int NONCE_LENGTH = 12;
|
||||
private static final int GCM_TAG_BITS = 128;
|
||||
private static final int GCM_TAG_LENGTH = GCM_TAG_BITS / 8;
|
||||
// Velocity defaults to 32,767 bytes for plugin message payloads.
|
||||
private static final int MAX_WIRE_BYTES = 32_767;
|
||||
private static final int MAX_PLAINTEXT_BYTES = MAX_WIRE_BYTES - HEADER_LENGTH - NONCE_LENGTH - GCM_TAG_LENGTH;
|
||||
private static final SecureRandom RANDOM = new SecureRandom();
|
||||
private static final byte[] HKDF_SALT = "ProAntiTab/plugin-messaging/v1".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
// Stable packet IDs. Do not reorder/reuse IDs without a protocol-version bump.
|
||||
private static final byte P_UPDATE = 1;
|
||||
private static final byte P_IDENTITY = 2;
|
||||
private static final byte P_NOTIFICATION = 3;
|
||||
private static final byte P_EXEC_CONSOLE = 4;
|
||||
private static final byte P_EXEC_PLAYER = 5;
|
||||
private static final byte P_CONSOLE_MESSAGE = 6;
|
||||
private static final byte P_KEEPALIVE_RESPONSE = 7;
|
||||
private static final byte P_DATA_SYNC = 8;
|
||||
private static final byte P_IDENTITY_REQUEST = 20;
|
||||
private static final byte P_IDENTITY_RESPONSE = 21;
|
||||
private static final byte P_DATA_SYNC_RECEIVED = 22;
|
||||
private static final byte P_KEEPALIVE = 23;
|
||||
private static final byte P_PLAYER_PERMISSION_CHANGE = 24;
|
||||
private static final byte P_GROUP_PERMISSION_CHANGE = 25;
|
||||
|
||||
public static byte[] preparePacket(Object object) {
|
||||
return preparePacket(object, Communicator.get().getId());
|
||||
}
|
||||
|
||||
public static byte[] preparePacket(Object object, UUID id) {
|
||||
if (!isValidPacket(object)) {
|
||||
if (!isValidPacket(object) || Storage.TOKEN == null || Storage.TOKEN.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final boolean isInitialPacket = isInitialPacket(object);
|
||||
final ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
|
||||
try {
|
||||
final boolean initial = isInitialPacket(object);
|
||||
if (!initial && id == null) {
|
||||
return null;
|
||||
}
|
||||
final byte[] plaintext = encodePacket((PATPacket) object);
|
||||
final byte[] nonce = new byte[NONCE_LENGTH];
|
||||
RANDOM.nextBytes(nonce);
|
||||
|
||||
try (ObjectOutputStream outputStream = new ObjectOutputStream(arrayOutputStream)) {
|
||||
outputStream.writeObject(object);
|
||||
outputStream.flush();
|
||||
// Wire format: [version:1][init:1][nonce:12][ciphertext + GCM tag:16].
|
||||
// The version and init flag are authenticated as GCM additional authenticated data.
|
||||
final byte[] header = new byte[]{PROTOCOL_VERSION, initial ? INIT_PACKET : NOT_INIT_PACKET};
|
||||
final SecretKeySpec key = deriveKey(Storage.TOKEN, initial ? null : id);
|
||||
final byte[] ciphertext = encrypt(plaintext, key, nonce, header);
|
||||
|
||||
final byte[] encryptedBytes = xor(arrayOutputStream.toByteArray(), isInitialPacket
|
||||
? Storage.TOKEN
|
||||
: id.toString()
|
||||
);
|
||||
|
||||
final byte[] bytes = new byte[encryptedBytes.length + 1];
|
||||
|
||||
bytes[0] = isInitialPacket ? INIT_PACKET : NOT_INIT_PACKET;
|
||||
System.arraycopy(encryptedBytes, 0, bytes, 1, bytes.length - 1);
|
||||
|
||||
return bytes;
|
||||
|
||||
} catch (Exception ignored) { }
|
||||
|
||||
return null;
|
||||
final byte[] result = new byte[header.length + NONCE_LENGTH + ciphertext.length];
|
||||
System.arraycopy(header, 0, result, 0, header.length);
|
||||
System.arraycopy(nonce, 0, result, header.length, NONCE_LENGTH);
|
||||
System.arraycopy(ciphertext, 0, result, header.length + NONCE_LENGTH, ciphertext.length);
|
||||
return result;
|
||||
} catch (IOException | GeneralSecurityException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static Object readPacket(byte[] bytes) {
|
||||
@@ -52,147 +95,265 @@ public class CommunicationPackets {
|
||||
}
|
||||
|
||||
public static Object readPacket(byte[] bytes, UUID id) {
|
||||
if (bytes.length == 0) {
|
||||
if (bytes == null || bytes.length < HEADER_LENGTH + NONCE_LENGTH + GCM_TAG_LENGTH
|
||||
|| bytes.length > MAX_WIRE_BYTES || Storage.TOKEN == null || Storage.TOKEN.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final byte init = bytes[0];
|
||||
bytes = Arrays.copyOfRange(bytes, 1, bytes.length);
|
||||
|
||||
bytes = xor(bytes, isInitialPacket(init)
|
||||
? Storage.TOKEN
|
||||
: id.toString()
|
||||
);
|
||||
|
||||
final ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(bytes);
|
||||
|
||||
try (ObjectInput input = new ObjectInputStream(arrayInputStream)) {
|
||||
final Object object = input.readObject();
|
||||
|
||||
if (object.getClass() == null || !isValidPacket(object)) {
|
||||
try {
|
||||
final byte version = bytes[0];
|
||||
final byte initFlag = bytes[1];
|
||||
if (version != PROTOCOL_VERSION || (initFlag != INIT_PACKET && initFlag != NOT_INIT_PACKET)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return object;
|
||||
} catch (Exception ignored) { }
|
||||
final boolean initial = initFlag == INIT_PACKET;
|
||||
if (!initial && id == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
final byte[] header = Arrays.copyOfRange(bytes, 0, 2);
|
||||
final byte[] nonce = Arrays.copyOfRange(bytes, 2, 2 + NONCE_LENGTH);
|
||||
final byte[] ciphertext = Arrays.copyOfRange(bytes, 2 + NONCE_LENGTH, bytes.length);
|
||||
|
||||
final SecretKeySpec key = deriveKey(Storage.TOKEN, initial ? null : id);
|
||||
// Authentication is verified by GCM before decodePacket() sees any plaintext.
|
||||
final byte[] plaintext = decrypt(ciphertext, key, nonce, header);
|
||||
return decodePacket(plaintext, initial);
|
||||
} catch (IOException | GeneralSecurityException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Yes, I am aware that xor is not the best encryption out there,
|
||||
// but it will suffice for now since the encryption shouldn't be too heavy.
|
||||
private static byte[] xor(byte[] bytes, String key) {
|
||||
final byte[] output = new byte[bytes.length];
|
||||
final byte[] secret = key.getBytes();
|
||||
private static SecretKeySpec deriveKey(String token, UUID id) throws GeneralSecurityException {
|
||||
// RFC 5869 HKDF-SHA-256. The token is the input keying material; the UUID is
|
||||
// public context used to separate normal-session keys between backend identities.
|
||||
final Mac mac = Mac.getInstance("HmacSHA256");
|
||||
|
||||
int pos = 0;
|
||||
// HKDF-Extract(salt, IKM)
|
||||
mac.init(new SecretKeySpec(HKDF_SALT, "HmacSHA256"));
|
||||
final byte[] prk = mac.doFinal(token.getBytes(StandardCharsets.UTF_8));
|
||||
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
output[i] = (byte) (bytes[i] ^ secret[pos]);
|
||||
pos += 1;
|
||||
// HKDF-Expand(PRK, info, 32). One HMAC block is sufficient for an AES-256 key.
|
||||
final String context = id == null ? "initial" : "backend:" + id;
|
||||
final byte[] info = context.getBytes(StandardCharsets.UTF_8);
|
||||
mac.init(new SecretKeySpec(prk, "HmacSHA256"));
|
||||
mac.update(info);
|
||||
mac.update((byte) 0x01);
|
||||
final byte[] okm = mac.doFinal();
|
||||
return new SecretKeySpec(okm, "AES");
|
||||
}
|
||||
|
||||
if (pos >= secret.length) {
|
||||
pos = 0;
|
||||
private static byte[] encrypt(byte[] plaintext, SecretKeySpec key, byte[] nonce, byte[] aad) throws GeneralSecurityException {
|
||||
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(GCM_TAG_BITS, nonce));
|
||||
cipher.updateAAD(aad);
|
||||
return cipher.doFinal(plaintext);
|
||||
}
|
||||
|
||||
private static byte[] decrypt(byte[] ciphertext, SecretKeySpec key, byte[] nonce, byte[] aad) throws GeneralSecurityException {
|
||||
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(GCM_TAG_BITS, nonce));
|
||||
cipher.updateAAD(aad);
|
||||
return cipher.doFinal(ciphertext);
|
||||
}
|
||||
|
||||
private static byte[] encodePacket(PATPacket packet) throws IOException {
|
||||
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
try (DataOutputStream out = new DataOutputStream(new BoundedOutputStream(buffer, MAX_PLAINTEXT_BYTES))) {
|
||||
if (packet instanceof Proxy2Backend.UpdatePacket p) {
|
||||
out.writeByte(P_UPDATE); writeNullableUuid(out, p.playerId());
|
||||
} else if (packet instanceof Proxy2Backend.IdentityPacket p) {
|
||||
out.writeByte(P_IDENTITY); writeUuid(out, p.targetServerId()); writeString(out, p.serverName());
|
||||
} else if (packet instanceof Proxy2Backend.NotificationPacket p) {
|
||||
out.writeByte(P_NOTIFICATION); writeUuid(out, p.playerId()); writeString(out, p.command());
|
||||
} else if (packet instanceof Proxy2Backend.ExecuteConsoleCommandPacket p) {
|
||||
out.writeByte(P_EXEC_CONSOLE); writeString(out, p.command());
|
||||
} else if (packet instanceof Proxy2Backend.ExecutePlayerCommandPacket p) {
|
||||
out.writeByte(P_EXEC_PLAYER); writeUuid(out, p.playerId()); writeString(out, p.command());
|
||||
} else if (packet instanceof Proxy2Backend.ConsoleMessagePacket p) {
|
||||
out.writeByte(P_CONSOLE_MESSAGE); writeString(out, p.message());
|
||||
} else if (packet instanceof Proxy2Backend.KeepAliveResponsePacket) {
|
||||
out.writeByte(P_KEEPALIVE_RESPONSE);
|
||||
} else if (packet instanceof Proxy2Backend.DataSyncPacket p) {
|
||||
out.writeByte(P_DATA_SYNC);
|
||||
writeString(out, p.messages().prefix());
|
||||
out.writeBoolean(p.autoLowerCase().enabled());
|
||||
out.writeBoolean(p.unknownCommand().enabled());
|
||||
final List<String> lines = p.unknownCommand().message().getLines();
|
||||
out.writeInt(lines.size());
|
||||
for (String line : lines) writeString(out, line);
|
||||
} else if (packet instanceof Backend2Proxy.IdentityRequestPacket p) {
|
||||
out.writeByte(P_IDENTITY_REQUEST); writeUuid(out, p.serverId());
|
||||
} else if (packet instanceof Backend2Proxy.IdentityResponsePacket p) {
|
||||
out.writeByte(P_IDENTITY_RESPONSE); writeUuid(out, p.serverId());
|
||||
} else if (packet instanceof Backend2Proxy.DataSyncReceivedPacket) {
|
||||
out.writeByte(P_DATA_SYNC_RECEIVED);
|
||||
} else if (packet instanceof Backend2Proxy.KeepAlivePacket) {
|
||||
out.writeByte(P_KEEPALIVE);
|
||||
} else if (packet instanceof Backend2Proxy.AnnouncePlayerPermissionChanges p) {
|
||||
out.writeByte(P_PLAYER_PERMISSION_CHANGE); writeUuid(out, p.playerId());
|
||||
} else if (packet instanceof Backend2Proxy.AnnounceGroupPermissionChanges p) {
|
||||
out.writeByte(P_GROUP_PERMISSION_CHANGE);
|
||||
out.writeInt(p.playerIds().size());
|
||||
for (UUID uuid : p.playerIds()) writeUuid(out, uuid);
|
||||
} else {
|
||||
throw new IOException("Unknown packet type");
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
if (buffer.size() > MAX_PLAINTEXT_BYTES) throw new IOException("Packet too large");
|
||||
return buffer.toByteArray();
|
||||
}
|
||||
|
||||
public static boolean isValidPacket(Object object) {
|
||||
return object instanceof PATPacket;
|
||||
}
|
||||
private static PATPacket decodePacket(byte[] bytes, boolean initial) throws IOException {
|
||||
if (bytes.length == 0 || bytes.length > MAX_PLAINTEXT_BYTES) throw new IOException("Invalid packet length");
|
||||
try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes))) {
|
||||
final int type = in.readUnsignedByte();
|
||||
final PATPacket packet = switch (type) {
|
||||
case P_UPDATE -> new Proxy2Backend.UpdatePacket(readNullableUuid(in));
|
||||
case P_IDENTITY -> new Proxy2Backend.IdentityPacket(readUuid(in), readString(in));
|
||||
case P_NOTIFICATION -> new Proxy2Backend.NotificationPacket(readUuid(in), readString(in));
|
||||
case P_EXEC_CONSOLE -> new Proxy2Backend.ExecuteConsoleCommandPacket(readString(in));
|
||||
case P_EXEC_PLAYER -> new Proxy2Backend.ExecutePlayerCommandPacket(readUuid(in), readString(in));
|
||||
case P_CONSOLE_MESSAGE -> new Proxy2Backend.ConsoleMessagePacket(readString(in));
|
||||
case P_KEEPALIVE_RESPONSE -> new Proxy2Backend.KeepAliveResponsePacket();
|
||||
case P_DATA_SYNC -> {
|
||||
final Proxy2Backend.DataSyncPacket.Messages messages =
|
||||
new Proxy2Backend.DataSyncPacket.Messages(readString(in));
|
||||
final Proxy2Backend.DataSyncPacket.AutoLowerCase autoLowerCase =
|
||||
new Proxy2Backend.DataSyncPacket.AutoLowerCase(in.readBoolean());
|
||||
final boolean unknownEnabled = in.readBoolean();
|
||||
final int count = readCount(in, Integer.BYTES);
|
||||
final List<String> lines = new ArrayList<>(count);
|
||||
for (int i = 0; i < count; i++) lines.add(readString(in));
|
||||
final Proxy2Backend.DataSyncPacket.UnknownCommand unknown =
|
||||
new Proxy2Backend.DataSyncPacket.UnknownCommand(
|
||||
unknownEnabled, new MultipleMessagesHelper(lines));
|
||||
yield new Proxy2Backend.DataSyncPacket(messages, autoLowerCase, unknown);
|
||||
}
|
||||
case P_IDENTITY_REQUEST -> new Backend2Proxy.IdentityRequestPacket(readUuid(in));
|
||||
case P_IDENTITY_RESPONSE -> new Backend2Proxy.IdentityResponsePacket(readUuid(in));
|
||||
case P_DATA_SYNC_RECEIVED -> new Backend2Proxy.DataSyncReceivedPacket();
|
||||
case P_KEEPALIVE -> new Backend2Proxy.KeepAlivePacket();
|
||||
case P_PLAYER_PERMISSION_CHANGE -> new Backend2Proxy.AnnouncePlayerPermissionChanges(readUuid(in));
|
||||
case P_GROUP_PERMISSION_CHANGE -> {
|
||||
final int count = readCount(in, 2 * Long.BYTES);
|
||||
final Set<UUID> ids = new HashSet<>(Math.max(16, count));
|
||||
for (int i = 0; i < count; i++) ids.add(readUuid(in));
|
||||
yield new Backend2Proxy.AnnounceGroupPermissionChanges(ids);
|
||||
}
|
||||
default -> throw new IOException("Unknown packet type: " + type);
|
||||
};
|
||||
|
||||
public static boolean isP2BPacket(Object object) {
|
||||
return object instanceof P2BPacket;
|
||||
}
|
||||
|
||||
public static boolean isB2PPacket(Object object) {
|
||||
return object instanceof B2PPacket;
|
||||
}
|
||||
|
||||
public static boolean isInitialPacket(Object object) {
|
||||
return object instanceof InitialPacket;
|
||||
}
|
||||
|
||||
public static boolean isInitialPacket(byte[] bytes) {
|
||||
return bytes.length > 0 && isInitialPacket(bytes[0]);
|
||||
}
|
||||
|
||||
public static boolean isInitialPacket(byte b) {
|
||||
return b == INIT_PACKET;
|
||||
}
|
||||
|
||||
public interface PATPacket extends Serializable {
|
||||
String token = Storage.TOKEN;
|
||||
|
||||
default boolean tokenMatches(String token) {
|
||||
return PATPacket.token.equals(token);
|
||||
if (in.available() != 0) throw new IOException("Trailing packet data");
|
||||
if (initial != isInitialPacket(packet)) throw new IOException("Packet/header type mismatch");
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
|
||||
// Reject oversized plaintext as it is written, rather than after allocating it.
|
||||
private static final class BoundedOutputStream extends FilterOutputStream {
|
||||
private final int limit;
|
||||
private int written;
|
||||
|
||||
private interface InitialPacket extends PATPacket {}
|
||||
private interface Synchronizable extends Serializable {}
|
||||
private BoundedOutputStream(OutputStream out, int limit) {
|
||||
super(out);
|
||||
this.limit = limit;
|
||||
}
|
||||
|
||||
private interface P2BPacket extends PATPacket {}
|
||||
private interface B2PPacket extends PATPacket {}
|
||||
@Override
|
||||
public void write(int value) throws IOException {
|
||||
if (written >= limit) throw new IOException("Packet too large");
|
||||
out.write(value);
|
||||
written++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] bytes, int offset, int length) throws IOException {
|
||||
if (length > limit - written) throw new IOException("Packet too large");
|
||||
out.write(bytes, offset, length);
|
||||
written += length;
|
||||
}
|
||||
}
|
||||
|
||||
private static void writeString(DataOutputStream out, String value) throws IOException {
|
||||
if (value == null) throw new IOException("Null string");
|
||||
final byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
|
||||
out.writeInt(bytes.length);
|
||||
out.write(bytes);
|
||||
}
|
||||
|
||||
private static String readString(DataInputStream in) throws IOException {
|
||||
final int length = in.readInt();
|
||||
if (length < 0 || length > in.available()) {
|
||||
throw new IOException("Invalid string length");
|
||||
}
|
||||
return new String(in.readNBytes(length), StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
private static int readCount(DataInputStream in, int minimumEntryBytes) throws IOException {
|
||||
final int count = in.readInt();
|
||||
if (count < 0 || count > in.available() / minimumEntryBytes) {
|
||||
throw new IOException("Invalid collection size");
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private static void writeUuid(DataOutputStream out, UUID uuid) throws IOException {
|
||||
if (uuid == null) throw new IOException("Null UUID");
|
||||
out.writeLong(uuid.getMostSignificantBits());
|
||||
out.writeLong(uuid.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
private static UUID readUuid(DataInputStream in) throws IOException {
|
||||
return new UUID(in.readLong(), in.readLong());
|
||||
}
|
||||
|
||||
private static void writeNullableUuid(DataOutputStream out, UUID uuid) throws IOException {
|
||||
out.writeBoolean(uuid != null);
|
||||
if (uuid != null) writeUuid(out, uuid);
|
||||
}
|
||||
|
||||
private static UUID readNullableUuid(DataInputStream in) throws IOException {
|
||||
return in.readBoolean() ? readUuid(in) : null;
|
||||
}
|
||||
|
||||
public static boolean isValidPacket(Object object) { return object instanceof PATPacket; }
|
||||
public static boolean isP2BPacket(Object object) { return object instanceof P2BPacket; }
|
||||
public static boolean isB2PPacket(Object object) { return object instanceof B2PPacket; }
|
||||
public static boolean isInitialPacket(Object object) { return object instanceof InitialPacket; }
|
||||
// Routing hint only; the flag is authenticated by readPacket().
|
||||
public static boolean isInitialPacket(byte[] bytes) { return bytes != null && bytes.length > 1 && bytes[0] == PROTOCOL_VERSION && bytes[1] == INIT_PACKET; }
|
||||
|
||||
public interface PATPacket { }
|
||||
private interface InitialPacket extends PATPacket { }
|
||||
private interface Synchronizable { }
|
||||
private interface P2BPacket extends PATPacket { }
|
||||
private interface B2PPacket extends PATPacket { }
|
||||
|
||||
public static class Proxy2Backend {
|
||||
|
||||
private Proxy2Backend() { }
|
||||
|
||||
public record UpdatePacket(UUID playerId) implements P2BPacket {
|
||||
public boolean forEveryone() { return playerId == null; }
|
||||
}
|
||||
|
||||
public record UpdatePacket(UUID playerId) implements P2BPacket { public boolean forEveryone() { return playerId == null; } }
|
||||
public record IdentityPacket(UUID targetServerId, String serverName) implements InitialPacket, P2BPacket { }
|
||||
|
||||
public record NotificationPacket(UUID playerId, String command) implements P2BPacket { }
|
||||
|
||||
public record ExecuteConsoleCommandPacket(String command) implements P2BPacket { }
|
||||
|
||||
public record ExecutePlayerCommandPacket(UUID playerId, String command) implements P2BPacket { }
|
||||
|
||||
public record ConsoleMessagePacket(String message) implements P2BPacket { }
|
||||
|
||||
public record KeepAliveResponsePacket() implements P2BPacket { }
|
||||
|
||||
public record DataSyncPacket(
|
||||
Messages messages,
|
||||
AutoLowerCase autoLowerCase,
|
||||
UnknownCommand unknownCommand
|
||||
) implements P2BPacket {
|
||||
|
||||
public record Messages(String prefix)
|
||||
implements Synchronizable {}
|
||||
|
||||
public record AutoLowerCase(boolean enabled)
|
||||
implements Synchronizable {}
|
||||
|
||||
public record UnknownCommand(boolean enabled, MultipleMessagesHelper message)
|
||||
implements Synchronizable {}
|
||||
|
||||
public record DataSyncPacket(Messages messages, AutoLowerCase autoLowerCase, UnknownCommand unknownCommand) implements P2BPacket {
|
||||
public record Messages(String prefix) implements Synchronizable { }
|
||||
public record AutoLowerCase(boolean enabled) implements Synchronizable { }
|
||||
public record UnknownCommand(boolean enabled, MultipleMessagesHelper message) implements Synchronizable { }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class Backend2Proxy {
|
||||
|
||||
private Backend2Proxy() { }
|
||||
|
||||
public record IdentityRequestPacket(UUID serverId) implements InitialPacket, B2PPacket { }
|
||||
|
||||
public record IdentityResponsePacket(UUID serverId) implements InitialPacket, B2PPacket { }
|
||||
|
||||
public record DataSyncReceivedPacket() implements B2PPacket { }
|
||||
|
||||
public record KeepAlivePacket() implements B2PPacket { }
|
||||
|
||||
public record AnnouncePlayerPermissionChanges(UUID playerId) implements B2PPacket { }
|
||||
|
||||
public record AnnounceGroupPermissionChanges(Set<UUID> playerIds) implements B2PPacket { }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -66,10 +66,14 @@ public class Reflection {
|
||||
return software == Software.FOLIA;
|
||||
}
|
||||
|
||||
public static boolean isCraftbukkit() {
|
||||
public static boolean isBukkit() {
|
||||
return software == Software.BUKKIT;
|
||||
}
|
||||
|
||||
public static boolean isSpigot() {
|
||||
return software == Software.SPIGOT;
|
||||
}
|
||||
|
||||
public static boolean isArclight() {
|
||||
return software == Software.ARCLIGHT;
|
||||
}
|
||||
@@ -77,6 +81,11 @@ public class Reflection {
|
||||
public static boolean isProxyServer() {
|
||||
return software.isProxySoftware();
|
||||
}
|
||||
|
||||
public static boolean isBungeeServer() {
|
||||
return software == Software.BUNGEECORD;
|
||||
}
|
||||
|
||||
public static boolean isVelocityServer() {
|
||||
return software == Software.VELOCITY;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
package de.rayzs.pat.utils;
|
||||
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.*;
|
||||
|
||||
public class StringUtils {
|
||||
@@ -26,7 +24,7 @@ public class StringUtils {
|
||||
String line = lines.get(i);
|
||||
|
||||
if (line.startsWith(centerVariable)) {
|
||||
line = MessageTranslator.colorless(line.substring(centerVariable.length()));
|
||||
line = MessageHelper.strip(line.substring(centerVariable.length()));
|
||||
|
||||
int size = line.length();
|
||||
sizes.put(i, size);
|
||||
@@ -51,31 +49,6 @@ public class StringUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String hashString(final String string, final String algorithm) {
|
||||
try {
|
||||
final MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
|
||||
final byte[] hash = messageDigest.digest(string.getBytes(StandardCharsets.UTF_8));
|
||||
final StringBuilder hexString = new StringBuilder(2 * hash.length);
|
||||
|
||||
for (final byte b : hash) {
|
||||
final String hex = Integer.toHexString(0xff & b);
|
||||
|
||||
if (hex.length() == 1) {
|
||||
hexString.append('0');
|
||||
}
|
||||
|
||||
hexString.append(hex);
|
||||
}
|
||||
|
||||
return hexString.toString();
|
||||
|
||||
} catch (Exception exception) {
|
||||
exception.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String replaceFirst(String input, String trigger, String replacement) {
|
||||
|
||||
if (!input.contains(trigger)) {
|
||||
@@ -151,28 +124,33 @@ public class StringUtils {
|
||||
return input;
|
||||
}
|
||||
|
||||
public static String replace(List<String> input, String... replacements) {
|
||||
return replace(String.join("\n", input), replacements);
|
||||
}
|
||||
|
||||
public static String replace(String input, String... replacements) {
|
||||
final HashMap<String, String> REPLACEMENTS = new HashMap<>();
|
||||
if (replacements.length == 0) {
|
||||
return input;
|
||||
}
|
||||
|
||||
if (replacements.length > 0) {
|
||||
String firstReplacementInput = null, secondReplacementInput = null;
|
||||
|
||||
for (String replacement : replacements) {
|
||||
if (firstReplacementInput == null) firstReplacementInput = replacement;
|
||||
else secondReplacementInput = replacement;
|
||||
final HashMap<String, String> cache = new HashMap<>();
|
||||
String firstReplacementInput = null, secondReplacementInput = null;
|
||||
|
||||
if (firstReplacementInput != null && secondReplacementInput != null) {
|
||||
REPLACEMENTS.put(firstReplacementInput, secondReplacementInput);
|
||||
firstReplacementInput = null;
|
||||
secondReplacementInput = null;
|
||||
}
|
||||
for (String replacement : replacements) {
|
||||
if (firstReplacementInput == null) firstReplacementInput = replacement;
|
||||
else secondReplacementInput = replacement;
|
||||
|
||||
if (firstReplacementInput != null && secondReplacementInput != null) {
|
||||
cache.put(firstReplacementInput, secondReplacementInput);
|
||||
firstReplacementInput = null;
|
||||
secondReplacementInput = null;
|
||||
}
|
||||
}
|
||||
|
||||
String text = input;
|
||||
if (replacements.length > 0)
|
||||
for (Map.Entry<String, String> entry : REPLACEMENTS.entrySet())
|
||||
text = text.replace(entry.getKey(), entry.getValue());
|
||||
for (Map.Entry<String, String> entry : cache.entrySet())
|
||||
text = text.replace(entry.getKey(), entry.getValue());
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -6,21 +6,26 @@ import java.util.*;
|
||||
|
||||
public class MultipleMessagesHelper implements Serializable {
|
||||
|
||||
private final ArrayList<String> lines;
|
||||
private final List<String> lines;
|
||||
|
||||
/** Construct a message set from authenticated wire data. */
|
||||
public MultipleMessagesHelper(List<String> lines) {
|
||||
this.lines = new ArrayList<>(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;
|
||||
}
|
||||
}
|
||||
@@ -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.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package de.rayzs.pat.utils.message;
|
||||
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.utils.configuration.helper.MultipleMessagesHelper;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import de.rayzs.pat.utils.message.translators.*;
|
||||
import de.rayzs.pat.utils.*;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
|
||||
import java.sql.Ref;
|
||||
import java.util.List;
|
||||
|
||||
public class MessageHelper {
|
||||
|
||||
private static boolean support;
|
||||
private static Translator translator = null;
|
||||
|
||||
public static void initialize() {
|
||||
|
||||
if (Reflection.isBukkit() || Reflection.isSpigot()) {
|
||||
Logger.warning("MiniMessage support disabled! Your server software is too old. Please switch to a more modern paper-based fork such as Paper, Purpur, Leaf..., etc to enable MiniMessage support.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Reflection.isBungeeServer() && !Reflection.doesClassExist("net.kyori.adventure.util.Buildable$Builder")) {
|
||||
Logger.warning("MiniMessage support disabled! Since MiniMessage isn't supported for Bungeecord anymore and this version of Bungeecord is too advanced, MiniMessage support is disabled!");
|
||||
return;
|
||||
}
|
||||
|
||||
support = true;
|
||||
translator = Reflection.isVelocityServer() ? new VelocityMessageTranslator()
|
||||
: Reflection.isProxyServer() ? new BungeeMessageTranslator()
|
||||
: Reflection.isPaper() ? new PaperMessageTranslator()
|
||||
: new BukkitMessageTranslator();
|
||||
}
|
||||
|
||||
public static void sendMessage(CommandSender sender, MultipleMessagesHelper texts, String... replacements) {
|
||||
sendMessage(sender, texts.getLines(), replacements);
|
||||
}
|
||||
|
||||
public static void sendMessage(CommandSender sender, List<String> texts, String... replacements) {
|
||||
sendMessage(sender, StringUtils.getStringList(texts, "\n"), replacements);
|
||||
}
|
||||
|
||||
public static void sendMessage(CommandSender sender, String text, String... replacements) {
|
||||
if (text.isEmpty()) return;
|
||||
|
||||
|
||||
if (!Reflection.isProxyServer()) {
|
||||
text = PlaceholderReplacer.applyPlaceholders(sender, text, replacements);
|
||||
|
||||
if (support) {
|
||||
translator.send(sender, text);
|
||||
return;
|
||||
}
|
||||
|
||||
sender.sendMessage(text);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (support) {
|
||||
PlaceholderReplacer.applyProxyPlaceholders(sender, text, result -> translator.send(sender, result), replacements);
|
||||
return;
|
||||
}
|
||||
|
||||
PlaceholderReplacer.applyProxyPlaceholders(sender, text, sender::sendMessage, replacements);
|
||||
}
|
||||
|
||||
public static void sendActionbar(CommandSender sender, String message) {
|
||||
if (!support) {
|
||||
sender.sendActionbar(message);
|
||||
return;
|
||||
}
|
||||
|
||||
translator.sendActionbar(sender, message);
|
||||
}
|
||||
|
||||
public static void sendTitle(CommandSender sender, String title, String subtitle, int fadeIn, int stay, int fadeOut) {
|
||||
if (!support) {
|
||||
sender.sendTitle(title, subtitle, fadeIn, stay, fadeOut);
|
||||
return;
|
||||
}
|
||||
|
||||
translator.sendTitle(sender, title, subtitle, fadeIn, stay, fadeOut);
|
||||
}
|
||||
|
||||
public static void playSound(CommandSender sender, String soundKey, float volume, float pitch) throws Exception {
|
||||
translator.playSound(sender, soundKey, volume, pitch);
|
||||
}
|
||||
|
||||
public static String strip(String text) {
|
||||
return translator.strip(text);
|
||||
}
|
||||
|
||||
public static void closeAudiences() {
|
||||
if (translator == null) return;
|
||||
translator.close();
|
||||
}
|
||||
|
||||
public static boolean isSupported() {
|
||||
return support;
|
||||
}
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
package de.rayzs.pat.utils.message;
|
||||
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.utils.configuration.helper.MultipleMessagesHelper;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import de.rayzs.pat.utils.message.translators.*;
|
||||
import de.rayzs.pat.api.storage.Storage;
|
||||
import de.rayzs.pat.utils.*;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class MessageTranslator {
|
||||
|
||||
private static final HashMap<Character, String> colors = new HashMap<>(), endingColors = new HashMap<>();
|
||||
private static boolean support;
|
||||
private static Translator translator = null;
|
||||
|
||||
public static void initialize() {
|
||||
colors.put('1', "<dark_blue>");
|
||||
colors.put('2', "<dark_green>");
|
||||
colors.put('3', "<dark_aqua>");
|
||||
colors.put('4', "<dark_red>");
|
||||
colors.put('5', "<dark_purple>");
|
||||
colors.put('6', "<gold>");
|
||||
colors.put('7', "<gray>");
|
||||
colors.put('8', "<dark_gray>");
|
||||
colors.put('9', "<blue>");
|
||||
colors.put('a', "<green>");
|
||||
colors.put('b', "<aqua>");
|
||||
colors.put('c', "<red>");
|
||||
colors.put('d', "<light_purple>");
|
||||
colors.put('e', "<yellow>");
|
||||
colors.put('f', "<white>");
|
||||
colors.put('m', "<st>");
|
||||
colors.put('k', "<obf>");
|
||||
colors.put('r', "<reset>");
|
||||
colors.put('o', "<i>");
|
||||
colors.put('l', "<b>");
|
||||
|
||||
for (Map.Entry<Character, String> entry : colors.entrySet())
|
||||
endingColors.put(entry.getKey(), "</" + entry.getValue().substring(1));
|
||||
|
||||
support = !Reflection.isArclight()
|
||||
&& !Reflection.isCraftbukkit()
|
||||
&& (Reflection.isAtLeast(1, 18) || Reflection.isProxyServer());
|
||||
|
||||
if (Reflection.isAtLeast(26, 2) && !Reflection.getSoftware().isPaperBased()) {
|
||||
support = false;
|
||||
|
||||
Logger.warning("Due to an incompatibility issue, MiniMessage support is not given for non-Paper based server softwares as of now!");
|
||||
}
|
||||
|
||||
if (Reflection.getSoftware() == Reflection.Software.BUNGEECORD && !Reflection.doesClassExist("net.kyori.adventure.util.Buildable$Builder")) {
|
||||
support = false;
|
||||
|
||||
Logger.warning("Since MiniMessage isn't supported for Bungeecord anymore and this version of Bungeecord is too advanced, MiniMessage support is disabled!");
|
||||
}
|
||||
|
||||
if (support) {
|
||||
translator = Reflection.isVelocityServer() ? new VelocityMessageTranslator()
|
||||
: Reflection.isProxyServer() ? new BungeeMessageTranslator()
|
||||
: new BukkitMessageTranslator();
|
||||
}
|
||||
}
|
||||
|
||||
public static String translateLegacy(String text) {
|
||||
text = replaceMessage(text);
|
||||
if(!text.contains("§")) return text;
|
||||
|
||||
for (Map.Entry<Character, String> entry : colors.entrySet())
|
||||
text = text.replace("§" + entry.getKey(), entry.getValue());
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public static String colorless(String text) {
|
||||
text = replaceMessage(text);
|
||||
if(!text.contains("§")) return text;
|
||||
|
||||
for (Map.Entry<Character, String> entry : colors.entrySet())
|
||||
text = text.replace("§" + entry.getKey(), "");
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public static void send(Object target, MultipleMessagesHelper texts) {
|
||||
String stringList = StringUtils.getStringList(texts.getLines(), "\n");
|
||||
send(target, stringList);
|
||||
}
|
||||
|
||||
public static void send(Object target, MultipleMessagesHelper texts, String... replacements) {
|
||||
String stringList = StringUtils.getStringList(texts.getLines(), "\n");
|
||||
send(target, stringList, replacements);
|
||||
}
|
||||
|
||||
public static void send(Object target, List<String> texts) {
|
||||
String stringList = StringUtils.getStringList(texts, "\n");
|
||||
send(target, stringList);
|
||||
}
|
||||
|
||||
public static void send(Object target, List<String> texts, String... replacements) {
|
||||
texts = replaceMessageList(texts, replacements);
|
||||
send(target, texts);
|
||||
}
|
||||
|
||||
public static void send(Object target, String text, String... replacements) {
|
||||
if (text.isEmpty()) return;
|
||||
|
||||
text = replaceMessageString(target, text, replacements);
|
||||
|
||||
if (text.contains("%no-message%")) return;
|
||||
|
||||
if(translator == null) {
|
||||
|
||||
CommandSender sender = target instanceof CommandSender
|
||||
? (CommandSender) target
|
||||
: CommandSender.from(target);
|
||||
|
||||
if (!PlaceholderReplacer.process(sender, text, sender::sendMessage))
|
||||
sender.sendMessage(text);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
final Object tmpTarget = target instanceof CommandSender sender
|
||||
? sender.getSenderObject() : target;
|
||||
|
||||
if (PlaceholderReplacer.process(target, text, result -> translator.send(tmpTarget, result))) {
|
||||
return;
|
||||
}
|
||||
|
||||
translator.send(tmpTarget, text);
|
||||
}
|
||||
|
||||
public static String replaceMessage(String text) {
|
||||
return replaceMessage(null, text);
|
||||
}
|
||||
|
||||
public static String replaceMessage(Object targetObj, String text) {
|
||||
CommandSender sender = targetObj == null ? null
|
||||
: targetObj instanceof CommandSender
|
||||
? (CommandSender) targetObj
|
||||
: CommandSender.from(targetObj);
|
||||
|
||||
String executorName = (sender == null || sender.isConsole())
|
||||
? ""
|
||||
: sender.getName();
|
||||
|
||||
String token = (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED || Reflection.isProxyServer())
|
||||
? Storage.CENSORED_TOKEN
|
||||
: "/";
|
||||
|
||||
String serverName = Storage.SERVER_NAME == null ? "/" : Storage.SERVER_NAME;
|
||||
|
||||
text = StringUtils.replace(text,
|
||||
"&", "§",
|
||||
"\\n", "\n",
|
||||
"%executor%", executorName,
|
||||
"%prefix%", Storage.ConfigSections.Messages.PREFIX.PREFIX,
|
||||
"%pat_general_prefix%", Storage.ConfigSections.Messages.PREFIX.PREFIX,
|
||||
"%token%", token,
|
||||
"%sync_server_name%", serverName,
|
||||
"%server%", serverName,
|
||||
"%current_version%", Storage.CURRENT_VERSION,
|
||||
"%newest_version%", Storage.NEWER_VERSION
|
||||
);
|
||||
|
||||
return PlaceholderReplacer.replace(targetObj, text);
|
||||
}
|
||||
|
||||
public static String replaceMessageString(Object targetObj, String rawText, String... replacements) {
|
||||
return replaceMessage(targetObj, StringUtils.replace(rawText, replacements));
|
||||
}
|
||||
|
||||
public static List<String> replaceMessageList(MultipleMessagesHelper rawText, String... replacements) {
|
||||
return replaceMessageList(rawText.getLines(), replacements);
|
||||
}
|
||||
|
||||
public static List<String> replaceMessageList(List<String> rawText, String... replacements) {
|
||||
final HashMap<String, String> REPLACEMENTS = new HashMap<>();
|
||||
List<String> result = new ArrayList<>();
|
||||
|
||||
if(replacements != null) {
|
||||
String firstReplacementInput = null, secondReplacementInput = null;
|
||||
for (String replacement : replacements) {
|
||||
if (firstReplacementInput == null) firstReplacementInput = replacement;
|
||||
else secondReplacementInput = replacement;
|
||||
|
||||
if (firstReplacementInput != null && secondReplacementInput != null) {
|
||||
REPLACEMENTS.put(firstReplacementInput, secondReplacementInput);
|
||||
firstReplacementInput = null;
|
||||
secondReplacementInput = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rawText.forEach(text -> {
|
||||
if(replacements != null)
|
||||
for (Map.Entry<String, String> entry : REPLACEMENTS.entrySet())
|
||||
text = text.replace(entry.getKey(), entry.getValue());
|
||||
String resultText = replaceMessage(text);
|
||||
result.add(resultText);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void sendActionbar(Object targetObj, String message) {
|
||||
translator.sendActionbar(targetObj, message);
|
||||
}
|
||||
|
||||
public static void sendTitle(Object targetObj, String title, String subtitle, int fadeIn, int stay, int fadeOut) {
|
||||
translator.sendTitle(targetObj, title, subtitle, fadeIn, stay, fadeOut);
|
||||
}
|
||||
|
||||
public static void playSound(Object targetObj, String soundKey, float volume, float pitch) throws Exception {
|
||||
translator.playSound(targetObj, soundKey, volume, pitch);
|
||||
}
|
||||
|
||||
public static void closeAudiences() {
|
||||
if(translator == null) return;
|
||||
translator.close();
|
||||
}
|
||||
|
||||
public static boolean isSupported() {
|
||||
return support;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package de.rayzs.pat.utils.message;
|
||||
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
@@ -9,21 +10,21 @@ public interface Translator {
|
||||
|
||||
MiniMessage miniMessage = MiniMessage.miniMessage();
|
||||
|
||||
String translate(String text);
|
||||
String strip(String text);
|
||||
|
||||
void send(Object target, String text);
|
||||
void send(CommandSender sender, String text);
|
||||
|
||||
void sendActionbar(Object target, String text);
|
||||
void sendActionbar(CommandSender sender, String text);
|
||||
|
||||
void sendTitle(Object target, String title, String subtitle, int fadeIn, int stay, int fadeOut);
|
||||
void sendTitle(CommandSender sender, String title, String subtitle, int fadeIn, int stay, int fadeOut);
|
||||
|
||||
void playSound(Object target, String soundKey, float volume, float pitch) throws Exception;
|
||||
void playSound(CommandSender sender, String soundKey, float volume, float pitch) throws Exception;
|
||||
|
||||
default Component toComponent(String text) {
|
||||
text = StringUtils.replace(text, "§", "&");
|
||||
|
||||
Component legacy = LegacyComponentSerializer.legacyAmpersand().deserialize(text);
|
||||
text = StringUtils.replace(miniMessage.serialize(legacy), "\\", "");
|
||||
final Component legacy = LegacyComponentSerializer.legacyAmpersand().deserialize(text);
|
||||
text = miniMessage.serialize(legacy).replace("\\", "");
|
||||
|
||||
return miniMessage.deserialize(text);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
package de.rayzs.pat.utils.message.replacer;
|
||||
|
||||
import de.rayzs.pat.utils.Reflection;
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import de.rayzs.pat.utils.message.replacer.impl.*;
|
||||
import de.rayzs.pat.api.storage.Storage;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class PlaceholderReplacer {
|
||||
@@ -9,8 +14,10 @@ public class PlaceholderReplacer {
|
||||
private static BukkitPlaceholderReplacer BUKKIT_PLACEHOLDER_REPLACER = null;
|
||||
private static ProxyPlaceholderReplacer PROXY_PLACEHOLDER_REPLACER = null;
|
||||
|
||||
public static String replace(Object playerObj, String text) {
|
||||
if (!Storage.USE_PLACEHOLDERAPI)
|
||||
public static String applyPlaceholders(CommandSender sender, String text, String... replacements) {
|
||||
text = applyGeneralReplacements(sender, text, replacements);
|
||||
|
||||
if (Reflection.isProxyServer() || !Storage.USE_PLACEHOLDERAPI)
|
||||
return text;
|
||||
|
||||
if (!text.contains("%"))
|
||||
@@ -19,18 +26,51 @@ public class PlaceholderReplacer {
|
||||
if (BUKKIT_PLACEHOLDER_REPLACER == null)
|
||||
BUKKIT_PLACEHOLDER_REPLACER = new BukkitPlaceholderReplacer();
|
||||
|
||||
return BUKKIT_PLACEHOLDER_REPLACER.process(playerObj, text);
|
||||
return BUKKIT_PLACEHOLDER_REPLACER.process(sender, text);
|
||||
}
|
||||
|
||||
public static boolean process(Object playerObj, String text, Consumer<String> consumer) {
|
||||
if (!Storage.USE_PAPIPROXYBRIDGE)
|
||||
return false;
|
||||
public static void applyProxyPlaceholders(CommandSender sender, String text, Consumer<String> consumer, String... replacements) {
|
||||
text = applyPlaceholders(sender, text, replacements);
|
||||
|
||||
if (!text.contains("%")) return false;
|
||||
if (!Storage.USE_PAPIPROXYBRIDGE) {
|
||||
consumer.accept(text);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PROXY_PLACEHOLDER_REPLACER == null)
|
||||
if (!text.contains("%")) {
|
||||
consumer.accept(text);
|
||||
return;
|
||||
}
|
||||
|
||||
if (PROXY_PLACEHOLDER_REPLACER == null) {
|
||||
PROXY_PLACEHOLDER_REPLACER = new ProxyPlaceholderReplacer();
|
||||
}
|
||||
|
||||
return PROXY_PLACEHOLDER_REPLACER.process(playerObj, text, consumer);
|
||||
if (!PROXY_PLACEHOLDER_REPLACER.process(sender, text, consumer)) {
|
||||
consumer.accept(text);
|
||||
}
|
||||
}
|
||||
|
||||
private static String applyGeneralReplacements(CommandSender sender, String text, String... replacements) {
|
||||
final String executorName = sender == null ? "" : sender.getName();
|
||||
|
||||
final String token = (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED || Reflection.isProxyServer())
|
||||
? Storage.CENSORED_TOKEN
|
||||
: "/";
|
||||
|
||||
final String serverName = Objects.requireNonNullElse(Storage.SERVER_NAME, "/");
|
||||
|
||||
return StringUtils.replace(StringUtils.replace(text, replacements),
|
||||
"&", "§",
|
||||
"\\n", "\n",
|
||||
"%executor%", executorName,
|
||||
"%prefix%", Storage.ConfigSections.Messages.PREFIX.PREFIX,
|
||||
"%pat_general_prefix%", Storage.ConfigSections.Messages.PREFIX.PREFIX,
|
||||
"%token%", token,
|
||||
"%sync_server_name%", serverName,
|
||||
"%server%", serverName,
|
||||
"%current_version%", Storage.CURRENT_VERSION,
|
||||
"%newest_version%", Storage.NEWER_VERSION
|
||||
);
|
||||
}
|
||||
}
|
||||
+5
-10
@@ -6,17 +6,12 @@ import org.bukkit.entity.Player;
|
||||
|
||||
public class BukkitPlaceholderReplacer {
|
||||
|
||||
public String process(Object playerObj, String text) {
|
||||
Player player = null;
|
||||
public String process(CommandSender sender, String text) {
|
||||
|
||||
if(playerObj != null)
|
||||
if(playerObj instanceof CommandSender) {
|
||||
CommandSender sender = (CommandSender) playerObj;
|
||||
player = sender.isPlayer() ? (Player) sender.getSenderObject() : null;
|
||||
} else if(playerObj instanceof Player)
|
||||
player = (Player) playerObj;
|
||||
if (sender.isPlayer() && sender.getSenderObject() instanceof Player player) {
|
||||
return PlaceholderAPI.setPlaceholders(player, text);
|
||||
}
|
||||
|
||||
|
||||
return PlaceholderAPI.setPlaceholders(player, text);
|
||||
return PlaceholderAPI.setPlaceholders(null, text);
|
||||
}
|
||||
}
|
||||
+3
-26
@@ -15,33 +15,10 @@ public class ProxyPlaceholderReplacer {
|
||||
placeholderAPI.setRequestTimeout(1500);
|
||||
}
|
||||
|
||||
public boolean process(Object playerObj, String text, Consumer<String> consumer) {
|
||||
UUID uuid = null;
|
||||
|
||||
if(playerObj != null)
|
||||
|
||||
if (playerObj instanceof CommandSender) {
|
||||
|
||||
uuid = ((CommandSender) playerObj).getUniqueId();
|
||||
|
||||
} else if (Reflection.isVelocityServer()) {
|
||||
|
||||
if (playerObj instanceof com.velocitypowered.api.proxy.Player)
|
||||
uuid = ((com.velocitypowered.api.proxy.Player) playerObj).getUniqueId();
|
||||
|
||||
} else if (Reflection.isProxyServer()) {
|
||||
|
||||
if (playerObj instanceof net.md_5.bungee.api.connection.ProxiedPlayer)
|
||||
uuid = ((net.md_5.bungee.api.connection.ProxiedPlayer) playerObj).getUniqueId();
|
||||
|
||||
} else {
|
||||
if (playerObj instanceof org.bukkit.entity.Player)
|
||||
uuid = ((org.bukkit.entity.Player) playerObj).getUniqueId();
|
||||
}
|
||||
|
||||
if(uuid == null) return false;
|
||||
placeholderAPI.formatPlaceholders(text, uuid).thenAccept(consumer);
|
||||
public boolean process(CommandSender sender, String text, Consumer<String> consumer) {
|
||||
if (sender == null || !sender.isPlayer()) return false;
|
||||
|
||||
placeholderAPI.formatPlaceholders(text, sender.getUniqueId()).thenAccept(consumer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package de.rayzs.pat.utils.message.translators;
|
||||
|
||||
import de.rayzs.pat.utils.Reflection;
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import de.rayzs.pat.plugin.BukkitLoader;
|
||||
import net.kyori.adventure.title.Title;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import de.rayzs.pat.utils.message.*;
|
||||
@@ -21,76 +21,67 @@ public class BukkitMessageTranslator implements Translator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String translate(String text) {
|
||||
return miniMessage.serialize(miniMessage.deserialize(MessageTranslator.translateLegacy(text)));
|
||||
public String strip(String text) {
|
||||
return ChatColor.stripColor(miniMessage.stripTags(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Object target, String text) {
|
||||
if (Reflection.getSoftware().isPaperBased()) {
|
||||
if (target instanceof Player player) {
|
||||
player.sendMessage(toComponent(text));
|
||||
} else if (target instanceof CommandSender sender) {
|
||||
sender.sendMessage(toComponent(text));
|
||||
}
|
||||
public void send(de.rayzs.pat.utils.sender.CommandSender sender, String text) {
|
||||
final Audience audience = sender.getSenderObject() instanceof Player player
|
||||
? audiences.player(player)
|
||||
: sender.getSenderObject() instanceof CommandSender commandSender
|
||||
? audiences.sender(commandSender)
|
||||
: null;
|
||||
|
||||
|
||||
if (audience == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Audience audience = target instanceof Player
|
||||
? audiences.player((Player) target)
|
||||
: audiences.sender((CommandSender) target);
|
||||
|
||||
audience.sendMessage(toComponent(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionbar(Object target, String text) {
|
||||
public void sendActionbar(de.rayzs.pat.utils.sender.CommandSender sender, String text) {
|
||||
final Audience audience = sender.getSenderObject() instanceof Player player
|
||||
? audiences.player(player)
|
||||
: sender.getSenderObject() instanceof CommandSender commandSender
|
||||
? audiences.sender(commandSender)
|
||||
: null;
|
||||
|
||||
if (Reflection.getSoftware().isPaperBased()) {
|
||||
if (target instanceof Player player) {
|
||||
player.sendActionBar(toComponent(text));
|
||||
} else if (target instanceof CommandSender sender) {
|
||||
sender.sendActionBar(toComponent(text));
|
||||
}
|
||||
|
||||
if (audience == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Audience audience = target instanceof Player
|
||||
? audiences.player((Player) target)
|
||||
: audiences.sender((CommandSender) target);
|
||||
|
||||
audience.sendActionBar(toComponent(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(Object target, String titleStr, String subtitleStr, int fadeIn, int stay, int fadeOut) {
|
||||
Title.Times times = Title.Times.times(Duration.ofMillis(fadeIn), Duration.ofMillis(stay), Duration.ofMillis(fadeOut));
|
||||
Title title = Title.title(toComponent(titleStr), toComponent(subtitleStr), times);
|
||||
public void sendTitle(de.rayzs.pat.utils.sender.CommandSender sender, String titleStr, String subtitleStr, int fadeIn, int stay, int fadeOut) {
|
||||
|
||||
if (Reflection.getSoftware().isPaperBased()) {
|
||||
if (target instanceof Player player) {
|
||||
player.showTitle(title);
|
||||
} else if (target instanceof CommandSender sender) {
|
||||
sender.showTitle(title);
|
||||
}
|
||||
final Audience audience = sender.getSenderObject() instanceof Player player
|
||||
? audiences.player(player)
|
||||
: sender.getSenderObject() instanceof CommandSender commandSender
|
||||
? audiences.sender(commandSender)
|
||||
: null;
|
||||
|
||||
|
||||
if (audience == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Audience audience = target instanceof Player
|
||||
? audiences.player((Player) target)
|
||||
: audiences.sender((CommandSender) target);
|
||||
|
||||
final Title.Times times = Title.Times.times(Duration.ofMillis(fadeIn), Duration.ofMillis(stay), Duration.ofMillis(fadeOut));
|
||||
final Title title = Title.title(toComponent(titleStr), toComponent(subtitleStr), times);
|
||||
|
||||
audience.showTitle(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Object target, String soundKey, float volume, float pitch) throws Exception {
|
||||
if (target instanceof Player player) {
|
||||
public void playSound(de.rayzs.pat.utils.sender.CommandSender sender, String soundKey, float volume, float pitch) throws Exception {
|
||||
if (sender.getSenderObject() instanceof Player player) {
|
||||
Sound sound = Sound.valueOf(soundKey);
|
||||
player.playSound(player.getLocation(), sound, volume, pitch);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
package de.rayzs.pat.utils.message.translators;
|
||||
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.sound.Sound;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
|
||||
import net.kyori.adventure.title.Title;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import net.kyori.adventure.audience.Audience;
|
||||
import de.rayzs.pat.utils.message.Translator;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import de.rayzs.pat.plugin.BungeeLoader;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
@@ -24,39 +22,79 @@ public class BungeeMessageTranslator implements Translator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String translate(String text) {
|
||||
return miniMessage.serialize(miniMessage.deserialize(MessageTranslator.translateLegacy(text)));
|
||||
public String strip(String text) {
|
||||
return ChatColor.stripColor(miniMessage.stripTags(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Object target, String text) {
|
||||
Audience audience = target instanceof ProxiedPlayer ? audiences.player((ProxiedPlayer) target) : audiences.sender((CommandSender) target);
|
||||
public void send(de.rayzs.pat.utils.sender.CommandSender sender, String text) {
|
||||
final Audience audience = sender.getSenderObject() instanceof ProxiedPlayer player
|
||||
? audiences.player(player)
|
||||
: sender.getSenderObject() instanceof CommandSender commandSender
|
||||
? audiences.sender(commandSender)
|
||||
: null;
|
||||
|
||||
|
||||
if (audience == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
audience.sendMessage(toComponent(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionbar(Object target, String text) {
|
||||
Audience audience = target instanceof ProxiedPlayer ? audiences.player((ProxiedPlayer) target) : audiences.sender((CommandSender) target);
|
||||
public void sendActionbar(de.rayzs.pat.utils.sender.CommandSender sender, String text) {
|
||||
final Audience audience = sender.getSenderObject() instanceof ProxiedPlayer player
|
||||
? audiences.player(player)
|
||||
: sender.getSenderObject() instanceof CommandSender commandSender
|
||||
? audiences.sender(commandSender)
|
||||
: null;
|
||||
|
||||
|
||||
if (audience == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
audience.sendActionBar(toComponent(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(Object target, String titleStr, String subtitleStr, int fadeIn, int stay, int fadeOut) {
|
||||
Audience audience = target instanceof ProxiedPlayer ? audiences.player((ProxiedPlayer) target) : audiences.sender((CommandSender) target);
|
||||
public void sendTitle(de.rayzs.pat.utils.sender.CommandSender sender, String titleStr, String subtitleStr, int fadeIn, int stay, int fadeOut) {
|
||||
final Audience audience = sender.getSenderObject() instanceof ProxiedPlayer player
|
||||
? audiences.player(player)
|
||||
: sender.getSenderObject() instanceof CommandSender commandSender
|
||||
? audiences.sender(commandSender)
|
||||
: null;
|
||||
|
||||
Title.Times times = Title.Times.times(Duration.ofMillis(fadeIn), Duration.ofMillis(stay), Duration.ofMillis(fadeOut));
|
||||
Title title = Title.title(toComponent(titleStr), toComponent(subtitleStr), times);
|
||||
|
||||
if (audience == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final Title.Times times = Title.Times.times(Duration.ofMillis(fadeIn), Duration.ofMillis(stay), Duration.ofMillis(fadeOut));
|
||||
final Title title = Title.title(toComponent(titleStr), toComponent(subtitleStr), times);
|
||||
|
||||
audience.showTitle(title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Object target, String soundKey, float volume, float pitch) throws Exception {
|
||||
Audience audience = target instanceof ProxiedPlayer ? audiences.player((ProxiedPlayer) target) : audiences.sender((CommandSender) target);
|
||||
Sound sound = Sound.sound(Key.key(soundKey), Sound.Source.MASTER, 1f, 1f);
|
||||
public void playSound(de.rayzs.pat.utils.sender.CommandSender sender, String soundKey, float volume, float pitch) throws Exception {
|
||||
final Audience audience = sender.getSenderObject() instanceof ProxiedPlayer player
|
||||
? audiences.player(player)
|
||||
: sender.getSenderObject() instanceof CommandSender commandSender
|
||||
? audiences.sender(commandSender)
|
||||
: null;
|
||||
|
||||
|
||||
if (audience == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final Sound sound = Sound.sound(Key.key(soundKey), Sound.Source.MASTER, 1f, 1f);
|
||||
audience.playSound(sound, Sound.Emitter.self());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package de.rayzs.pat.utils.message.translators;
|
||||
|
||||
import de.rayzs.pat.utils.message.Translator;
|
||||
import net.kyori.adventure.title.Title;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
public class PaperMessageTranslator implements Translator {
|
||||
|
||||
@Override
|
||||
public String strip(String text) {
|
||||
return ChatColor.stripColor(miniMessage.stripTags(text));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(de.rayzs.pat.utils.sender.CommandSender sender, String text) {
|
||||
if (sender.getSenderObject() instanceof Player player) {
|
||||
player.sendMessage(toComponent(text));
|
||||
} else if (sender.getSenderObject() instanceof CommandSender commandSender) {
|
||||
commandSender.sendMessage(toComponent(text));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionbar(de.rayzs.pat.utils.sender.CommandSender sender, String text) {
|
||||
if (sender.getSenderObject() instanceof Player player) {
|
||||
player.sendActionBar(toComponent(text));
|
||||
} else if (sender.getSenderObject() instanceof CommandSender commandSender) {
|
||||
commandSender.sendActionBar(toComponent(text));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(de.rayzs.pat.utils.sender.CommandSender sender, String titleStr, String subtitleStr, int fadeIn, int stay, int fadeOut) {
|
||||
final Title.Times times = Title.Times.times(Duration.ofMillis(fadeIn), Duration.ofMillis(stay), Duration.ofMillis(fadeOut));
|
||||
final Title title = Title.title(toComponent(titleStr), toComponent(subtitleStr), times);
|
||||
|
||||
if (sender.getSenderObject() instanceof Player player) {
|
||||
player.showTitle(title);
|
||||
} else if (sender.getSenderObject() instanceof CommandSender commandSender) {
|
||||
commandSender.showTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(de.rayzs.pat.utils.sender.CommandSender sender, String soundKey, float volume, float pitch) throws Exception {
|
||||
if (sender.getSenderObject() instanceof Player player) {
|
||||
final Sound sound = Sound.valueOf(soundKey);
|
||||
player.playSound(player.getLocation(), sound, volume, pitch);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {}
|
||||
}
|
||||
+13
-14
@@ -12,39 +12,38 @@ import java.time.Duration;
|
||||
public class VelocityMessageTranslator implements Translator {
|
||||
|
||||
@Override
|
||||
public String translate(String text) {
|
||||
return MiniMessage.miniMessage().serialize(miniMessage.deserialize(MessageTranslator.translateLegacy(text)));
|
||||
public String strip(String text) {
|
||||
return miniMessage.stripTags(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(Object target, String text) {
|
||||
if (target instanceof CommandSource source) {
|
||||
public void send(de.rayzs.pat.utils.sender.CommandSender sender, String text) {
|
||||
if (sender.getSenderObject() instanceof CommandSource source) {
|
||||
source.sendMessage(toComponent(text));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionbar(Object target, String text) {
|
||||
if (target instanceof CommandSource source) {
|
||||
public void sendActionbar(de.rayzs.pat.utils.sender.CommandSender sender, String text) {
|
||||
if (sender.getSenderObject() instanceof CommandSource source) {
|
||||
source.sendActionBar(toComponent(text));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(Object target, String titleStr, String subtitleStr, int fadeIn, int stay, int fadeOut) {
|
||||
Title.Times times = Title.Times.times(Duration.ofMillis(fadeIn), Duration.ofMillis(stay), Duration.ofMillis(fadeOut));
|
||||
Title title = Title.title(toComponent(titleStr), toComponent(subtitleStr), times);
|
||||
public void sendTitle(de.rayzs.pat.utils.sender.CommandSender sender, String titleStr, String subtitleStr, int fadeIn, int stay, int fadeOut) {
|
||||
final Title.Times times = Title.Times.times(Duration.ofMillis(fadeIn), Duration.ofMillis(stay), Duration.ofMillis(fadeOut));
|
||||
final Title title = Title.title(toComponent(titleStr), toComponent(subtitleStr), times);
|
||||
|
||||
if (target instanceof CommandSource source) {
|
||||
if (sender.getSenderObject() instanceof CommandSource source) {
|
||||
source.showTitle(title);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Object target, String soundKey, float volume, float pitch) throws Exception {
|
||||
if (target instanceof CommandSource source) {
|
||||
Sound sound = Sound.sound(Key.key(soundKey), Sound.Source.MASTER, 1f, 1f);
|
||||
|
||||
public void playSound(de.rayzs.pat.utils.sender.CommandSender sender, String soundKey, float volume, float pitch) throws Exception {
|
||||
if (sender.getSenderObject() instanceof CommandSource source) {
|
||||
final Sound sound = Sound.sound(Key.key(soundKey), Sound.Source.MASTER, 1f, 1f);
|
||||
source.playSound(sound, Sound.Emitter.self());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,12 +92,29 @@ 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);
|
||||
}
|
||||
@@ -169,7 +186,9 @@ public class PermissionUtil {
|
||||
}
|
||||
}
|
||||
|
||||
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, final boolean isOperator) {
|
||||
|
||||
@@ -4,7 +4,8 @@ import de.rayzs.pat.plugin.system.communication.Communicator;
|
||||
import de.rayzs.pat.api.storage.Storage;
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@@ -25,8 +26,8 @@ public interface Action {
|
||||
final String displayCommand = StringUtils.replaceTriggers(command, "", "\\", "<", ">", "&");
|
||||
|
||||
|
||||
final List<String> notificationMessage = MessageTranslator.replaceMessageList(
|
||||
Storage.ConfigSections.Messages.NOTIFICATION.ALERT,
|
||||
final String notificationMessage = StringUtils.replace(
|
||||
Storage.ConfigSections.Messages.NOTIFICATION.ALERT.getLines(),
|
||||
"%player%", playerName,
|
||||
"%command%", displayCommand,
|
||||
"%server%", serverName);
|
||||
@@ -36,10 +37,11 @@ public interface Action {
|
||||
if (Storage.SEND_CONSOLE_NOTIFICATION)
|
||||
Logger.info(notificationMessage);
|
||||
|
||||
Storage.NOTIFY_PLAYERS.stream().forEach(tmpUUID -> {
|
||||
Object p = Storage.getLoader().getPlayerObjByUUID(tmpUUID);
|
||||
if (p != null) {
|
||||
MessageTranslator.send(p, notificationMessage);
|
||||
Storage.NOTIFY_PLAYERS.stream().forEach(otherUuid -> {
|
||||
final CommandSender otherSender = CommandSender.from(otherUuid);
|
||||
|
||||
if (otherSender != null) {
|
||||
MessageHelper.sendMessage(otherSender, notificationMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
package de.rayzs.pat.utils.response.action;
|
||||
|
||||
import de.rayzs.pat.utils.response.action.impl.BungeeAction;
|
||||
import de.rayzs.pat.utils.response.action.impl.ModernBukkitAction;
|
||||
import de.rayzs.pat.utils.response.action.impl.OldBukkitAction;
|
||||
import de.rayzs.pat.utils.response.action.impl.BukkitAction;
|
||||
import de.rayzs.pat.utils.response.action.impl.VelocityAction;
|
||||
import de.rayzs.pat.utils.Reflection;
|
||||
import java.util.UUID;
|
||||
@@ -11,8 +10,7 @@ public class ActionHandler {
|
||||
|
||||
private static final Action ACTION = Reflection.isProxyServer() ? Reflection.isVelocityServer()
|
||||
? new VelocityAction() : new BungeeAction()
|
||||
: Reflection.isAtMost(1, 16)
|
||||
? new OldBukkitAction() : new ModernBukkitAction();
|
||||
: new BukkitAction();
|
||||
|
||||
public static void initialize() {}
|
||||
|
||||
|
||||
+24
-23
@@ -2,10 +2,11 @@ package de.rayzs.pat.utils.response.action.impl;
|
||||
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import de.rayzs.pat.utils.response.ResponseHandler;
|
||||
import de.rayzs.pat.utils.response.action.Action;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
@@ -13,19 +14,19 @@ import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ModernBukkitAction implements Action {
|
||||
public class BukkitAction implements Action {
|
||||
|
||||
@Override
|
||||
public void executeConsoleCommand(String action, UUID uuid, String command, String message) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
final CommandSender sender = CommandSender.from(uuid);
|
||||
message = ResponseHandler.replaceArgsVariables(message, command);
|
||||
|
||||
if (player != null) {
|
||||
message = StringUtils.replace(message, "%player%", player.getName());
|
||||
if (sender != null) {
|
||||
message = StringUtils.replace(message, "%player%", sender.getName());
|
||||
}
|
||||
|
||||
if (message.contains("%")) {
|
||||
message = PlaceholderReplacer.replace(player, message);
|
||||
message = PlaceholderReplacer.applyPlaceholders(sender, message);
|
||||
}
|
||||
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), message);
|
||||
@@ -33,37 +34,37 @@ public class ModernBukkitAction implements Action {
|
||||
|
||||
@Override
|
||||
public void executePlayerCommand(String action, UUID uuid, String command, String message) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
final CommandSender sender = CommandSender.from(uuid);
|
||||
|
||||
if (player == null) {
|
||||
if (sender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
message = StringUtils.replace(message, "%player%", player.getName());
|
||||
message = StringUtils.replace(message, "%player%", sender.getName());
|
||||
message = ResponseHandler.replaceArgsVariables(message, command);
|
||||
|
||||
if (message.contains("%")) {
|
||||
message = PlaceholderReplacer.replace(player, message);
|
||||
message = PlaceholderReplacer.applyPlaceholders(sender, message);
|
||||
}
|
||||
|
||||
Bukkit.dispatchCommand(player, message);
|
||||
sender.execute(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String action, UUID uuid, String command, String title, String subTitle, int fadeIn, int stay, int fadeOut) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
final CommandSender sender = CommandSender.from(uuid);
|
||||
|
||||
if (player == null) {
|
||||
if (sender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
title = ResponseHandler.replaceArgsVariables(title, command);
|
||||
subTitle = ResponseHandler.replaceArgsVariables(subTitle, command);
|
||||
|
||||
title = StringUtils.replace(title, "&", "§", "%player%", player.getName());
|
||||
subTitle = StringUtils.replace(subTitle, "&", "§", "%player%", player.getName());
|
||||
title = StringUtils.replace(title, "%player%", sender.getName());
|
||||
subTitle = StringUtils.replace(subTitle, "%player%", sender.getName());
|
||||
|
||||
MessageTranslator.sendTitle(player, title, subTitle, fadeIn, stay, fadeOut);
|
||||
MessageHelper.sendTitle(sender, title, subTitle, fadeIn, stay, fadeOut);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,14 +93,14 @@ public class ModernBukkitAction implements Action {
|
||||
|
||||
@Override
|
||||
public void playSound(String action, UUID uuid, String soundName, float volume, float pitch) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
final CommandSender sender = CommandSender.from(uuid);
|
||||
|
||||
if (player == null) {
|
||||
if (sender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
MessageTranslator.playSound(player, soundName, volume, pitch);
|
||||
MessageHelper.playSound(sender, soundName, volume, pitch);
|
||||
} catch (Exception exception) {
|
||||
Logger.warning("! Failed to read action: " + action);
|
||||
Logger.warning(" > The sound \"" + soundName + "\" could not be found!");
|
||||
@@ -110,15 +111,15 @@ public class ModernBukkitAction implements Action {
|
||||
|
||||
@Override
|
||||
public void sendActionbar(String action, UUID uuid, String command, String message) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
final CommandSender sender = CommandSender.from(uuid);
|
||||
|
||||
if (player == null) {
|
||||
if (sender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
message = StringUtils.replace(message, "%player%", player.getName());
|
||||
message = StringUtils.replace(message, "%player%", sender.getName());
|
||||
message = ResponseHandler.replaceArgsVariables(message, command);
|
||||
|
||||
MessageTranslator.sendActionbar(player, message);
|
||||
MessageHelper.sendActionbar(sender, message);
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,10 @@ package de.rayzs.pat.utils.response.action.impl;
|
||||
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.response.ResponseHandler;
|
||||
import de.rayzs.pat.utils.response.action.Action;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
@@ -40,19 +41,19 @@ public class BungeeAction implements Action {
|
||||
|
||||
@Override
|
||||
public void sendTitle(String action, UUID uuid, String command, String title, String subTitle, int fadeIn, int stay, int fadeOut) {
|
||||
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid);
|
||||
final CommandSender sender = CommandSender.from(uuid);
|
||||
|
||||
if (player == null) {
|
||||
if (sender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
title = ResponseHandler.replaceArgsVariables(title, command);
|
||||
subTitle = ResponseHandler.replaceArgsVariables(subTitle, command);
|
||||
|
||||
title = StringUtils.replace(title, "%player%", player.getName());
|
||||
subTitle = StringUtils.replace(subTitle, "%player%", player.getName());
|
||||
title = StringUtils.replace(title, "%player%", sender.getName());
|
||||
subTitle = StringUtils.replace(subTitle, "%player%", sender.getName());
|
||||
|
||||
MessageTranslator.sendTitle(player, title, subTitle, fadeIn, stay, fadeOut);
|
||||
MessageHelper.sendTitle(sender, title, subTitle, fadeIn, stay, fadeOut);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,14 +62,14 @@ public class BungeeAction implements Action {
|
||||
|
||||
@Override
|
||||
public void playSound(String action, UUID uuid, String soundName, float volume, float pitch) {
|
||||
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid);
|
||||
final CommandSender sender = CommandSender.from(uuid);
|
||||
|
||||
if (player == null) {
|
||||
if (sender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
MessageTranslator.playSound(player, soundName, volume, pitch);
|
||||
MessageHelper.playSound(sender, soundName, volume, pitch);
|
||||
} catch (Exception exception) {
|
||||
Logger.warning("! Failed to read action: " + action);
|
||||
Logger.warning(" > The sound \"" + soundName + "\" could not be found!");
|
||||
@@ -79,14 +80,14 @@ public class BungeeAction implements Action {
|
||||
|
||||
@Override
|
||||
public void sendActionbar(String action, UUID uuid, String command, String message) {
|
||||
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid);
|
||||
final CommandSender sender = CommandSender.from(uuid);
|
||||
|
||||
if (player == null) {
|
||||
if (sender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
message = StringUtils.replace(message, "%player%", player.getName());
|
||||
message = StringUtils.replace(message, "%player%", sender.getName());
|
||||
message = ResponseHandler.replaceArgsVariables(message, command);
|
||||
MessageTranslator.sendActionbar(player, message);
|
||||
MessageHelper.sendActionbar(sender, message);
|
||||
}
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
package de.rayzs.pat.utils.response.action.impl;
|
||||
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.utils.Reflection;
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import de.rayzs.pat.utils.response.ResponseHandler;
|
||||
import de.rayzs.pat.utils.response.action.Action;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class OldBukkitAction implements Action {
|
||||
|
||||
private String versionPackage = null;
|
||||
|
||||
@Override
|
||||
public void executeConsoleCommand(String action, UUID uuid, String command, String message) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
message = ResponseHandler.replaceArgsVariables(message, command);
|
||||
|
||||
if(player != null) {
|
||||
message = StringUtils.replace(message, "%player%", player.getName());
|
||||
}
|
||||
|
||||
if (message.contains("%")) {
|
||||
message = PlaceholderReplacer.replace(player, message);
|
||||
}
|
||||
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executePlayerCommand(String action, UUID uuid, String command, String message) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
message = ResponseHandler.replaceArgsVariables(message, command);
|
||||
message = StringUtils.replace(message, "%player%", player.getName());
|
||||
|
||||
if (message.contains("%")) {
|
||||
message = PlaceholderReplacer.replace(player, message);
|
||||
}
|
||||
|
||||
Bukkit.dispatchCommand(player, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String action, UUID uuid, String command, String title, String subTitle, int fadeIn, int stay, int fadeOut) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
title = StringUtils.replace(title, "&", "§", "%player%", player.getName());
|
||||
subTitle = StringUtils.replace(title, "&", "§", "%player%", player.getName());
|
||||
|
||||
title = ResponseHandler.replaceArgsVariables(title, command);
|
||||
subTitle = ResponseHandler.replaceArgsVariables(subTitle, command);
|
||||
|
||||
title = PlaceholderReplacer.replace(player, title);
|
||||
subTitle = PlaceholderReplacer.replace(player, subTitle);
|
||||
|
||||
player.sendTitle(title, subTitle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPotionEffect(String action, UUID uuid, String potionEffectTypeName, int duration, int amplifier) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PotionEffectType potionEffectType = null;
|
||||
try {
|
||||
potionEffectType = PotionEffectType.getByName(potionEffectTypeName);
|
||||
} catch (Exception ignored) { }
|
||||
|
||||
if (potionEffectType == null) {
|
||||
Logger.warning("! Failed to read action: " + action);
|
||||
Logger.warning(" > The effect \"" + potionEffectTypeName + "\" could not be found!");
|
||||
Logger.warning(" > Here's an example of an existing effect:");
|
||||
Logger.warning(" > BLINDNESS, REGENERATION");
|
||||
return;
|
||||
}
|
||||
|
||||
player.addPotionEffect(new PotionEffect(potionEffectType, duration, amplifier));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(String action, UUID uuid, String soundName, float volume, float pitch) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
|
||||
if(player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Sound sound = Sound.valueOf(soundName);
|
||||
player.playSound(player.getLocation(), sound, volume, pitch);
|
||||
} catch (Exception exception) {
|
||||
Logger.warning("! Failed to read action: " + action);
|
||||
Logger.warning(" > The sound \"" + soundName + "\" could not be found!");
|
||||
Logger.warning(" > Here's an example of an existing sound effect:");
|
||||
Logger.warning(" > ENTITY_ENDER_DRAGON_GROWL");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionbar(String action, UUID uuid, String command, String message) {
|
||||
Player player = Bukkit.getPlayer(uuid);
|
||||
|
||||
if (player == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
message = ResponseHandler.replaceArgsVariables(message, command);
|
||||
message = StringUtils.replace(message, "&", "§", "%player%", player.getName());
|
||||
message = PlaceholderReplacer.replace(player, message);
|
||||
|
||||
try {
|
||||
if (versionPackage == null) {
|
||||
versionPackage = Reflection.getVersionPackageName();
|
||||
}
|
||||
|
||||
Object entityPlayer = player.getClass().getMethod("getHandle").invoke(player);
|
||||
Constructor<?> constructor = (Objects.<Class<?>>requireNonNull(Class.forName("net.minecraft.server." + versionPackage + ".PacketPlayOutChat"))).getConstructor(Class.forName("net.minecraft.server." + versionPackage + ".IChatBaseComponent"), byte.class);
|
||||
Object iChatBaseComponent = (Objects.requireNonNull(Class.forName("net.minecraft.server." + versionPackage + ".IChatBaseComponent"))).getDeclaredClasses()[0].getMethod("a", String.class).invoke(null, "{\"text\":\"" + message + "\"}");
|
||||
Object actionbarPacket = constructor.newInstance(iChatBaseComponent, (byte) 2);
|
||||
Object playerConnection = entityPlayer.getClass().getField("playerConnection").get(entityPlayer);
|
||||
playerConnection.getClass().getMethod("sendPacket", Class.forName("net.minecraft.server." + versionPackage + ".Packet")).invoke(playerConnection, actionbarPacket);
|
||||
|
||||
} catch (ClassNotFoundException
|
||||
| NoSuchMethodException
|
||||
| IllegalAccessException
|
||||
| InvocationTargetException
|
||||
| NoSuchFieldException
|
||||
| InstantiationException exception) {
|
||||
|
||||
Logger.warning("! Failed to run action: " + action);
|
||||
Logger.warning(" > Actionbars are not supported in this server version!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
package de.rayzs.pat.utils.response.action.impl;
|
||||
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.response.ResponseHandler;
|
||||
import de.rayzs.pat.utils.response.action.Action;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import de.rayzs.pat.plugin.VelocityLoader;
|
||||
import de.rayzs.pat.utils.StringUtils;
|
||||
import de.rayzs.pat.utils.sender.CommandSender;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -14,49 +14,48 @@ public class VelocityAction implements Action {
|
||||
|
||||
@Override
|
||||
public void executeConsoleCommand(String action, UUID uuid, String command, String message) {
|
||||
Optional<Player> optPlayer = VelocityLoader.getServer().getPlayer(uuid);
|
||||
final CommandSender sender = CommandSender.from(uuid);
|
||||
message = ResponseHandler.replaceArgsVariables(message, command);
|
||||
|
||||
if (optPlayer.isPresent()) {
|
||||
message = message.replace("%player%", optPlayer.get().getUsername());
|
||||
if (sender != null && sender.isPlayer()) {
|
||||
message = message.replace("%player%", sender.getName());
|
||||
}
|
||||
|
||||
VelocityLoader.getServer().getCommandManager().executeAsync(VelocityLoader.getServer().getConsoleCommandSource(), message);
|
||||
VelocityLoader.getServer().getCommandManager().executeAsync(
|
||||
VelocityLoader.getServer().getConsoleCommandSource(),
|
||||
message
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executePlayerCommand(String action, UUID uuid, String command, String message) {
|
||||
Optional<Player> optPlayer = VelocityLoader.getServer().getPlayer(uuid);
|
||||
final CommandSender sender = CommandSender.from(uuid);
|
||||
|
||||
if (optPlayer.isEmpty()) {
|
||||
if (sender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = optPlayer.get();
|
||||
|
||||
message = message.replace("%player%", player.getUsername());
|
||||
message = message.replace("%player%", sender.getName());
|
||||
message = ResponseHandler.replaceArgsVariables(message, command);
|
||||
|
||||
VelocityLoader.getServer().getCommandManager().executeAsync(player, message);
|
||||
sender.execute(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String action, UUID uuid, String command, String title, String subTitle, int fadeIn, int stay, int fadeOut) {
|
||||
Optional<Player> optPlayer = VelocityLoader.getServer().getPlayer(uuid);
|
||||
final CommandSender sender = CommandSender.from(uuid);
|
||||
|
||||
if (optPlayer.isEmpty()) {
|
||||
if (sender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = optPlayer.get();
|
||||
|
||||
title = ResponseHandler.replaceArgsVariables(title, command);
|
||||
subTitle = ResponseHandler.replaceArgsVariables(subTitle, command);
|
||||
|
||||
title = StringUtils.replace(title, "%player%", player.getUsername());
|
||||
subTitle = StringUtils.replace(subTitle, "%player%", player.getUsername());
|
||||
title = StringUtils.replace(title, "%player%", sender.getName());
|
||||
subTitle = StringUtils.replace(subTitle, "%player%", sender.getName());
|
||||
|
||||
MessageTranslator.sendTitle(player, title, subTitle, fadeIn, stay, fadeOut);
|
||||
MessageHelper.sendTitle(sender, title, subTitle, fadeIn, stay, fadeOut);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,16 +64,14 @@ public class VelocityAction implements Action {
|
||||
|
||||
@Override
|
||||
public void playSound(String action, UUID uuid, String soundName, float volume, float pitch) {
|
||||
Optional<Player> optPlayer = VelocityLoader.getServer().getPlayer(uuid);
|
||||
final CommandSender sender = CommandSender.from(uuid);
|
||||
|
||||
if (optPlayer.isEmpty()) {
|
||||
if (sender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = optPlayer.get();
|
||||
|
||||
try {
|
||||
MessageTranslator.playSound(player, soundName, volume, pitch);
|
||||
MessageHelper.playSound(sender, soundName, volume, pitch);
|
||||
} catch (Exception exception) {
|
||||
Logger.warning("! Failed to read action: " + action);
|
||||
Logger.warning(" > The sound \"" + soundName + "\" could not be found!");
|
||||
@@ -85,17 +82,15 @@ public class VelocityAction implements Action {
|
||||
|
||||
@Override
|
||||
public void sendActionbar(String action, UUID uuid, String command, String message) {
|
||||
Optional<Player> optPlayer = VelocityLoader.getServer().getPlayer(uuid);
|
||||
final CommandSender sender = CommandSender.from(uuid);
|
||||
|
||||
if (optPlayer.isEmpty()) {
|
||||
if (sender == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = optPlayer.get();
|
||||
|
||||
message = ResponseHandler.replaceArgsVariables(message, command);
|
||||
message = StringUtils.replace(message, "%player%", player.getUsername());
|
||||
message = StringUtils.replace(message, "%player%", sender.getName());
|
||||
|
||||
MessageTranslator.sendActionbar(player, message);
|
||||
MessageHelper.sendActionbar(sender, message);
|
||||
}
|
||||
}
|
||||
@@ -51,5 +51,9 @@ public interface CommandSender {
|
||||
String getName();
|
||||
String getServerName();
|
||||
|
||||
void execute(String command);
|
||||
void sendTitle(String title, String subtitle, int fadeIn, int stay, int fadeOut);
|
||||
void sendActionbar(String message);
|
||||
|
||||
void sendMessage(String message);
|
||||
}
|
||||
@@ -1,13 +1,20 @@
|
||||
package de.rayzs.pat.utils.sender.impl;
|
||||
|
||||
import de.rayzs.pat.api.storage.Storage;
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.utils.Reflection;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import de.rayzs.pat.utils.sender.CommandSenderAbstract;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BukkitSender extends CommandSenderAbstract {
|
||||
@@ -100,23 +107,95 @@ public class BukkitSender extends CommandSenderAbstract {
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
if (MessageTranslator.isSupported()) {
|
||||
MessageTranslator.send(sender, message);
|
||||
if (MessageHelper.isSupported()) {
|
||||
MessageHelper.sendMessage(this, message);
|
||||
return;
|
||||
}
|
||||
|
||||
// To prevent color-code overlapping on Bukkit consoles.
|
||||
if (Reflection.isCraftbukkit() && isConsole()) {
|
||||
if (Reflection.isBukkit() && isConsole()) {
|
||||
String[] lines = message.split("\n");
|
||||
|
||||
for (String line : lines) {
|
||||
sender.sendMessage(MessageTranslator.replaceMessage(sender, line));
|
||||
sender.sendMessage(PlaceholderReplacer.applyPlaceholders(this, line));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
sender.sendMessage(MessageTranslator.replaceMessage(sender, message));
|
||||
sender.sendMessage(PlaceholderReplacer.applyPlaceholders(this, message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String title, String subtitle, int fadeIn, int stay, int fadeOut) {
|
||||
if (isPlayer()) return;
|
||||
|
||||
if (MessageHelper.isSupported()) {
|
||||
MessageHelper.sendTitle(this, title, subtitle, 10, 10, 10);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Reflection.isAfter(1, 11, 0)) {
|
||||
((Player) sender).sendTitle(
|
||||
PlaceholderReplacer.applyPlaceholders(this, title),
|
||||
PlaceholderReplacer.applyPlaceholders(this, subtitle),
|
||||
fadeIn, stay, fadeOut
|
||||
);
|
||||
} else {
|
||||
((Player) sender).sendTitle(
|
||||
PlaceholderReplacer.applyPlaceholders(this, title),
|
||||
PlaceholderReplacer.applyPlaceholders(this, subtitle)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String command) {
|
||||
Bukkit.dispatchCommand(sender, command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionbar(String message) {
|
||||
if (MessageHelper.isSupported()) {
|
||||
MessageHelper.sendActionbar(this, message);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (Reflection.isAtMost(1, 16)) {
|
||||
try {
|
||||
final Object entityPlayer = sender.getClass().getMethod("getHandle").invoke(sender);
|
||||
final Constructor<?> constructor = (Objects.<Class<?>> requireNonNull(Class.forName("net.minecraft.server." + Reflection.getVersionPackageName() + ".PacketPlayOutChat")))
|
||||
.getConstructor(
|
||||
Class.forName("net.minecraft.server." + Reflection.getVersionPackageName() + ".IChatBaseComponent"),
|
||||
byte.class
|
||||
);
|
||||
|
||||
final Object iChatBaseComponent = (Objects.requireNonNull(Class.forName("net.minecraft.server." + Reflection.getVersionPackageName() + ".IChatBaseComponent")))
|
||||
.getDeclaredClasses()[0]
|
||||
.getMethod("a", String.class)
|
||||
.invoke(null, "{\"text\":\"" + message + "\"}");
|
||||
|
||||
final Object actionbarPacket = constructor.newInstance(iChatBaseComponent, (byte) 2);
|
||||
final Object playerConnection = entityPlayer.getClass().getField("playerConnection").get(entityPlayer);
|
||||
|
||||
playerConnection.getClass().getMethod(
|
||||
"sendPacket",
|
||||
Class.forName("net.minecraft.server." + Reflection.getVersionPackageName() + ".Packet")
|
||||
).invoke(playerConnection, actionbarPacket);
|
||||
|
||||
return;
|
||||
|
||||
|
||||
} catch (ClassNotFoundException
|
||||
| NoSuchMethodException
|
||||
| IllegalAccessException
|
||||
| InvocationTargetException
|
||||
| NoSuchFieldException
|
||||
| InstantiationException ignored) { }
|
||||
}
|
||||
|
||||
Logger.warning("Actionbars are not supported in this server version!");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package de.rayzs.pat.utils.sender.impl;
|
||||
|
||||
import de.rayzs.pat.api.storage.Storage;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.plugin.logger.Logger;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.message.replacer.PlaceholderReplacer;
|
||||
import de.rayzs.pat.utils.sender.CommandSenderAbstract;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -102,12 +106,56 @@ public class BungeeSender extends CommandSenderAbstract {
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
if (MessageTranslator.isSupported()) {
|
||||
MessageTranslator.send(sender, message);
|
||||
if (MessageHelper.isSupported()) {
|
||||
MessageHelper.sendMessage(this, message);
|
||||
return;
|
||||
}
|
||||
|
||||
sender.sendMessage(MessageTranslator.replaceMessage(sender, message));
|
||||
sender.sendMessage(PlaceholderReplacer.applyPlaceholders(this, message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String title, String subtitle, int fadeIn, int stay, int fadeOut) {
|
||||
if (MessageHelper.isSupported()) {
|
||||
MessageHelper.sendTitle(this, title, subtitle, fadeIn, stay, fadeOut);
|
||||
return;
|
||||
}
|
||||
|
||||
if (! (sender instanceof ProxiedPlayer player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProxyServer.getInstance().createTitle()
|
||||
.title(TextComponent.fromLegacyText(PlaceholderReplacer.applyPlaceholders(this, title)))
|
||||
.subTitle(TextComponent.fromLegacyText(PlaceholderReplacer.applyPlaceholders(this, subtitle)))
|
||||
.fadeIn(fadeIn)
|
||||
.stay(stay)
|
||||
.fadeOut(fadeOut)
|
||||
.send(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionbar(String message) {
|
||||
if (MessageHelper.isSupported()) {
|
||||
MessageHelper.sendActionbar(this, message);
|
||||
return;
|
||||
}
|
||||
|
||||
if (! (sender instanceof ProxiedPlayer player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.sendMessage(
|
||||
ChatMessageType.ACTION_BAR,
|
||||
TextComponent.fromLegacyText(
|
||||
PlaceholderReplacer.applyPlaceholders(this, message)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String command) {
|
||||
ProxyServer.getInstance().getPluginManager().dispatchCommand(sender, command);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,7 +4,7 @@ import com.velocitypowered.api.command.CommandSource;
|
||||
import com.velocitypowered.api.proxy.Player;
|
||||
import de.rayzs.pat.api.storage.Storage;
|
||||
import de.rayzs.pat.plugin.VelocityLoader;
|
||||
import de.rayzs.pat.utils.message.MessageTranslator;
|
||||
import de.rayzs.pat.utils.message.MessageHelper;
|
||||
import de.rayzs.pat.utils.sender.CommandSenderAbstract;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -105,7 +105,22 @@ public class VelocitySender extends CommandSenderAbstract {
|
||||
|
||||
@Override
|
||||
public void sendMessage(String message) {
|
||||
MessageTranslator.send(sender, message);
|
||||
MessageHelper.sendMessage(this, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String title, String subtitle, int fadeIn, int stay, int fadeOut) {
|
||||
MessageHelper.sendTitle(this, title, subtitle, fadeIn, stay, fadeOut);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionbar(String message) {
|
||||
MessageHelper.sendActionbar(this, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String command) {
|
||||
VelocityLoader.getServer().getCommandManager().executeAsync(sender, command);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,7 +3,13 @@ description: Hides more than just your plugins.
|
||||
website: https://www.rayzs.de/products/proantitab/page
|
||||
|
||||
author: Rayzs_YT
|
||||
version: 2.4.3
|
||||
version: 2.5.1
|
||||
main: de.rayzs.pat.plugin.BungeeLoader
|
||||
|
||||
softDepends: [LuckPerms, PAPIProxyBridge]
|
||||
softDepends: [LuckPerms, PAPIProxyBridge]
|
||||
|
||||
libraries:
|
||||
- net.kyori:adventure-platform-bungeecord:4.4.1
|
||||
- net.kyori:adventure-text-minimessage:5.2.0
|
||||
- net.kyori:adventure-api:5.2.0
|
||||
- net.kyori:adventure-text-serializer-legacy:5.2.0
|
||||
@@ -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
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
# %pat_general_prefix% = Get the PAT prefix set in the config.yml.
|
||||
# %pat_general_user% = Get the name of the user who receives this message.
|
||||
# %pat_general_version_current% = Get current version name of PAT.
|
||||
# %pat_general_version_newest% = Get newest version name of PAT.
|
||||
# %pat_general_version_newest% = Get the newest version name of PAT.
|
||||
|
||||
# Placeholders of some of the messages in the config.yml:
|
||||
# %pat_message_unknowncommand% = Get the "unknown command"-message from the config.yml of PAT. [cancel-blocked-command]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -3,13 +3,19 @@ description: Hides more than just your plugins.
|
||||
website: https://www.rayzs.de/products/proantitab/page
|
||||
|
||||
author: Rayzs_YT
|
||||
version: 2.4.3
|
||||
version: 2.5.1
|
||||
api-version: 1.13
|
||||
folia-supported: true
|
||||
main: de.rayzs.pat.plugin.BukkitLoader
|
||||
|
||||
softdepend: [PlaceholderAPI, LuckPerms, GroupManager, Skript, ViaVersion, ViaBackwards, ViaRewind]
|
||||
|
||||
libraries:
|
||||
- net.kyori:adventure-platform-bukkit:4.4.1
|
||||
- net.kyori:adventure-text-minimessage:5.2.0
|
||||
- net.kyori:adventure-api:5.2.0
|
||||
- net.kyori:adventure-text-serializer-legacy:5.2.0
|
||||
|
||||
commands:
|
||||
proantitab:
|
||||
aliases: [pat]
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"id": "proantitab",
|
||||
"name": "ProAntiTab",
|
||||
"version": "2.5.1",
|
||||
"description": "Hides more than just your plugins.",
|
||||
"url": "https://www.rayzs.de/products/proantitab/page",
|
||||
"authors": ["Rayzs_YT"],
|
||||
"main":"de.rayzs.pat.plugin.VelocityLoader",
|
||||
"dependencies": [
|
||||
{
|
||||
"id":"luckperms",
|
||||
"optional":true
|
||||
},
|
||||
{
|
||||
"id":"papiproxybridge",
|
||||
"optional":true
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,371 @@
|
||||
package de.rayzs.pat.utils;
|
||||
|
||||
import de.rayzs.pat.api.storage.Storage;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import de.rayzs.pat.utils.configuration.helper.MultipleMessagesHelper;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.spec.GCMParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class CommunicationPacketsSecurityTest {
|
||||
|
||||
private static final String TOKEN = "test-token-6d21af0b-e44e-4c94-9920-7ecbd96243e1";
|
||||
private static final UUID BACKEND_ID = UUID.fromString("28ef48c0-62cc-4f25-b2f0-6fb53d2dd61b");
|
||||
private static final UUID OTHER_BACKEND_ID = UUID.fromString("dfe05064-55c9-4b3b-a65f-d6beaeb0b9af");
|
||||
private static final String EXPECTED_HKDF_SALT = "ProAntiTab/plugin-messaging/v1";
|
||||
|
||||
private String previousToken;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
previousToken = Storage.TOKEN;
|
||||
Storage.TOKEN = TOKEN;
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
Storage.TOKEN = previousToken;
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalPacketRoundTripsWithMatchingBackendContext() {
|
||||
UUID playerId = UUID.fromString("7c9f9835-cf72-49c1-aaf0-e4c9853cf7fa");
|
||||
var original = new CommunicationPackets.Proxy2Backend.ExecutePlayerCommandPacket(
|
||||
playerId, "warp spawn"
|
||||
);
|
||||
|
||||
byte[] encoded = CommunicationPackets.preparePacket(original, BACKEND_ID);
|
||||
Object decoded = CommunicationPackets.readPacket(encoded, BACKEND_ID);
|
||||
|
||||
assertNotNull(encoded);
|
||||
assertEquals(original, decoded);
|
||||
assertTrue(CommunicationPackets.isP2BPacket(decoded));
|
||||
assertFalse(CommunicationPackets.isInitialPacket(decoded));
|
||||
}
|
||||
|
||||
@Test
|
||||
void initialHandshakePacketRoundTripsIndependentlyOfBackendContext() {
|
||||
var original = new CommunicationPackets.Backend2Proxy.IdentityRequestPacket(BACKEND_ID);
|
||||
|
||||
byte[] encoded = CommunicationPackets.preparePacket(original, BACKEND_ID);
|
||||
|
||||
assertNotNull(encoded);
|
||||
assertTrue(CommunicationPackets.isInitialPacket(encoded));
|
||||
assertEquals(original, CommunicationPackets.readPacket(encoded, OTHER_BACKEND_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void samePlaintextProducesDifferentCiphertextBecauseNonceIsRandom() {
|
||||
var packet = new CommunicationPackets.Proxy2Backend.ConsoleMessagePacket("same message");
|
||||
|
||||
byte[] first = CommunicationPackets.preparePacket(packet, BACKEND_ID);
|
||||
byte[] second = CommunicationPackets.preparePacket(packet, BACKEND_ID);
|
||||
|
||||
assertNotNull(first);
|
||||
assertNotNull(second);
|
||||
assertFalse(Arrays.equals(first, second), "AES-GCM packets must use fresh nonces");
|
||||
assertEquals(packet, CommunicationPackets.readPacket(first, BACKEND_ID));
|
||||
assertEquals(packet, CommunicationPackets.readPacket(second, BACKEND_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void tamperingWithCiphertextIsRejected() {
|
||||
var packet = new CommunicationPackets.Proxy2Backend.ExecuteConsoleCommandPacket("say secure");
|
||||
byte[] encoded = CommunicationPackets.preparePacket(packet, BACKEND_ID);
|
||||
assertNotNull(encoded);
|
||||
|
||||
byte[] tampered = encoded.clone();
|
||||
tampered[tampered.length - 1] ^= 0x01;
|
||||
|
||||
assertNull(CommunicationPackets.readPacket(tampered, BACKEND_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void tamperingWithAuthenticatedHeaderIsRejected() {
|
||||
var packet = new CommunicationPackets.Proxy2Backend.KeepAliveResponsePacket();
|
||||
byte[] encoded = CommunicationPackets.preparePacket(packet, BACKEND_ID);
|
||||
assertNotNull(encoded);
|
||||
|
||||
byte[] tampered = encoded.clone();
|
||||
tampered[1] = 0; // claim this normal packet is an initial packet
|
||||
|
||||
assertNull(CommunicationPackets.readPacket(tampered, BACKEND_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void wrongBackendUuidCannotDecryptNormalPacket() {
|
||||
var packet = new CommunicationPackets.Backend2Proxy.AnnouncePlayerPermissionChanges(UUID.randomUUID());
|
||||
byte[] encoded = CommunicationPackets.preparePacket(packet, BACKEND_ID);
|
||||
|
||||
assertNotNull(encoded);
|
||||
assertNull(CommunicationPackets.readPacket(encoded, OTHER_BACKEND_ID));
|
||||
assertEquals(packet, CommunicationPackets.readPacket(encoded, BACKEND_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void wrongStorageTokenCannotDecryptPacket() {
|
||||
var packet = new CommunicationPackets.Proxy2Backend.NotificationPacket(
|
||||
UUID.randomUUID(), "help"
|
||||
);
|
||||
byte[] encoded = CommunicationPackets.preparePacket(packet, BACKEND_ID);
|
||||
assertNotNull(encoded);
|
||||
|
||||
Storage.TOKEN = "different-token-that-must-not-authenticate";
|
||||
assertNull(CommunicationPackets.readPacket(encoded, BACKEND_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void truncatedAndInvalidFramesAreRejectedWithoutThrowing() {
|
||||
assertDoesNotThrow(() -> {
|
||||
assertNull(CommunicationPackets.readPacket(null, BACKEND_ID));
|
||||
assertNull(CommunicationPackets.readPacket(new byte[0], BACKEND_ID));
|
||||
assertNull(CommunicationPackets.readPacket(new byte[8], BACKEND_ID));
|
||||
});
|
||||
|
||||
var packet = new CommunicationPackets.Backend2Proxy.KeepAlivePacket();
|
||||
byte[] encoded = CommunicationPackets.preparePacket(packet, BACKEND_ID);
|
||||
assertNotNull(encoded);
|
||||
|
||||
for (int length : new int[]{1, 2, 5, 13, encoded.length - 1}) {
|
||||
byte[] truncated = Arrays.copyOf(encoded, length);
|
||||
assertDoesNotThrow(() -> assertNull(CommunicationPackets.readPacket(truncated, BACKEND_ID)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void invalidProtocolVersionIsRejected() {
|
||||
var packet = new CommunicationPackets.Backend2Proxy.KeepAlivePacket();
|
||||
byte[] encoded = CommunicationPackets.preparePacket(packet, BACKEND_ID);
|
||||
assertNotNull(encoded);
|
||||
|
||||
byte[] wrongVersion = encoded.clone();
|
||||
wrongVersion[0] = (byte) (CommunicationPackets.PROTOCOL_VERSION + 1);
|
||||
|
||||
assertNull(CommunicationPackets.readPacket(wrongVersion, BACKEND_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void blankTokenDisablesEncodingAndDecoding() {
|
||||
var packet = new CommunicationPackets.Backend2Proxy.KeepAlivePacket();
|
||||
byte[] valid = CommunicationPackets.preparePacket(packet, BACKEND_ID);
|
||||
assertNotNull(valid);
|
||||
|
||||
Storage.TOKEN = " ";
|
||||
assertNull(CommunicationPackets.preparePacket(packet, BACKEND_ID));
|
||||
assertNull(CommunicationPackets.readPacket(valid, BACKEND_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void representativePacketTypesPreserveTheirPayloads() {
|
||||
UUID player = UUID.fromString("c112a6b7-82ec-4120-a4f6-f7c6d0953eef");
|
||||
Set<UUID> players = new HashSet<>(Set.of(
|
||||
player,
|
||||
UUID.fromString("f59bad95-cd4c-4fc2-a76b-834f38de2447")
|
||||
));
|
||||
|
||||
CommunicationPackets.PATPacket[] packets = {
|
||||
new CommunicationPackets.Proxy2Backend.UpdatePacket(null),
|
||||
new CommunicationPackets.Proxy2Backend.UpdatePacket(player),
|
||||
new CommunicationPackets.Proxy2Backend.IdentityPacket(BACKEND_ID, "survival"),
|
||||
new CommunicationPackets.Proxy2Backend.ExecuteConsoleCommandPacket("list"),
|
||||
new CommunicationPackets.Proxy2Backend.ConsoleMessagePacket("hello"),
|
||||
new CommunicationPackets.Backend2Proxy.IdentityResponsePacket(BACKEND_ID),
|
||||
new CommunicationPackets.Backend2Proxy.DataSyncReceivedPacket(),
|
||||
new CommunicationPackets.Backend2Proxy.AnnounceGroupPermissionChanges(players)
|
||||
};
|
||||
|
||||
for (CommunicationPackets.PATPacket packet : packets) {
|
||||
byte[] encoded = CommunicationPackets.preparePacket(packet, BACKEND_ID);
|
||||
assertNotNull(encoded, () -> "Failed to encode " + packet.getClass().getSimpleName());
|
||||
assertEquals(packet, CommunicationPackets.readPacket(encoded, BACKEND_ID),
|
||||
() -> "Round-trip mismatch for " + packet.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void normalPacketRequiresBackendContext() {
|
||||
var packet = new CommunicationPackets.Backend2Proxy.KeepAlivePacket();
|
||||
|
||||
assertNull(CommunicationPackets.preparePacket(packet, null));
|
||||
|
||||
byte[] encoded = CommunicationPackets.preparePacket(packet, BACKEND_ID);
|
||||
assertNotNull(encoded);
|
||||
assertNull(CommunicationPackets.readPacket(encoded, null));
|
||||
}
|
||||
|
||||
private static CommunicationPackets.Proxy2Backend.DataSyncPacket sync(String prefix, List<String> lines) {
|
||||
return new CommunicationPackets.Proxy2Backend.DataSyncPacket(
|
||||
new CommunicationPackets.Proxy2Backend.DataSyncPacket.Messages(prefix),
|
||||
new CommunicationPackets.Proxy2Backend.DataSyncPacket.AutoLowerCase(true),
|
||||
new CommunicationPackets.Proxy2Backend.DataSyncPacket.UnknownCommand(true, new MultipleMessagesHelper(lines)));
|
||||
}
|
||||
|
||||
private static void assertRoundTrip(CommunicationPackets.PATPacket packet) {
|
||||
byte[] wire = CommunicationPackets.preparePacket(packet, BACKEND_ID);
|
||||
assertNotNull(wire, () -> "Encoding failed for " + packet.getClass().getSimpleName());
|
||||
Object decoded = CommunicationPackets.readPacket(wire, BACKEND_ID);
|
||||
if (packet instanceof CommunicationPackets.Proxy2Backend.DataSyncPacket original) {
|
||||
var actual = assertInstanceOf(CommunicationPackets.Proxy2Backend.DataSyncPacket.class, decoded);
|
||||
assertEquals(original.messages(), actual.messages());
|
||||
assertEquals(original.autoLowerCase(), actual.autoLowerCase());
|
||||
assertEquals(original.unknownCommand().enabled(), actual.unknownCommand().enabled());
|
||||
assertEquals(original.unknownCommand().message().getLines(), actual.unknownCommand().message().getLines());
|
||||
} else {
|
||||
assertEquals(packet, decoded);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void allFourteenPacketTypesRoundTrip() {
|
||||
UUID player = UUID.fromString("f5b80b7d-c1ad-48f0-b07b-4bd3e24fb8f2");
|
||||
CommunicationPackets.PATPacket[] packets = {
|
||||
new CommunicationPackets.Proxy2Backend.UpdatePacket(null),
|
||||
new CommunicationPackets.Proxy2Backend.IdentityPacket(BACKEND_ID, "survival"),
|
||||
new CommunicationPackets.Proxy2Backend.NotificationPacket(player, "help"),
|
||||
new CommunicationPackets.Proxy2Backend.ExecuteConsoleCommandPacket("list"),
|
||||
new CommunicationPackets.Proxy2Backend.ExecutePlayerCommandPacket(player, "spawn"),
|
||||
new CommunicationPackets.Proxy2Backend.ConsoleMessagePacket("hello"),
|
||||
new CommunicationPackets.Proxy2Backend.KeepAliveResponsePacket(),
|
||||
sync("prefix", List.of("one", "two", "three")),
|
||||
new CommunicationPackets.Backend2Proxy.IdentityRequestPacket(BACKEND_ID),
|
||||
new CommunicationPackets.Backend2Proxy.IdentityResponsePacket(BACKEND_ID),
|
||||
new CommunicationPackets.Backend2Proxy.DataSyncReceivedPacket(),
|
||||
new CommunicationPackets.Backend2Proxy.KeepAlivePacket(),
|
||||
new CommunicationPackets.Backend2Proxy.AnnouncePlayerPermissionChanges(player),
|
||||
new CommunicationPackets.Backend2Proxy.AnnounceGroupPermissionChanges(Set.of(player, BACKEND_ID))
|
||||
};
|
||||
assertEquals(14, packets.length);
|
||||
for (var packet : packets) assertRoundTrip(packet);
|
||||
}
|
||||
|
||||
@Test
|
||||
void maximumPlaintextAndWireSizeAreAcceptedAndNextByteRejected() {
|
||||
// 19 bytes of framing + 16,384 + 8,192 + 8,142 bytes of strings = 32,737 bytes.
|
||||
var maximum = sync("a".repeat(16384), List.of("b".repeat(8192), "c".repeat(8142)));
|
||||
byte[] wire = CommunicationPackets.preparePacket(maximum, BACKEND_ID);
|
||||
assertNotNull(wire);
|
||||
assertEquals(32_767, wire.length);
|
||||
assertRoundTrip(maximum);
|
||||
assertNull(CommunicationPackets.readPacket(Arrays.copyOf(wire, wire.length + 1), BACKEND_ID));
|
||||
|
||||
var overMaximum = sync("a".repeat(16384), List.of("b".repeat(8192), "c".repeat(8143)));
|
||||
assertNull(CommunicationPackets.preparePacket(overMaximum, BACKEND_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void utf8StringsAreLimitedByTotalPacketBytes() {
|
||||
// 1-byte type + 4-byte length + UTF-8 bytes.
|
||||
assertRoundTrip(new CommunicationPackets.Proxy2Backend.ConsoleMessagePacket("é".repeat(16_366)));
|
||||
assertNull(CommunicationPackets.preparePacket(
|
||||
new CommunicationPackets.Proxy2Backend.ConsoleMessagePacket("é".repeat(16_367)), BACKEND_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void collectionsAreLimitedByTotalPacketBytes() {
|
||||
// Each empty string still takes 4 bytes for its length prefix.
|
||||
assertRoundTrip(sync("", java.util.Collections.nCopies(8_181, "")));
|
||||
assertNull(CommunicationPackets.preparePacket(
|
||||
sync("", java.util.Collections.nCopies(8_182, "")), BACKEND_ID));
|
||||
|
||||
Set<UUID> ids = new HashSet<>();
|
||||
for (int i = 0; i < 2_045; i++) ids.add(new UUID(0, i));
|
||||
assertRoundTrip(new CommunicationPackets.Backend2Proxy.AnnounceGroupPermissionChanges(ids));
|
||||
ids.add(new UUID(0, 2_045));
|
||||
assertNull(CommunicationPackets.preparePacket(
|
||||
new CommunicationPackets.Backend2Proxy.AnnounceGroupPermissionChanges(ids), BACKEND_ID));
|
||||
}
|
||||
|
||||
// Independently encrypt arbitrary plaintext to exercise malformed authenticated codec input.
|
||||
private static byte[] authenticatedFrame(byte[] plaintext, boolean initial) throws Exception {
|
||||
Method derive = CommunicationPackets.class.getDeclaredMethod("deriveKey", String.class, UUID.class);
|
||||
derive.setAccessible(true);
|
||||
SecretKeySpec key = (SecretKeySpec) derive.invoke(null, TOKEN, initial ? null : BACKEND_ID);
|
||||
byte[] header = {CommunicationPackets.PROTOCOL_VERSION, (byte) (initial ? 0 : 1)};
|
||||
byte[] nonce = new byte[12]; // Deterministic nonce used only by isolated test frames.
|
||||
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(128, nonce));
|
||||
cipher.updateAAD(header);
|
||||
byte[] ciphertext = cipher.doFinal(plaintext);
|
||||
byte[] frame = new byte[header.length + nonce.length + ciphertext.length];
|
||||
System.arraycopy(header, 0, frame, 0, 2);
|
||||
System.arraycopy(nonce, 0, frame, 2, 12);
|
||||
System.arraycopy(ciphertext, 0, frame, 14, ciphertext.length);
|
||||
return frame;
|
||||
}
|
||||
|
||||
private static byte[] plaintext(int type, int length) throws Exception {
|
||||
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
|
||||
DataOutputStream out = new DataOutputStream(bytes);
|
||||
out.writeByte(type);
|
||||
out.writeInt(length);
|
||||
return bytes.toByteArray();
|
||||
}
|
||||
|
||||
@Test
|
||||
void authenticatedMalformedPayloadsAreRejected() throws Exception {
|
||||
// Unknown packet type, trailing bytes, invalid/negative string lengths.
|
||||
byte[][] invalid = {
|
||||
{(byte) 127},
|
||||
{23, 1},
|
||||
plaintext(6, -1),
|
||||
plaintext(6, 32_738),
|
||||
plaintext(6, 10),
|
||||
plaintext(25, -1),
|
||||
plaintext(25, Integer.MAX_VALUE),
|
||||
plaintext(8, -1),
|
||||
plaintext(8, Integer.MAX_VALUE)
|
||||
};
|
||||
for (byte[] payload : invalid) {
|
||||
assertNull(CommunicationPackets.readPacket(authenticatedFrame(payload, false), BACKEND_ID),
|
||||
"Malformed authenticated packet accepted: " + Arrays.toString(payload));
|
||||
}
|
||||
// Initial flag must match decoded packet type, even with a valid GCM tag.
|
||||
assertNull(CommunicationPackets.readPacket(authenticatedFrame(new byte[]{23}, true), BACKEND_ID));
|
||||
assertNull(CommunicationPackets.readPacket(authenticatedFrame(new byte[]{20}, false), BACKEND_ID));
|
||||
}
|
||||
|
||||
@Test
|
||||
void hkdfMatchesIndependentExtractExpandComputation() throws Exception {
|
||||
Method derive = CommunicationPackets.class.getDeclaredMethod("deriveKey", String.class, UUID.class);
|
||||
derive.setAccessible(true);
|
||||
Mac mac = Mac.getInstance("HmacSHA256");
|
||||
mac.init(new SecretKeySpec(EXPECTED_HKDF_SALT.getBytes(StandardCharsets.UTF_8), "HmacSHA256"));
|
||||
byte[] prk = mac.doFinal(TOKEN.getBytes(StandardCharsets.UTF_8));
|
||||
for (UUID context : new UUID[]{null, BACKEND_ID}) {
|
||||
String info = context == null ? "initial" : "backend:" + context;
|
||||
mac.init(new SecretKeySpec(prk, "HmacSHA256"));
|
||||
mac.update(info.getBytes(StandardCharsets.UTF_8));
|
||||
mac.update((byte) 1);
|
||||
byte[] expected = mac.doFinal();
|
||||
SecretKeySpec actual = (SecretKeySpec) derive.invoke(null, TOKEN, context);
|
||||
assertArrayEquals(expected, actual.getEncoded());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void oversizedWirePacketIsRejectedBeforeDecryption() {
|
||||
// Default Velocity maximum payload size plus one byte.
|
||||
byte[] oversized = new byte[32_768];
|
||||
oversized[0] = CommunicationPackets.PROTOCOL_VERSION;
|
||||
oversized[1] = 1;
|
||||
|
||||
assertNull(CommunicationPackets.readPacket(oversized, BACKEND_ID));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user