Compare commits

...
107 Commits
Author SHA1 Message Date
rayzsyt 428ddfb78d Update MiniMessage API 2026-04-28 00:26:07 +02:00
rayzsyt 56bd8be247 Update Version 2026-04-27 23:54:32 +02:00
rayzsyt f7b2aa281e Small change 2026-04-27 23:18:48 +02:00
rayzsyt 0599d504af Fixed that messages were not set automatically in auto-config-updater 2026-04-27 23:18:29 +02:00
rayzsyt 471e0b100f Removed Version enum & simplified some code parts 2026-04-27 22:59:57 +02:00
rayzsyt 52d842b27a Small visual changes to make code more readable 2026-04-27 22:49:28 +02:00
Alihan dfc6ba91eb Merge pull request #26 from gaboss44/feat/mc-26.1-reflection
Reflection class changes
2026-04-27 21:22:51 +02:00
gaboss44 54d59d7b03 Reflection class changes 2026-04-27 13:01:04 -05:00
Alihan a4931199af Merge pull request #24 from MasivoSMP/main
Fix global-thread lag in Folia
2026-03-23 20:23:21 +01:00
Chesvin1 02469e977c Fix globa-thread lag in Folia
Replace backend plugin-message dispatch in BukkitClient from Server.sendPluginMessage(...) (broadcast/fan-out behavior) to single carrier-player dispatch via PATScheduler.execute(..., player).
This keeps plugin messaging on a player/entity scheduler for Folia, reducing redundant per-player sends and feedback amplification that were loading the global scheduler thread under high player counts.
2026-03-22 17:36:04 -03:00
rayzsyt f9386fd3f1 Merge remote-tracking branch 'origin/main' 2026-03-19 19:50:31 +01:00
rayzsyt 242590f3e8 Add 'suppress-exceptions' option 2026-03-19 19:50:12 +01:00
rayzsyt 65c383491e Changed order to filter number last 2026-03-06 19:26:16 +01:00
rayzsyt 0356c2f606 Implemented injection-failed settings 2026-02-27 22:32:49 +01:00
rayzsyt 60067f75d3 Added injection-failed option setting 2026-02-27 22:32:38 +01:00
rayzsyt e896ccb72d Added injection-failed option setting 2026-02-27 22:32:27 +01:00
rayzsyt 6c3dc58cd6 Updated Bungeecord API 2026-02-27 22:32:04 +01:00
rayzsyt 57ada83bfe Corrected wrong information 2026-02-17 03:23:46 +01:00
rayzsyt 8a86f05133 Fixed that proxies would create non-existing command tab-completions 2026-02-17 03:10:57 +01:00
rayzsyt f447cf69d3 Renamed "allow-p2b-packets" -> "allow-p2b-actions" 2026-02-15 00:44:11 +01:00
rayzsyt d06b723adc Reimplemented "Detected Software-API" 2026-02-14 23:46:26 +01:00
rayzsyt f8617cf1b9 Display software name 2026-02-14 23:46:00 +01:00
rayzsyt 8630a6f74c Removed debug message and shorten error message to something more informative 2026-02-14 23:25:30 +01:00
rayzsyt 424d892091 Changed to reveal first and last 2 characters of censored token 2026-02-14 23:18:37 +01:00
rayzsyt 9aaef6e297 Only display censored token instead 2026-02-14 23:10:33 +01:00
rayzsyt e749760136 Added CENSORED_TOKEN 2026-02-14 23:10:25 +01:00
rayzsyt 7f2f3c54ba Fixed color-code overlapping on Bukkit consoles 2026-02-14 22:54:03 +01:00
rayzsyt 24f2c867c6 Added method to reload Client to (un)register the plugin-channels accordingly 2026-02-14 22:28:10 +01:00
rayzsyt e7f3288fb7 Added method to reload Client to (un)register the plugin-channels accordingly 2026-02-14 22:28:05 +01:00
rayzsyt 2221062e98 Fix exception on Craftbukkit servers 2026-02-14 22:26:36 +01:00
rayzsyt 430f5ee9e6 Removed debug message 2026-02-14 22:26:20 +01:00
rayzsyt cd1a7cf312 Removed "Detected Software-API" since it's already in the title 2026-02-14 22:08:00 +01:00
rayzsyt 002cdc64ef Small code cleanup 2026-02-14 22:04:28 +01:00
rayzsyt 3d59686ba4 Small code cleanup 2026-02-14 22:02:01 +01:00
rayzsyt f6c72b9d0e Improved visual representation 2026-02-14 21:21:36 +01:00
rayzsyt d72d419044 Removed unrequired methods 2026-02-14 21:21:24 +01:00
rayzsyt c71a3a4002 Applied changes for new PAT sync-network 2026-02-14 21:21:05 +01:00
rayzsyt 02b70ed324 Applied changes for new PAT sync-network 2026-02-14 21:20:59 +01:00
rayzsyt 01d0a53049 Improved logic & implemented new PAT sync-network 2026-02-14 21:19:10 +01:00
rayzsyt c700ca6abb Removed unused method 2026-02-14 21:17:15 +01:00
rayzsyt d9cba6c010 Added option to toggle P2B packets 2026-02-14 21:16:49 +01:00
rayzsyt a6ed66cf1e Reimplemented PAT sync-network 2026-02-14 21:16:18 +01:00
rayzsyt 4f5b7ad3fb Recoded PAT sync-network 2026-02-14 21:12:03 +01:00
rayzsyt 962ea8b719 Small adjustment 2026-02-14 21:07:17 +01:00
rayzsyt 35e4d0b5aa Add AutoLowerCase for proxy 2026-02-14 20:05:48 +01:00
rayzsyt 497fe5ef98 Added last received alive packet 2026-02-14 20:02:48 +01:00
rayzsyt 0508387db1 Modified 'pat info' message 2026-02-14 19:49:20 +01:00
rayzsyt 1ff7c419ef Add last_alive_response 2026-02-14 19:24:03 +01:00
rayzsyt 612eda685c Modified bpat stats message 2026-02-14 19:17:50 +01:00
rayzsyt 7fc7b571a3 Add AutoLowerCase & Modified bpat stats message 2026-02-14 19:16:00 +01:00
rayzsyt 5cce86bf8d Check if token matches 2026-02-13 18:32:13 +01:00
Alihan Olgun 7621d815ac Code cleanup & Removed unnecessary data sync packets 2026-02-11 21:01:12 +01:00
rayzsyt 81495e3478 Removed unnecessary method implementation for Bukkit-Scheduler 2026-02-08 14:04:12 +01:00
rayzsyt 5c591d3a5b Fixed P2BExecute action in Folia 2026-02-08 13:54:23 +01:00
rayzsyt f1c225b718 Force command execution in main thread 2026-02-08 12:42:15 +01:00
rayzsyt ca7a098cfa Made warning a bit more visual present 2026-02-07 23:53:36 +01:00
rayzsyt b2fbba8455 Made warning a bit more visual present 2026-02-07 23:50:53 +01:00
rayzsyt ae6300c43c Changed parameters for Communicator#sendNotificationPacket method 2026-02-07 23:47:52 +01:00
rayzsyt cb62734da5 Implemented "alert" action and simplified the description 2026-02-07 23:47:18 +01:00
rayzsyt 04a2e4ea54 Add alert action for custom-responses 2026-02-07 23:46:32 +01:00
rayzsyt 2969469605 Replace %server% by server-name from Storage automatically 2026-02-07 23:08:28 +01:00
rayzsyt 25a0f7a742 Implemented P2B packets 2026-02-07 23:08:12 +01:00
rayzsyt d2f6c3336e Updated version 2026-02-07 21:44:01 +01:00
rayzsyt d2c7e00639 Fixed that only Bungeecord commands show up after "bpat reload" 2026-02-07 21:42:13 +01:00
rayzsyt e23fb19c98 Fixed custom-responses actions: execute & console 2026-02-07 21:40:25 +01:00
rayzsyt 1f8d5b78a7 Force command-update on Bungeecord 2026-01-25 01:24:50 +01:00
rayzsyt fee0362c69 Ensure packet not being sent if sync is disabled 2026-01-25 01:22:46 +01:00
rayzsyt 428d944933 Minor changes 2026-01-25 00:20:03 +01:00
rayzsyt 180d23fb1a Fixed wrong usage of sub-arguments in CommandWhitelist conversion 2026-01-23 12:35:04 +01:00
rayzsyt f54dc0f028 Implement Craftbukkit support 2026-01-21 22:05:38 +01:00
rayzsyt ef141a6e7f Disable MiniMessage for Craftbukkit 2026-01-21 21:45:25 +01:00
rayzsyt 55b0b5df75 Add Craftbukkit check 2026-01-21 21:37:10 +01:00
rayzsyt bc78304e97 Small adjustment 2026-01-21 20:18:48 +01:00
rayzsyt 42d8ea3526 Implement TEMP_PLAYER_SERVER_CACHE usage 2026-01-21 19:42:51 +01:00
rayzsyt dfc0066c17 Implement context check 2026-01-21 19:42:21 +01:00
rayzsyt 9e3e61e9a2 Reimplemented update-groups-per-server 2026-01-21 19:41:19 +01:00
rayzsyt 6551bffcdb Implement TEMP_PLAYER_SERVER_CACHE cache 2026-01-21 19:13:22 +01:00
rayzsyt 44f3b4d6d5 Return world name in getPlayerSerName(UUID) method 2026-01-21 18:12:27 +01:00
rayzsyt c672eaaf81 Cancelled event 2026-01-19 16:18:14 +01:00
rayzsyt 460013d22a Added default slash if not there 2026-01-19 16:17:06 +01:00
rayzsyt af89f082aa Always clear sub-arguments for custom-plugins & custom-version feature 2026-01-19 15:50:25 +01:00
rayzsyt e0c3c8a343 Made always executable if it's the console 2026-01-18 19:49:31 +01:00
rayzsyt 83480db4c6 Small adjustments 2026-01-18 19:44:46 +01:00
rayzsyt 04d441cfd6 Add missing interface 2026-01-18 19:44:29 +01:00
rayzsyt 842c2654c6 Add server placeholder to forwarded notification alert 2026-01-18 19:44:01 +01:00
rayzsyt 01d825da86 Implement NotificationPacket call 2026-01-18 18:50:21 +01:00
rayzsyt d61dd872eb Check if option is actually enabled 2026-01-18 17:49:01 +01:00
rayzsyt 3c417c6a8e Add displayCommand to NotificationPacket implementation 2026-01-18 17:40:01 +01:00
rayzsyt f0772a0969 Implement NotificationPacket 2026-01-18 17:39:47 +01:00
rayzsyt 2a83c1c548 Implement NotificationPacket and simplified logic 2026-01-18 17:35:23 +01:00
rayzsyt 12114c63bf Implement ForwardNotificationPacket 2026-01-18 17:30:37 +01:00
rayzsyt 8123ff2f27 Add Forward-Console-Notification-Alerts option 2026-01-18 17:29:29 +01:00
rayzsyt b56ebb3fcb Add NotificationPacket 2026-01-18 17:16:36 +01:00
rayzsyt 7adcce2361 Updated reference url 2026-01-18 17:10:08 +01:00
rayzsyt 6444ec153c Removed unused methods 2026-01-18 17:08:48 +01:00
rayzsyt 841253708d Changed version name 2026-01-18 16:31:46 +01:00
rayzsyt 467308be62 Implemented %offline_players% 2026-01-17 17:53:05 +01:00
rayzsyt d2f8305727 Added new commands to default config 2026-01-17 16:57:48 +01:00
rayzsyt 1a19435b96 Added checks to ensure the list hasn't been modified during the for-loop 2026-01-15 20:07:58 +01:00
rayzsyt eb4b2b1e17 Removed unnecessary computation 2026-01-15 19:53:32 +01:00
rayzsyt 8bca4bc091 Fixed sub-argument disappearing on Spigot servers 2026-01-15 19:48:02 +01:00
rayzsyt dfef20fb87 Fixed subargument blocking in BLACKLIST mode 2026-01-15 19:10:38 +01:00
rayzsyt f4e1dbf385 Fixed subargument blocking in BLACKLIST mode 2026-01-15 19:07:25 +01:00
rayzsyt 93a84f668a Fixed subargument blocking in BLACKLIST mode 2026-01-15 16:55:10 +01:00
rayzsyt f8463c9927 Fix command being blocked entirely if used in BLACKLIST mode 2026-01-15 16:22:46 +01:00
rayzsyt 34b5cd89e5 Ensures that the parent isn't null 2026-01-15 16:15:41 +01:00
rayzsyt 6aae96ab87 Removed old comment 2026-01-15 15:58:05 +01:00
71 changed files with 1793 additions and 1058 deletions

No files matched your search

+2 -2
View File
@@ -122,7 +122,7 @@ enabled: false
######
# **C**USTOM PLUGINS LIST
Just blocking the /plugins command is pretty boring after some time. This feature here allows you to make it more interesting by faking a /plugins message with, for example, fake plugins! ^^
Just blocking the /plugins command is pretty boring. This feature here allows you to make it more interesting by displaying for example fake plugins.
![https://www.rayzs.de/proantitab/assets/fakeplugins2.PNG](https://www.rayzs.de/proantitab/assets/fakeplugins2.PNG)
<details>
@@ -146,7 +146,7 @@ message:
######
# **C**USTOM VERSION COMMAND
Who wouldn't like to pretend to own a custom server-jar? Have fun customizing your very own /version command to your personal liking. ^^
Who wouldn't like to pretend to own a custom server-jar? Have fun customizing your very own /version command to your personal liking.
![https://www.rayzs.de/proantitab/assets/custom-version.png](https://www.rayzs.de/proantitab/assets/custom-version.png)
<details>
+4 -4
View File
@@ -6,7 +6,7 @@
<groupId>de.rayzs.pat</groupId>
<artifactId>ProAntiTab</artifactId>
<version>2.2.0</version>
<version>2.3.2</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
@@ -100,7 +100,7 @@
<dependency>
<groupId>net.md-5</groupId>
<artifactId>bungeecord-api</artifactId>
<version>1.20-R0.3-SNAPSHOT</version>
<version>1.21-R0.5-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@@ -227,14 +227,14 @@
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-text-minimessage</artifactId>
<version>4.25.0</version>
<version>4.26.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.25.0</version>
<version>4.26.1</version>
<scope>compile</scope>
</dependency>
@@ -7,7 +7,7 @@ import de.rayzs.pat.utils.Reflection;
public class CustomServerBrand {
public static final String CHANNEL_NAME = Reflection.getMinor() < 13 ? "MC|Brand" : "minecraft:brand";
public static final String CHANNEL_NAME = Reflection.isBefore(1, 13) ? "MC|Brand" : "minecraft:brand";
private static final ServerBrand SERVER_BRAND = Reflection.isVelocityServer() ? new VelocityServerBrand() : Reflection.isProxyServer() ? new BungeeServerBrand() : new BukkitServerBrand();
public static void initialize() { refreshTask(); }
@@ -30,7 +30,7 @@ public class BukkitServerBrand implements ServerBrand {
if (Reflection.isWeird()) {
NO_PREP_CHANNELS = Reflection.getMinor() >= 22 || (Reflection.getMinor() == 21 && Reflection.getRelease() >= 7);
NO_PREP_CHANNELS = Reflection.isAtLeast(1, 21, 7);
if (brandPayloadClass == null)
brandPayloadClass = Reflection.getClass("net.minecraft.network.protocol.common.custom.BrandPayload");
@@ -1,41 +1,101 @@
package de.rayzs.pat.api.communication;
import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.plugin.logger.Logger;
import de.rayzs.pat.utils.scheduler.*;
import org.bukkit.Bukkit;
public class BackendUpdater {
private BackendUpdater() {}
private static PATSchedulerTask TASK;
private static boolean CONNECTED = false,
WAITING = false;
private static final long SCHEDULER_PERIOD_TIME = 20 * 10;
public static void handle() {
if(isRunning() || !shouldRun() || !Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) return;
if (!Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) {
return;
}
if (isRunning() || !canRun()) {
return;
}
start();
}
public static boolean isRunning() {
return TASK != null && TASK.isActive();
public static void restart() {
stop();
handle();
}
public static void start() {
if(isRunning() || !Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) return;
public static void receivedKeepAlivePacket() {
WAITING = false;
CONNECTED = true;
}
public static boolean isConnected() {
return CONNECTED;
}
private static void start() {
if (isRunning()) return;
TASK = PATScheduler.createScheduler(() -> {
if (shouldRun())
Communicator.sendRequest();
else
if (!canRun()) {
stop();
}, 5, 20);
return;
}
if (CONNECTED) {
if (WAITING) {
disconnect();
Communicator.Backend2Proxy.sendIdentityRequest();
return;
}
WAITING = true;
Communicator.Backend2Proxy.sendKeepAliveRequest();
return;
}
Communicator.Backend2Proxy.sendIdentityRequest();
}, 20, SCHEDULER_PERIOD_TIME);
}
public static void stop() {
if(TASK == null || !TASK.isActive()) return;
TASK.cancelTask();
TASK = null;
disconnect();
if (isRunning()) {
TASK.cancelTask();
TASK = null;
}
}
private static boolean shouldRun() {
int onlinePlayerSize = Bukkit.getOnlinePlayers().size();
private static void disconnect() {
CONNECTED = false;
WAITING = false;
}
private static boolean isRunning() {
return TASK != null && TASK.isActive();
}
private static boolean canRun() {
if (!Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) {
return false;
}
final int onlinePlayerSize = Bukkit.getOnlinePlayers().size();
return onlinePlayerSize >= 1;
}
}
@@ -1,6 +1,9 @@
package de.rayzs.pat.api.communication;
import de.rayzs.pat.utils.CommunicationPackets;
public interface Client {
String CHANNEL_NAME = "pat:channel";
void send(Object packet);
void reload();
void send(CommunicationPackets.PATPacket packet);
}
@@ -1,253 +1,356 @@
package de.rayzs.pat.api.communication;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.TimeUnit;
import de.rayzs.pat.api.communication.client.ClientInfo;
import de.rayzs.pat.api.communication.client.impl.BungeeClientInfo;
import de.rayzs.pat.api.communication.client.impl.VelocityClientInfo;
import de.rayzs.pat.api.communication.impl.BukkitClient;
import de.rayzs.pat.api.communication.impl.BungeeClient;
import de.rayzs.pat.api.communication.impl.VelocityClient;
import de.rayzs.pat.api.event.PATEventHandler;
import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.api.storage.blacklist.impl.GeneralBlacklist;
import de.rayzs.pat.api.storage.blacklist.impl.GroupBlacklist;
import de.rayzs.pat.plugin.BukkitLoader;
import de.rayzs.pat.plugin.logger.Logger;
import de.rayzs.pat.utils.CommunicationPackets;
import de.rayzs.pat.utils.ExpireCache;
import de.rayzs.pat.utils.Reflection;
import de.rayzs.pat.utils.group.Group;
import de.rayzs.pat.utils.group.GroupManager;
import de.rayzs.pat.utils.group.TinyGroup;
import de.rayzs.pat.utils.permission.PermissionUtil;
public class Communicator {
private static final Client CLIENT =
Reflection.isVelocityServer() ? new VelocityClient()
: Reflection.isProxyServer() ? new BungeeClient()
: new BukkitClient();
private static final UUID SERVER_ID = UUID.randomUUID();
private static Communicator instance = null;
public static final List<ClientInfo> CLIENTS = new ArrayList<>();
public static void initialize(final Client client) {
if (instance != null) {
Logger.warning("Communicator instance is already initialized!");
return;
}
public static int SERVER_DATA_SYNC_COUNT = 0;
public static long LAST_DATA_UPDATE = System.currentTimeMillis(),
LAST_SENT_REQUEST = 0,
LAST_BUKKIT_SYNC = System.currentTimeMillis();
public static void sendPacket(Object packet) {
CLIENT.send(packet);
instance = new Communicator(client);
}
public static void sendPacket(ClientInfo clientInfo, Object packet) {
clientInfo.sendBytes(CommunicationPackets.convertToBytes(packet));
public static Communicator get() {
return instance;
}
public static void receiveInformation(String serverName, Object packet) {
ClientInfo client = getClientByName(serverName);
if (packet instanceof CommunicationPackets.RequestPacket) {
public static class Backend2Proxy {
CommunicationPackets.RequestPacket requestPacket = (CommunicationPackets.RequestPacket) packet;
private Backend2Proxy() {}
if (!requestPacket.isToken(Storage.TOKEN))
return;
if (client == null) {
client = Reflection.isVelocityServer()
? new VelocityClientInfo(requestPacket.getServerId(), serverName)
: new BungeeClientInfo(requestPacket.getServerId(), serverName);
CLIENTS.add(client);
}
if (!client.compareId(requestPacket.getServerId()))
client.setId(requestPacket.getServerId());
syncData(client.getId());
return;
}
if (packet instanceof CommunicationPackets.UpdateCommandsPacket) {
if (Reflection.isProxyServer())
return;
CommunicationPackets.UpdateCommandsPacket updateCommandsPacket = (CommunicationPackets.UpdateCommandsPacket) packet;
BukkitLoader.handleUpdateCommandsPacket(updateCommandsPacket);
}
if (packet instanceof CommunicationPackets.ForcePermissionResetPacket) {
if (Reflection.isProxyServer())
return;
CommunicationPackets.ForcePermissionResetPacket permissionResetPacket = (CommunicationPackets.ForcePermissionResetPacket) packet;
if (!permissionResetPacket.isToken(Storage.TOKEN))
return;
if (permissionResetPacket.hasTarget())
PermissionUtil.setPlayerPermissions(permissionResetPacket.getTargetUUID());
else
PermissionUtil.reloadPermissions();
return;
}
if (packet instanceof CommunicationPackets.BackendDataPacket) {
CommunicationPackets.BackendDataPacket backendDataPacket = (CommunicationPackets.BackendDataPacket) packet;
if (!backendDataPacket.isToken(Storage.TOKEN))
return;
Storage.SERVER_NAME = backendDataPacket.getServerName();
return;
}
if (packet instanceof CommunicationPackets.FeedbackPacket) {
CommunicationPackets.FeedbackPacket feedbackPacket = (CommunicationPackets.FeedbackPacket) packet;
if (!feedbackPacket.isToken(Storage.TOKEN))
return;
String serverId = feedbackPacket.getServerId();
if (client == null) {
client = Reflection.isVelocityServer()
? new VelocityClientInfo(feedbackPacket.getServerId(), serverName)
: new BungeeClientInfo(feedbackPacket.getServerId(), serverName);
CLIENTS.add(client);
}
if (!client.compareId(feedbackPacket.getServerId()))
client.setId(feedbackPacket.getServerId());
if (client.hasSentFeedback())
return;
client.setFeedback(true);
client.syncTime();
SERVER_DATA_SYNC_COUNT++;
CommunicationPackets.BackendDataPacket backendDataPacket = new CommunicationPackets.BackendDataPacket(Storage.TOKEN, serverId, serverName);
sendPacket(client, backendDataPacket);
return;
}
if (packet instanceof CommunicationPackets.PacketBundle) {
CommunicationPackets.PacketBundle packetBundle = (CommunicationPackets.PacketBundle) packet;
if (!packetBundle.isToken(Storage.TOKEN) || !packetBundle.isId(SERVER_ID.toString()))
return;
Storage.USE_VELOCITY = packetBundle.isVelocity();
LAST_BUKKIT_SYNC = System.currentTimeMillis();
BukkitLoader.synchronize(packetBundle);
}
}
public static void syncData() {
syncData(null);
}
public static void syncData(String serverId) {
if (!Reflection.isProxyServer() || Storage.ConfigSections.Settings.DISABLE_SYNC.DISABLED)
return;
LAST_DATA_UPDATE = System.currentTimeMillis();
ClientInfo clientInfo;
if(serverId == null) {
SERVER_DATA_SYNC_COUNT = 0;
CLIENTS.forEach(currentClient -> syncData(currentClient.getId()));
return;
} else {
clientInfo = getClientById(serverId);
if (clientInfo != null)
clientInfo.setFeedback(false);
SERVER_DATA_SYNC_COUNT = Math.max(0, SERVER_DATA_SYNC_COUNT -1);
}
CommunicationPackets.CommandsPacket commandsPacket = new CommunicationPackets.CommandsPacket();
CommunicationPackets.GroupsPacket groupsPacket;
CommunicationPackets.PacketBundle bundle;
List<String> commands = new ArrayList<>();
String tempServerName = "";
if (clientInfo != null && clientInfo.getName() != null) {
tempServerName = clientInfo.getName();
if (!Storage.Blacklist.isIgnoredServer(tempServerName))
commands.addAll(Storage.Blacklist.getBlacklist().getCommands());
List<GeneralBlacklist> serverBlacklists = Storage.Blacklist.getServerBlacklists(clientInfo.getName());
serverBlacklists.stream().filter(serverBlacklist ->
serverBlacklist != null && serverBlacklist.getCommands() != null
).forEach(serverBlacklist ->
commands.addAll(serverBlacklist.getCommands())
public static void sendIdentityRequest() {
get().send2Proxy(
new CommunicationPackets.Backend2Proxy.IdentityRequestPacket(get().getId())
);
}
final String serverName = tempServerName;
List<TinyGroup> groups = new ArrayList<>();
TinyGroup tinyGroup;
for (Group group : GroupManager.getGroups()) {
if (groups.stream().anyMatch(cTG -> cTG.getGroupName().equals(group.getGroupName())))
continue;
tinyGroup = new TinyGroup(group.getGroupName(), group.getPriority(), group.getAllCommands(serverName));
for (GroupBlacklist groupBlacklist : group.getAllServerGroupBlacklist(serverName))
tinyGroup.addAll(groupBlacklist.getCommands());
groups.add(tinyGroup);
public static void sendKeepAliveRequest() {
get().send2Proxy(
new CommunicationPackets.Backend2Proxy.KeepAlivePacket()
);
}
groupsPacket = new CommunicationPackets.GroupsPacket(groups);
commandsPacket.setTurnBlacklistToWhitelist(Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED);
commandsPacket.setCommands(commands);
bundle = new CommunicationPackets.PacketBundle(Storage.TOKEN, serverId, commandsPacket, groupsPacket);
clientInfo.sendBytes(CommunicationPackets.convertToBytes(bundle));
PATEventHandler.callSentSyncEvents(bundle, serverName);
}
public static void sendRequest() {
if(System.currentTimeMillis() - LAST_SENT_REQUEST >= 5000) {
LAST_SENT_REQUEST = System.currentTimeMillis();
sendPacket(new CommunicationPackets.RequestPacket(Storage.TOKEN, SERVER_ID.toString()));
public static class Proxy2Backend {
private Proxy2Backend() {}
// Update commands for all players
public static void sendUpdateCommand() {
get().send2AllClients(
new CommunicationPackets.Proxy2Backend.UpdatePacket(null)
);
}
// Update commands for a certain player.
public static void sendUpdateCommand(UUID playerId, String serverName) {
final ClientInfo clientInfo = get().clients.get(serverName);
if (clientInfo == null) return;
clientInfo.send(
new CommunicationPackets.Proxy2Backend.UpdatePacket(playerId)
);
}
public static void sendDataSync() {
Communicator.get().lastSync = System.currentTimeMillis();
Communicator.get().send2AllClients(
Communicator.get().constructDataSyncPacket()
);
}
// Sync data for one server
public static void sendDataSync(String serverName) {
final ClientInfo clientInfo = get().clients.get(serverName);
if (clientInfo == null) return;
clientInfo.send(
Communicator.get().constructDataSyncPacket()
);
}
// Sync data for all registered clients.
public static void sendConsoleMessage(String serverName, String message) {
final ClientInfo clientInfo = get().clients.get(serverName);
if (clientInfo == null) return;
clientInfo.send(
new CommunicationPackets.Proxy2Backend.ConsoleMessagePacket(message)
);
}
public static void sendExecutePlayerCommand(String serverName, UUID playerId, String command) {
final ClientInfo clientInfo = get().clients.get(serverName);
if (clientInfo == null) return;
clientInfo.send(
new CommunicationPackets.Proxy2Backend.ExecutePlayerCommandPacket(playerId, command)
);
}
public static void sendExecuteConsoleCommand(String serverName, String command) {
final ClientInfo clientInfo = get().clients.get(serverName);
if (clientInfo == null) return;
clientInfo.send(
new CommunicationPackets.Proxy2Backend.ExecuteConsoleCommandPacket(command)
);
}
public static void sendNotification(UUID playerId, String serverName, String command) {
if (!Storage.ConfigSections.Settings.FORWARD_CONSOLE_NOTIFICATIONS.ENABLED) {
return;
}
final ClientInfo clientInfo = get().clients.get(serverName);
if (clientInfo == null) return;
clientInfo.send(
new CommunicationPackets.Proxy2Backend.NotificationPacket(playerId, command)
);
}
}
public static void sendPermissionReset() {
if(Reflection.isProxyServer())
sendPacket(new CommunicationPackets.ForcePermissionResetPacket(Storage.TOKEN));
private final Client client;
private final UUID id = UUID.randomUUID();
// Server name, ClientInfo
private final Map<String, ClientInfo> clients = new HashMap<>();
private final ExpireCache<String, ClientInfo> pendingClients = new ExpireCache<>(2, TimeUnit.SECONDS);
private long lastReceivedKeepAliveResponse = System.currentTimeMillis();
private long lastSync = System.currentTimeMillis();
private Communicator(final Client client) {
this.client = client;
}
public static void sendUpdateCommand() {
sendPacket(new CommunicationPackets.UpdateCommandsPacket(Storage.TOKEN));
// BACKEND -> PROXY
public void handleB2PPacket(String serverName, CommunicationPackets.PATPacket incomingPacket) {
if (!incomingPacket.tokenMatches(Storage.TOKEN)) {
return;
}
if (incomingPacket instanceof CommunicationPackets.Backend2Proxy.KeepAlivePacket packet) {
final ClientInfo clientInfo = clients.get(serverName);
if (clientInfo == null) return;
clientInfo.updateKeepAliveTime();
clientInfo.send(new CommunicationPackets.Proxy2Backend.KeepAliveResponsePacket());
return;
}
if (incomingPacket instanceof CommunicationPackets.Backend2Proxy.IdentityRequestPacket packet) {
final ClientInfo registeredClientInfo = clients.get(serverName);
final boolean exist = registeredClientInfo != null;
final boolean same = exist && registeredClientInfo.getId().equals(packet.serverId());
if (!same) {
final ClientInfo clientInfo = Reflection.isVelocityServer()
? new VelocityClientInfo(packet.serverId(), serverName)
: new BungeeClientInfo(packet.serverId(), serverName);
pendingClients.put(serverName, clientInfo);
clientInfo.send(new CommunicationPackets.Proxy2Backend.IdentityPacket(packet.serverId(), serverName));
} else {
registeredClientInfo.send(new CommunicationPackets.Proxy2Backend.KeepAliveResponsePacket());
registeredClientInfo.send(new CommunicationPackets.Proxy2Backend.IdentityPacket(packet.serverId(), serverName));
}
return;
}
if (incomingPacket instanceof CommunicationPackets.Backend2Proxy.IdentityResponsePacket packet) {
final ClientInfo clientInfo = pendingClients.get(serverName);
if (clientInfo != null && clientInfo.getId().equals(packet.serverId())) {
clientInfo.setId(packet.serverId());
pendingClients.remove(serverName);
clients.put(serverName, clientInfo);
clientInfo.send(new CommunicationPackets.Proxy2Backend.KeepAliveResponsePacket());
clientInfo.send( constructDataSyncPacket() );
clientInfo.updateSyncTime();
}
return;
}
if (incomingPacket instanceof CommunicationPackets.Backend2Proxy.DataSyncReceivedPacket packet) {
final ClientInfo clientInfo = clients.get(serverName);
if (clientInfo == null) return;
clientInfo.updateSyncTime();
}
}
public static void sendUpdateCommand(UUID targetUUID) {
sendPacket(new CommunicationPackets.UpdateCommandsPacket(Storage.TOKEN, targetUUID));
// PROXY -> BACKEND
public void handleP2BPacket(CommunicationPackets.PATPacket incomingPacket) {
if (!incomingPacket.tokenMatches(Storage.TOKEN)) {
return;
}
if (incomingPacket instanceof CommunicationPackets.Proxy2Backend.KeepAliveResponsePacket packet) {
lastReceivedKeepAliveResponse = System.currentTimeMillis();
BackendUpdater.receivedKeepAlivePacket();
return;
}
if (incomingPacket instanceof CommunicationPackets.Proxy2Backend.IdentityPacket packet) {
Storage.SERVER_NAME = packet.serverName();
send2Proxy(new CommunicationPackets.Backend2Proxy.IdentityResponsePacket(id));
return;
}
if (incomingPacket instanceof CommunicationPackets.Proxy2Backend.DataSyncPacket packet) {
lastSync = System.currentTimeMillis();
send2Proxy(new CommunicationPackets.Backend2Proxy.DataSyncReceivedPacket());
BukkitLoader.handleDataSyncPacket(packet);
return;
}
if (incomingPacket instanceof CommunicationPackets.Proxy2Backend.UpdatePacket packet) {
BukkitLoader.handleUpdateCommandsPacket(packet);
return;
}
if (incomingPacket instanceof CommunicationPackets.Proxy2Backend.NotificationPacket packet) {
BukkitLoader.handleNotificationPacket(packet);
return;
}
if (incomingPacket instanceof CommunicationPackets.Proxy2Backend.ConsoleMessagePacket packet) {
BukkitLoader.handleConsoleMessagePacket(packet);
return;
}
if (incomingPacket instanceof CommunicationPackets.Proxy2Backend.ExecutePlayerCommandPacket packet) {
BukkitLoader.handlePlayerExecuteCommandPacket(packet);
return;
}
if (incomingPacket instanceof CommunicationPackets.Proxy2Backend.ExecuteConsoleCommandPacket packet) {
BukkitLoader.handleConsoleExecuteCommandPacket(packet);
return;
}
}
public static void sendFeedback() {
sendPacket(new CommunicationPackets.FeedbackPacket(Storage.TOKEN, SERVER_ID.toString()));
private void send2Proxy(CommunicationPackets.PATPacket packet) {
if (Reflection.isProxyServer()) {
Logger.warning("Cannot send B2P packet as proxy!");
return;
}
client.send(packet);
}
public static Client getClient() {
return CLIENT;
private void send2Client(ClientInfo clientInfo, CommunicationPackets.PATPacket packet) {
if (!Reflection.isProxyServer()) {
Logger.warning("Cannot send P2B packet as backend!");
return;
}
if (clientInfo == null || Storage.ConfigSections.Settings.DISABLE_SYNC.DISABLED) {
return;
}
clientInfo.send(packet);
}
public static ClientInfo getClientById(String id) {
return CLIENTS.isEmpty() ? null : CLIENTS.stream().filter(client -> client != null && client.compareId(id)).findFirst().orElse(null);
private void send2AllClients(CommunicationPackets.PATPacket packet) {
if (!Reflection.isProxyServer()) {
Logger.warning("Cannot send P2B packet as backend!");
return;
}
if (Storage.ConfigSections.Settings.DISABLE_SYNC.DISABLED) {
return;
}
getClients().forEach(clientInfo -> {
clientInfo.send(packet);
});
}
public static ClientInfo getClientByName(String name) {
return CLIENTS.isEmpty() ? null : CLIENTS.stream().filter(client -> client != null && client.getName().equalsIgnoreCase(name)).findFirst().orElse(null);
private CommunicationPackets.Proxy2Backend.DataSyncPacket constructDataSyncPacket() {
return new CommunicationPackets.Proxy2Backend.DataSyncPacket(
new CommunicationPackets.Proxy2Backend.DataSyncPacket.Messages(
Storage.ConfigSections.Messages.PREFIX.PREFIX
),
new CommunicationPackets.Proxy2Backend.DataSyncPacket.AutoLowerCase(
Storage.ConfigSections.Settings.AUTO_LOWERCASE_COMMANDS.ENABLED
),
new CommunicationPackets.Proxy2Backend.DataSyncPacket.UnknownCommand(
Storage.ConfigSections.Settings.CUSTOM_UNKNOWN_COMMAND.ENABLED,
Storage.ConfigSections.Settings.CUSTOM_UNKNOWN_COMMAND.MESSAGE
)
);
}
public void reload() {
this.client.reload();
}
public UUID getClientId(String serverName) {
final ClientInfo clientInfo = clients.get(serverName);
if (clientInfo == null) return null;
return clientInfo.getId();
}
public boolean hasConnectedClients() {
return !clients.isEmpty();
}
public Set<ClientInfo> getClients() {
return new HashSet<>(clients.values());
}
public UUID getId() {
return id;
}
public long getLastReceivedKeepAliveResponse() {
return lastReceivedKeepAliveResponse;
}
public long getLastSync() {
return lastSync;
}
}
@@ -1,58 +1,62 @@
package de.rayzs.pat.api.communication.client;
import de.rayzs.pat.utils.CommunicationPackets;
import de.rayzs.pat.utils.TimeConverter;
import java.util.UUID;
public abstract class ClientInfo {
private String id, name;
private UUID id;
private String serverName;
private boolean sentFeedback = false;
private long syncTime = System.currentTimeMillis();
private long syncTime = System.currentTimeMillis(),
keepAliveTime = System.currentTimeMillis();
public ClientInfo(String serverId) {
this.id = serverId;
public ClientInfo(UUID id) {
this.id = id;
}
public ClientInfo(String serverId, String name) {
this.id = serverId;
this.name = name;
public ClientInfo(UUID id, String name) {
this.id = id;
this.serverName = name;
}
public abstract void sendBytes(byte[] bytes);
public abstract void send(CommunicationPackets.PATPacket packet);
public void setName(String name) {
this.name = name;
public void setServerName(String name) {
this.serverName = name;
}
public void setId(String serverId) {
this.id = serverId;
public void setId(UUID id) {
this.id = id;
}
public String getName() {
return name;
public String getServerName() {
return serverName;
}
public boolean compareId(String id) {
return this.id.equals(id);
}
public void syncTime() {
public void updateSyncTime() {
syncTime = System.currentTimeMillis();
}
public String getSyncTime() {
public void updateKeepAliveTime() {
keepAliveTime = System.currentTimeMillis();
}
public boolean isAlive() {
return System.currentTimeMillis() - keepAliveTime > 5000;
}
public String getFormattedSyncTime() {
return TimeConverter.calcAndGetTime(syncTime);
}
public void setFeedback(boolean state) {
this.sentFeedback = state;
public String getFormattedLastReceivedKeepAlivePacketTime() {
return TimeConverter.calcAndGetTime(keepAliveTime);
}
public boolean hasSentFeedback() {
return sentFeedback;
}
public String getId() {
public UUID getId() {
return id;
}
}
@@ -2,33 +2,34 @@ package de.rayzs.pat.api.communication.client.impl;
import de.rayzs.pat.api.communication.client.ClientInfo;
import de.rayzs.pat.api.communication.Client;
import de.rayzs.pat.plugin.BungeeLoader;
import de.rayzs.pat.plugin.logger.Logger;
import de.rayzs.pat.utils.CommunicationPackets;
import net.md_5.bungee.api.ProxyServer;
import net.md_5.bungee.api.config.ServerInfo;
import java.util.UUID;
public class BungeeClientInfo extends ClientInfo {
public BungeeClientInfo(String serverId) {
super(serverId);
public BungeeClientInfo(UUID id) {
super(id);
}
public BungeeClientInfo(String serverId, String name) {
super(serverId, name);
public BungeeClientInfo(UUID id, String name) {
super(id, name);
}
@Override
public void sendBytes(byte[] bytes) {
try {
ProxyServer server = BungeeLoader.getPlugin().getProxy();
public void send(CommunicationPackets.PATPacket packet) {
final byte[] preparedPacket = CommunicationPackets.preparePacket(packet, getId());
server.getServers().entrySet().stream().filter(entry ->
entry.getKey().equalsIgnoreCase(getName())
).forEach(entry ->
entry.getValue().sendData(Client.CHANNEL_NAME, bytes)
);
if (preparedPacket == null) {
return;
}
} catch (NoClassDefFoundError exception) {
Logger.warning("Failed to send data to backend servers! :c");
final ServerInfo serverInfo = ProxyServer.getInstance().getServerInfo(getServerName());
if (serverInfo != null) {
serverInfo.sendData(Client.CHANNEL_NAME, preparedPacket);
}
}
}
@@ -1,25 +1,36 @@
package de.rayzs.pat.api.communication.client.impl;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import de.rayzs.pat.api.communication.impl.VelocityClient;
import de.rayzs.pat.api.communication.client.ClientInfo;
import de.rayzs.pat.plugin.VelocityLoader;
import de.rayzs.pat.utils.CommunicationPackets;
import java.util.Optional;
import java.util.UUID;
public class VelocityClientInfo extends ClientInfo {
public VelocityClientInfo(String serverId) {
super(serverId);
public VelocityClientInfo(UUID id) {
super(id);
}
public VelocityClientInfo(String serverId, String name) {
super(serverId, name);
public VelocityClientInfo(UUID id, String name) {
super(id, name);
}
@Override
public void sendBytes(byte[] bytes) {
VelocityLoader.getServer().getAllServers().stream().filter(server ->
server.getServerInfo().getName().equalsIgnoreCase(getName())
).forEach(server ->
server.sendPluginMessage(VelocityClient.getIdentifier(), bytes)
);
public void send(CommunicationPackets.PATPacket packet) {
final byte[] preparedPacket = CommunicationPackets.preparePacket(packet, getId());
if (preparedPacket == null) {
return;
}
final Optional<RegisteredServer> optServer = VelocityLoader.getServer().getServer(getServerName());
optServer.ifPresent(registeredServer -> {
registeredServer.sendPluginMessage(VelocityClient.getIdentifier(), preparedPacket);
});
}
}
@@ -8,48 +8,96 @@ import de.rayzs.pat.plugin.BukkitLoader;
import de.rayzs.pat.api.communication.*;
import org.bukkit.entity.Player;
import org.bukkit.*;
import java.util.Iterator;
public class BukkitClient implements Client, PluginMessageListener {
private static final Server SERVER = Bukkit.getServer();
private boolean registered = false;
public BukkitClient() {
reload();
}
@Override
public void reload() {
if (!Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) {
if (registered) {
unregister();
}
return;
}
if (!registered) {
register();
}
}
private void register() {
registered = true;
SERVER.getMessenger().registerIncomingPluginChannel(BukkitLoader.getPlugin(), CHANNEL_NAME, this);
SERVER.getMessenger().registerOutgoingPluginChannel(BukkitLoader.getPlugin(), CHANNEL_NAME);
}
private void unregister() {
registered = false;
SERVER.getMessenger().unregisterIncomingPluginChannel(BukkitLoader.getPlugin(), CHANNEL_NAME, this);
SERVER.getMessenger().unregisterOutgoingPluginChannel(BukkitLoader.getPlugin(), CHANNEL_NAME);
}
@Override
public void send(Object packet) {
try {
public void send(CommunicationPackets.PATPacket packet) {
final byte[] preparedPacket = CommunicationPackets.preparePacket(packet);
SERVER.sendPluginMessage(BukkitLoader.getPlugin(), CHANNEL_NAME, CommunicationPackets.convertToBytes(packet));
} catch (Throwable throwable) {
throwable.printStackTrace();
if (preparedPacket == null) {
return;
}
final Player carrier = selectCarrier();
if (carrier == null) {
return;
}
PATScheduler.execute(() -> {
if (!carrier.isOnline()) {
return;
}
try {
carrier.sendPluginMessage(BukkitLoader.getPlugin(), CHANNEL_NAME, preparedPacket);
} catch (Exception exception) {
exception.printStackTrace();
}
}, carrier);
}
@Override
public void onPluginMessageReceived(String channel, Player player, byte[] bytes) {
if (!channel.equals(CHANNEL_NAME))
if (!channel.equals(CHANNEL_NAME)) {
return;
}
try {
Object packetObj = CommunicationPackets.buildFromBytes(bytes);
final Object packetObj = CommunicationPackets.readPacket(bytes);
if (!CommunicationPackets.isPacket(packetObj))
if (!CommunicationPackets.isP2BPacket(packetObj)) {
return;
}
PATScheduler.createScheduler(() -> Communicator.receiveInformation("proxy", packetObj));
PATScheduler.createScheduler(() -> Communicator.get().handleP2BPacket((CommunicationPackets.PATPacket) packetObj));
} catch (Throwable throwable) {
throwable.printStackTrace();
} catch (Exception exception) {
exception.printStackTrace();
}
}
private Player selectCarrier() {
final Iterator<? extends Player> iterator = SERVER.getOnlinePlayers().iterator();
return iterator.hasNext() ? iterator.next() : null;
}
}
@@ -11,6 +11,8 @@ import de.rayzs.pat.plugin.BungeeLoader;
import de.rayzs.pat.api.communication.*;
import net.md_5.bungee.api.ProxyServer;
import java.util.UUID;
public class BungeeClient implements Client, Listener {
private static final ProxyServer SERVER = ProxyServer.getInstance();
@@ -26,15 +28,22 @@ public class BungeeClient implements Client, Listener {
}
@Override
public void send(Object packet) {
public void reload() {}
@Override
public void send(CommunicationPackets.PATPacket packet) {
final byte[] preparedPacket = CommunicationPackets.preparePacket(packet);
if (preparedPacket == null) {
return;
}
for (ServerInfo serverInfo : ProxyServer.getInstance().getServers().values()) {
try {
serverInfo.sendData(CHANNEL_NAME, CommunicationPackets.convertToBytes(packet));
} catch (Throwable throwable) {
throwable.printStackTrace();
serverInfo.sendData(CHANNEL_NAME, preparedPacket);
} catch (Exception exception) {
exception.printStackTrace();
}
}
@@ -42,18 +51,26 @@ public class BungeeClient implements Client, Listener {
@EventHandler
public void onQueryReceive(PluginMessageEvent event) {
if (!event.getTag().equalsIgnoreCase(CHANNEL_NAME))
if (!event.getTag().equalsIgnoreCase(CHANNEL_NAME)) {
return;
}
final Server server = (Server) event.getSender();
final String serverName = server.getInfo().getName();
final UUID clientId = Communicator.get().getClientId(serverName);
if (!CommunicationPackets.isInitialPacket(event.getData()) && clientId == null) {
return;
}
try {
Object packetObj = CommunicationPackets.buildFromBytes(event.getData());
if (!CommunicationPackets.isPacket(packetObj))
Object packetObj = CommunicationPackets.readPacket(event.getData(), clientId);
if (!CommunicationPackets.isB2PPacket(packetObj)) {
return;
}
Server server = (Server) event.getSender();
Communicator.receiveInformation(server.getInfo().getName(), packetObj);
Communicator.get().handleB2PPacket(serverName, (CommunicationPackets.PATPacket) packetObj);
} catch (Throwable throwable) {
throwable.printStackTrace();
@@ -9,6 +9,7 @@ import com.velocitypowered.api.event.Subscribe;
import de.rayzs.pat.plugin.VelocityLoader;
import de.rayzs.pat.api.communication.*;
import com.velocitypowered.api.proxy.*;
import java.util.UUID;
public class VelocityClient implements Client {
@@ -26,15 +27,23 @@ public class VelocityClient implements Client {
}
@Override
public void send(Object packet) {
public void reload() {}
@Override
public void send(CommunicationPackets.PATPacket packet) {
final byte[] preparedPacket = CommunicationPackets.preparePacket(packet);
if (preparedPacket == null) {
return;
}
for (RegisteredServer registeredServer : SERVER.getAllServers()) {
try {
registeredServer.sendPluginMessage(IDENTIFIER, CommunicationPackets.convertToBytes(packet));
} catch (Throwable throwable) {
throwable.printStackTrace();
registeredServer.sendPluginMessage(IDENTIFIER, preparedPacket);
} catch (Exception exception) {
exception.printStackTrace();
}
}
@@ -42,16 +51,26 @@ public class VelocityClient implements Client {
@Subscribe
public void onQueryReceive(PluginMessageEvent event) {
if (event.getIdentifier() != IDENTIFIER)
if (event.getIdentifier() != IDENTIFIER) {
return;
}
Object packetObj = CommunicationPackets.buildFromBytes(event.getData());
final ServerConnection server = (ServerConnection) event.getSource();
final String serverName = server.getServerInfo().getName();
final UUID clientId = Communicator.get().getClientId(serverName);
if (!CommunicationPackets.isPacket(packetObj))
if (!CommunicationPackets.isInitialPacket(event.getData()) && clientId == null) {
return;
}
Object packetObj = CommunicationPackets.readPacket(event.getData(), clientId);
if (!CommunicationPackets.isB2PPacket(packetObj)) {
return;
}
Communicator.get().handleB2PPacket(serverName, (CommunicationPackets.PATPacket) packetObj);
ServerConnection server = (ServerConnection) event.getSource();
Communicator.receiveInformation(server.getServerInfo().getName(), packetObj);
}
public static MinecraftChannelIdentifier getIdentifier() {
@@ -88,8 +88,8 @@ public class PATEventHandler {
return event;
}
public static SentSyncEvent callSentSyncEvents(CommunicationPackets.PacketBundle packetBundle, String serverName) {
SentSyncEvent event = EmptyEvent.createEmptySentSyncEvent(packetBundle, serverName);
public static SentSyncEvent callSentSyncEvents(CommunicationPackets.Proxy2Backend.DataSyncPacket dataSyncPacket, String serverName) {
SentSyncEvent event = EmptyEvent.createEmptySentSyncEvent(dataSyncPacket, serverName);
for (PATEvent patEvent : EVENTS) {
if(patEvent instanceof SentSyncEvent) {
@@ -101,8 +101,8 @@ public class PATEventHandler {
return event;
}
public static ReceiveSyncEvent callReceiveSyncEvents(CommunicationPackets.PacketBundle packetBundle) {
ReceiveSyncEvent event = EmptyEvent.createEmptyReceiveSyncEvent(packetBundle);
public static ReceiveSyncEvent callReceiveSyncEvents(CommunicationPackets.Proxy2Backend.DataSyncPacket dataSyncPacket) {
ReceiveSyncEvent event = EmptyEvent.createEmptyReceiveSyncEvent(dataSyncPacket);
for (PATEvent patEvent : EVENTS) {
if(patEvent instanceof ReceiveSyncEvent) {
@@ -133,8 +133,8 @@ public class PATEventHandler {
};
}
public static SentSyncEvent createEmptySentSyncEvent(CommunicationPackets.PacketBundle packetBundle, String serverName) {
return new SentSyncEvent(null, packetBundle, serverName) {
public static SentSyncEvent createEmptySentSyncEvent(CommunicationPackets.Proxy2Backend.DataSyncPacket dataSyncPacket, String serverName) {
return new SentSyncEvent(null, dataSyncPacket, serverName) {
@Override
public void handle(SentSyncEvent event) {
@@ -142,8 +142,8 @@ public class PATEventHandler {
};
}
public static ReceiveSyncEvent createEmptyReceiveSyncEvent(CommunicationPackets.PacketBundle packetBundle) {
return new ReceiveSyncEvent(null, packetBundle) {
public static ReceiveSyncEvent createEmptyReceiveSyncEvent(CommunicationPackets.Proxy2Backend.DataSyncPacket dataSyncPacket) {
return new ReceiveSyncEvent(null, dataSyncPacket) {
@Override
public void handle(ReceiveSyncEvent event) {
@@ -5,19 +5,19 @@ import de.rayzs.pat.api.event.PATEvent;
public abstract class ReceiveSyncEvent extends PATEvent<ReceiveSyncEvent> {
private final CommunicationPackets.PacketBundle packetBundle;
private final CommunicationPackets.Proxy2Backend.DataSyncPacket dataSyncPacket;
public ReceiveSyncEvent() {
super(null);
this.packetBundle = null;
this.dataSyncPacket = null;
}
public ReceiveSyncEvent(Object senderObj, CommunicationPackets.PacketBundle packetBundle) {
public ReceiveSyncEvent(Object senderObj, CommunicationPackets.Proxy2Backend.DataSyncPacket dataSyncPacket) {
super(senderObj);
this.packetBundle = packetBundle;
this.dataSyncPacket = dataSyncPacket;
}
public CommunicationPackets.PacketBundle getPacketBundle() {
return packetBundle;
public CommunicationPackets.Proxy2Backend.DataSyncPacket getDataSyncPacket() {
return dataSyncPacket;
}
}
@@ -5,18 +5,18 @@ import de.rayzs.pat.api.event.PATEvent;
public abstract class SentSyncEvent extends PATEvent<SentSyncEvent> {
private final CommunicationPackets.PacketBundle packetBundle;
private final CommunicationPackets.Proxy2Backend.DataSyncPacket dataSyncPacket;
private final String serverName;
public SentSyncEvent() {
super(null);
this.packetBundle = null;
this.dataSyncPacket = null;
this.serverName = null;
}
public SentSyncEvent(Object senderObj, CommunicationPackets.PacketBundle packetBundle, String serverName) {
public SentSyncEvent(Object senderObj, CommunicationPackets.Proxy2Backend.DataSyncPacket dataSyncPacket, String serverName) {
super(senderObj);
this.packetBundle = packetBundle;
this.dataSyncPacket = dataSyncPacket;
this.serverName = serverName;
}
@@ -24,7 +24,7 @@ public abstract class SentSyncEvent extends PATEvent<SentSyncEvent> {
return serverName;
}
public CommunicationPackets.PacketBundle getPacketBundle() {
return packetBundle;
public CommunicationPackets.Proxy2Backend.DataSyncPacket getDataSyncPacket() {
return dataSyncPacket;
}
}
@@ -23,7 +23,7 @@ public class BukkitPacketAnalyzer {
private static final String HANDLER_NAME = "pat-bukkit-handler", PIPELINE_NAME = "packet_handler";
private static final BukkitPacketHandler PACKET_HANDLER = Reflection.getMinor() >= 16 ? new ModernPacketHandler() : new LegacyPacketHandler();
private static final BukkitPacketHandler PACKET_HANDLER = Reflection.isAtLeast(1, 16) ? new ModernPacketHandler() : new LegacyPacketHandler();
private static final BukkitPacketHandler COMMANDS_NODE_HANDLER = new ModernCommandsNodeHandler();
private static final HashMap<Player, String> PLAYER_INPUT_CACHE = new HashMap<>();
@@ -65,20 +65,19 @@ public class BukkitPacketAnalyzer {
BukkitPacketAnalyzer.INJECTED_PLAYERS.put(player.getUniqueId(), channel);
} catch (IndexOutOfBoundsException indexOutOfBoundsException) {
Reflection.toggleInjectionMethod();
Logger.info("Injection failed. Switching to secondary injection method.");
boolean success = inject(player);
if (success) {
Logger.info("Secondary injection method was successful.");
} else {
Logger.warning("Secondary injection method failed!");
if (!success) {
Logger.warning("Both injection methods failed! Please report this back to me on my Discord! (https://www.rayzs.de/discord)");
}
return success;
} catch (Exception exception) {
exception.printStackTrace();
if (!Storage.ConfigSections.Settings.INJECTION_FAILED.SUPPRESS_EXCEPTIONS) {
exception.printStackTrace();
}
return false;
}
@@ -40,6 +40,8 @@ public class ModernPacketHandler implements BukkitPacketHandler {
}
String text = (String) stringField.get(packetObj);
if (!text.isBlank() && text.charAt(0) != '/') text = '/' + text;
if (Storage.ConfigSections.Settings.PATCH_EXPLOITS.isMalicious(text)) {
MessageTranslator.send(
Bukkit.getConsoleSender(),
@@ -103,7 +105,7 @@ public class ModernPacketHandler implements BukkitPacketHandler {
if ((input.isEmpty() || cancelsBeforeHand) && Reflection.isWeird())
return false;
if (spaces >= 1 && cancelsBeforeHand || !BukkitLoader.isLoaded()) {
if (spaces >= 1 && cancelsBeforeHand) {
suggestions.clear();
return true;
}
@@ -154,7 +156,7 @@ public class ModernPacketHandler implements BukkitPacketHandler {
}
if (Reflection.getMinor() < 17) {
if (Reflection.isBefore(1, 17)) {
Field suggestionsField = Reflection.getFieldsByType(packetObj.getClass(), "Suggestions", Reflection.SearchOption.ENDS).get(0);
if (suggestionsField == null) return false;
suggestionObj = suggestionsField.get(packetObj);
@@ -176,7 +178,7 @@ public class ModernPacketHandler implements BukkitPacketHandler {
return false;
}
if(spaces >= 1 && cancelsBeforeHand || !BukkitLoader.isLoaded()) {
if(spaces >= 1 && cancelsBeforeHand) {
suggestions.getList().clear();
return true;
}
@@ -9,6 +9,7 @@ import com.mojang.brigadier.tree.CommandNode;
import com.mojang.brigadier.tree.RootCommandNode;
import de.rayzs.pat.api.brand.CustomServerBrand;
import de.rayzs.pat.api.communication.Communicator;
import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.plugin.logger.Logger;
import de.rayzs.pat.plugin.subarguments.SubArguments;
@@ -102,8 +103,11 @@ public class BungeePacketAnalyzer {
channel.pipeline().addAfter(BungeePacketAnalyzer.PIPELINE_NAME, BungeePacketAnalyzer.HANDLER_NAME, new PacketDecoder(player));
BungeePacketAnalyzer.INJECTED_PLAYERS.put(player, channel);
} catch (Throwable throwable) {
throwable.printStackTrace();
} catch (Exception exception) {
if (!Storage.ConfigSections.Settings.INJECTION_FAILED.SUPPRESS_EXCEPTIONS) {
exception.printStackTrace();
}
return false;
}
@@ -220,6 +224,10 @@ public class BungeePacketAnalyzer {
}
public static void sendCommandsPacket() {
if (!Communicator.get().hasConnectedClients()) {
return;
}
for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) {
if (player.getPendingConnection().getVersion() < 754)
continue;
@@ -118,8 +118,11 @@ public class VelocityPacketAnalyzer {
Logger.warning("Failed to find 'handler' inside player pipeline! (name=" + player.getUsername() + ", uuid=" + player.getUniqueId() + ", version=" + player.getProtocolVersion() + ", brand=" + player.getClientBrand() + " )");
return false;
} catch (Throwable throwable) {
throwable.printStackTrace();
} catch (Exception exception) {
if (!Storage.ConfigSections.Settings.INJECTION_FAILED.SUPPRESS_EXCEPTIONS) {
exception.printStackTrace();
}
return false;
}
@@ -60,12 +60,12 @@ public class Storage {
public static final List<UUID> NOTIFY_PLAYERS = new ArrayList<>();
public static String 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 Object PLUGIN_OBJECT;
public static boolean USE_PLACEHOLDERAPI = false, USE_PAPIPROXYBRIDGE = false, USE_VIAVERSION = false, USE_VELOCITY = false, USE_SIMPLECLOUD;
public static long LAST_SYNC = System.currentTimeMillis();
public static boolean USE_PLACEHOLDERAPI = false, USE_PAPIPROXYBRIDGE = false, USE_VIAVERSION = false;
private final static ExpireCache<UUID, String> TEMP_PLAYER_SERVER_CACHE = new ExpireCache<>(1, TimeUnit.SECONDS);
private static PermissionPlugin PERMISSION_PLUGIN = PermissionPlugin.NONE;
public static void initialize(PluginLoader loader, String currentVersion) {
@@ -81,6 +81,7 @@ public class Storage {
PERMISSION_PLUGIN = permissionPlugin;
}
public static void broadcastPermissionsPluginNotice() {
if (Storage.getPermissionPlugin() != PermissionPlugin.NONE) {
return;
@@ -99,9 +100,9 @@ public class Storage {
loadToken();
if (TOKEN != null && !TOKEN.isEmpty()) {
int tokenLength = TOKEN.length(), cutIndex = Math.max(1, tokenLength - 3);
String censoredTokenDisplay = "*".repeat(cutIndex) + TOKEN.substring(cutIndex);
Logger.info("Token found! (" + censoredTokenDisplay + ")");
int tokenLength = TOKEN.length(), cutIndex = Math.max(1, tokenLength - 2);
CENSORED_TOKEN = TOKEN.charAt(0) + "*".repeat(cutIndex) + TOKEN.substring(cutIndex);
Logger.info("Token found! (" + CENSORED_TOKEN + ")");
}
if (loadBlacklist) Blacklist.loadAll();
@@ -178,14 +179,18 @@ public class Storage {
GroupManager.initialize();
if (!proxy) {
BackendUpdater.stop();
BackendUpdater.start();
Communicator.get().reload();
BackendUpdater.restart();
}
if (!backend) {
Storage.handleChange();
}
if (proxy) {
Communicator.Proxy2Backend.sendDataSync();
}
ConfigUpdater.broadcastMissingParts();
Storage.getLoader().handleReload();
}
@@ -249,22 +254,21 @@ public class Storage {
}
GroupManager.clearServerGroupBlacklists();
Communicator.syncData();
Storage.getLoader().updateCommandCache();
Communicator.sendPermissionReset();
if (!Reflection.isVelocityServer()) {
BungeePacketAnalyzer.sendCommandsPacket();
}
Communicator.Proxy2Backend.sendUpdateCommand();
return;
}
getLoader().handleReload();
PermissionUtil.reloadPermissions();
if (Reflection.getMinor() < 13) {
if (Reflection.isBefore(1, 13)) {
final List<UUID> playerIds = Storage.getLoader().getPlayerIds();
final List<String> commands = new ArrayList<>(Blacklist.BLACKLIST.getCommands());
@@ -279,6 +283,18 @@ public class Storage {
}
}
public static void tempCachePlayerToServer(UUID playerId, String server) {
TEMP_PLAYER_SERVER_CACHE.put(playerId, server);
}
public static void getTempCachedPlayerToServer(UUID playerId, String server) {
TEMP_PLAYER_SERVER_CACHE.put(playerId, server);
}
public static String getCachedPlayerServername(UUID playerId) {
return TEMP_PLAYER_SERVER_CACHE.get(playerId);
}
// Quickly updates all player subarguments.
public static void quickSubArgumentUpdate(UUID uuid) {
List<String> playerCommands = new ArrayList<>(SubArguments.getServerCommands(uuid));
@@ -347,12 +363,14 @@ public class Storage {
public static AutoLowercaseCommandsSection AUTO_LOWERCASE_COMMANDS = new AutoLowercaseCommandsSection();
public static BlockNamespaceCommandsSection BLOCK_NAMESPACE_COMMANDS = new BlockNamespaceCommandsSection();
public static HandleThroughProxySection HANDLE_THROUGH_PROXY = new HandleThroughProxySection();
public static InjectionFailedSection INJECTION_FAILED = new InjectionFailedSection();
public static PatchExploitSection PATCH_EXPLOITS = new PatchExploitSection();
public static CustomBrandSection CUSTOM_BRAND = new CustomBrandSection();
public static CancelCommandSection CANCEL_COMMAND = new CancelCommandSection();
public static CustomPluginsSection CUSTOM_PLUGIN = new CustomPluginsSection();
public static CustomVersionSection CUSTOM_VERSION = new CustomVersionSection();
public static DisableSyncSection DISABLE_SYNC = new DisableSyncSection();
public static ForwardConsoleNotificationAlertsSection FORWARD_CONSOLE_NOTIFICATIONS = new ForwardConsoleNotificationAlertsSection();
public static CustomProtocolPingSection CUSTOM_PROTOCOL_PING = new CustomProtocolPingSection();
public static CustomUnknownCommandSection CUSTOM_UNKNOWN_COMMAND = new CustomUnknownCommandSection();
public static TurnBlacklistToWhitelistSection TURN_BLACKLIST_TO_WHITELIST = new TurnBlacklistToWhitelistSection();
@@ -656,7 +674,7 @@ public class Storage {
return !turn;
}
return turn != listed; // Shorter version of above's code
return turn != listed;
}
@@ -1,12 +1,13 @@
package de.rayzs.pat.api.storage.config.messages;
import de.rayzs.pat.api.storage.storages.ConfigStorage;
import de.rayzs.pat.utils.Reflection;
import de.rayzs.pat.utils.configuration.helper.*;
import java.util.Arrays;
public class InfoSection extends ConfigStorage {
public String VERSION_OUTDATED, VERSION_UPDATED, SYNC_TIME, SYNC_DISABLED;
public String VERSION_OUTDATED, VERSION_UPDATED, SYNC_TIME, SYNC_DISABLED, SYNC_WAITING;
public MultipleMessagesHelper MESSAGE;
public InfoSection() {
@@ -20,6 +21,11 @@ public class InfoSection extends ConfigStorage {
VERSION_UPDATED = new ConfigSectionHelper<String>(this, "version.updated", "&aLatest version").getOrSet();
VERSION_OUTDATED = new ConfigSectionHelper<String>(this, "version.outdated", "&cOutdated (%newest_version%)").getOrSet();
SYNC_TIME = new ConfigSectionHelper<String>(this, "proxy-sync.time", "&e%time%").getOrSet();
if (!Reflection.isProxyServer()) {
SYNC_WAITING = new ConfigSectionHelper<String>(this, "proxy-sync.waiting", "&cWaiting to establish connection...").getOrSet();
}
SYNC_DISABLED = new ConfigSectionHelper<String>(this, "proxy-sync.disabled", "&cDisabled").getOrSet();
MESSAGE = new MultipleMessagesHelper(this, "message",
@@ -28,6 +34,7 @@ public class InfoSection extends ConfigStorage {
, "&7 Version: &e%current_version%"
, "&7 Status: %version_status%"
, "&7 Last sync with proxy: &e%sync_time%"
, "&7 Last received alive packet: %last_alive_response%"
, "&7 Proxy sync-token: &e%token%"
, "&7 Proxy-received server name: &e%sync_server_name%"
)
@@ -18,12 +18,17 @@ public class StatsSection extends ConfigStorage {
@Override
public void load() {
super.load();
if(!Reflection.isProxyServer()) return;
if (!Reflection.isProxyServer()) {
return;
}
NO_SERVER = new ConfigSectionHelper<String>(this, "no-server", "&cNone!").getOrSet();
SPLITTER = new ConfigSectionHelper<String>(this, "message.splitter", "&7, ").getOrSet();
SERVER = new ConfigSectionHelper<String>(this, "message.server", "&f%servername% &8(%updated%)").getOrSet();
SERVER = new ConfigSectionHelper<String>(this, "message.server", "&f%servername% &8(&a%last_alive_response% &8/ &2%updated%&8)").getOrSet();
STATISTIC = new MultipleMessagesHelper(this, "message.statistic", Arrays.asList(
"&7Last sync sent to &f%server_count% &7servers. &8&o(%last_sync_time% ago)",
"&7Format: &eserver (last alive packet / last sync packet)",
"&7Last sync sent to &f%server_count% &7server(s) &e%last_sync_time% &7ago:",
"&7Sent to servers: &f%servers%"
));
}
@@ -17,9 +17,6 @@ public class AutoLowercaseCommandsSection extends ConfigStorage {
public void load() {
super.load();
if (Reflection.isProxyServer())
return;
ENABLED = new ConfigSectionHelper<Boolean>(this, "enabled", true).getOrSet();
}
@@ -25,7 +25,7 @@ public class CustomProtocolPingSection extends ConfigStorage {
public void load() {
super.load();
if (!Reflection.isProxyServer() && (!Reflection.isPaper() || Reflection.getMinor() < 12))
if (!Reflection.isProxyServer() && (!Reflection.isPaper() || Reflection.isBefore(1, 12)))
return;
ENABLED = new ConfigSectionHelper<Boolean>(this, "enabled", true).getOrSet();
@@ -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 ForwardConsoleNotificationAlertsSection extends ConfigStorage {
public boolean ENABLED;
public ForwardConsoleNotificationAlertsSection() {
super("forward-console-notification-alerts");
}
@Override
public void load() {
super.load();
if(!Reflection.isProxyServer()) return;
ENABLED = new ConfigSectionHelper<Boolean>(this, null, false).getOrSet();
}
}
@@ -6,7 +6,7 @@ import de.rayzs.pat.utils.Reflection;
public class HandleThroughProxySection extends ConfigStorage {
public boolean ENABLED;
public boolean ENABLED, ALLOW_P2B_ACTIONS;
public boolean LOAD_FROM_ENV;
public String ENV_NAME;
@@ -20,11 +20,13 @@ public class HandleThroughProxySection extends ConfigStorage {
@Override
public void load() {
super.load();
if(Reflection.isProxyServer()) return;
if (Reflection.isProxyServer()) return;
ENABLED = new ConfigSectionHelper<Boolean>(this, "enabled", false).getOrSet();
TOKEN = new ConfigSectionHelper<String>(this, "token", "insert-token-of-proxy-here").getOrSet();
ALLOW_P2B_ACTIONS = new ConfigSectionHelper<Boolean>(this, "allow-p2b-actions", false).getOrSet();
LOAD_FROM_ENV = new ConfigSectionHelper<Boolean>(this, "load-from-env.enabled", false).getOrSet();
ENV_NAME = new ConfigSectionHelper<String>(this, "load-from-env.name", "PAT_TOKEN").getOrSet();
}
@@ -0,0 +1,23 @@
package de.rayzs.pat.api.storage.config.settings;
import de.rayzs.pat.api.storage.storages.ConfigStorage;
import de.rayzs.pat.utils.configuration.helper.ConfigSectionHelper;
public class InjectionFailedSection extends ConfigStorage {
public boolean ENABLED, SUPPRESS_EXCEPTIONS;
public String KICK_MESSAGE, CONSOLE_MESSAGE;
public InjectionFailedSection() {
super("injection-failed");
}
@Override
public void load() {
super.load();
ENABLED = new ConfigSectionHelper<Boolean>(this, "kick-on-failure", true).getOrSet();
SUPPRESS_EXCEPTIONS = new ConfigSectionHelper<Boolean>(this, "suppress-exceptions", false).getOrSet();
KICK_MESSAGE = new ConfigSectionHelper<String>(this, "kick-message", "&cInjection process failed! Please reconnect.").getOrSet();
CONSOLE_MESSAGE = new ConfigSectionHelper<String>(this, "console-message", "&cInjection process failed! (%player%)").getOrSet();
}
}
@@ -6,7 +6,6 @@ import de.rayzs.pat.utils.configuration.helper.ConfigSectionHelper;
public class UpdateGroupsPerServerSection extends ConfigStorage {
// Disabled for now
public boolean ENABLED = false;
public UpdateGroupsPerServerSection() {
@@ -17,11 +16,9 @@ public class UpdateGroupsPerServerSection extends ConfigStorage {
public void load() {
super.load();
/*
if (!Reflection.isProxyServer())
return;
ENABLED = new ConfigSectionHelper<Boolean>(this, null, false).getOrSet();
*/
}
}
@@ -21,6 +21,7 @@ public class BlacklistStorage extends StorageTemplate implements Serializable {
public boolean isListed(String command, boolean ignoreColons) {
final boolean caseSensitive = Storage.ConfigSections.Settings.BASE_COMMAND_CASE_SENSITIVE.ENABLED;
final boolean turn = Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED;
if (commands == null || command.isEmpty()) {
return false;
@@ -28,7 +29,7 @@ public class BlacklistStorage extends StorageTemplate implements Serializable {
boolean isNegated = Storage.Blacklist.BlockTypeFetcher.isNegated(command);
if (!isNegated) {
if (!isNegated == turn) {
command = StringUtils.getFirstArg(command);
}
@@ -43,7 +44,7 @@ public class BlacklistStorage extends StorageTemplate implements Serializable {
command = command.substring(command.indexOf(':'));
}
if (!isNegated) {
if (!isNegated == turn) {
listedCommand = StringUtils.getFirstArg(listedCommand);
}
@@ -1,6 +1,8 @@
package de.rayzs.pat.plugin;
import de.rayzs.pat.api.brand.CustomServerBrand;
import de.rayzs.pat.api.communication.impl.BukkitClient;
import de.rayzs.pat.api.event.PATEventHandler;
import de.rayzs.pat.plugin.converter.StorageConverter;
import de.rayzs.pat.plugin.subarguments.SubArguments;
import de.rayzs.pat.plugin.process.CommandProcess;
@@ -9,7 +11,6 @@ import de.rayzs.pat.api.communication.BackendUpdater;
import de.rayzs.pat.utils.adapter.GroupManagerAdapter;
import de.rayzs.pat.utils.configuration.Configurator;
import de.rayzs.pat.utils.configuration.updater.ConfigUpdater;
import de.rayzs.pat.utils.group.TinyGroup;
import de.rayzs.pat.utils.message.MessageTranslator;
import de.rayzs.pat.utils.permission.PermissionUtil;
import de.rayzs.pat.utils.adapter.ViaVersionAdapter;
@@ -18,7 +19,6 @@ import de.rayzs.pat.utils.adapter.LuckPermsAdapter;
import de.rayzs.pat.plugin.commands.BukkitCommand;
import de.rayzs.pat.utils.hooks.PlaceholderHook;
import de.rayzs.pat.plugin.listeners.bukkit.*;
import de.rayzs.pat.api.event.PATEventHandler;
import de.rayzs.pat.utils.group.GroupManager;
import de.rayzs.pat.plugin.metrics.bStats;
import de.rayzs.pat.plugin.logger.Logger;
@@ -45,7 +45,6 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
private static Plugin plugin;
private static java.util.logging.Logger logger;
private static boolean loaded = false, suggestions = false;
private static Map<String, Command> commandsMap = null;
private PATSchedulerTask updaterTask;
@@ -71,8 +70,9 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
loadCommandMap();
CommandProcess.initialize();
Reflection.initialize(getServer());
CommandProcess.initialize();
ConfigUpdater.initialize();
Storage.initialize(this, getDescription().getVersion());
@@ -90,7 +90,6 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
PluginManager manager = getServer().getPluginManager();
if (!Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) {
loaded = true;
GroupManager.initialize();
BukkitPacketAnalyzer.injectAll();
} else BackendUpdater.handle();
@@ -98,12 +97,11 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
manager.registerEvents(new BukkitPlayerListener(), this);
manager.registerEvents(new BukkitBlockCommandListener(), this);
if (Reflection.getMinor() >= 13) {
suggestions = true;
if (Reflection.isAtLeast(1, 13)) {
manager.registerEvents(new BukkitAntiTabListener(), this);
}
if (Reflection.isPaper() && Reflection.getMinor() >= 12)
if (Reflection.isPaper() && Reflection.isAtLeast(1, 12))
manager.registerEvents(new PaperServerListPing(), this);
registerCommand("proantitab", "pat");
@@ -122,11 +120,8 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
}
}
if (getServer().getPluginManager().getPlugin("ViaVersion") != null)
if (getServer().getPluginManager().getPlugin("ViaVersion") != null) {
ViaVersionAdapter.initialize();
if (Storage.USE_SIMPLECLOUD) {
Logger.warning("Detected SimpleCloud. Therefore, MiniMessages are disabled!");
}
Storage.broadcastPermissionsPluginNotice();
@@ -137,6 +132,8 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
StorageConverter.initialize();
Communicator.initialize(new BukkitClient());
PATScheduler.createScheduler(() -> {
Storage.reload();
loadAllCommands();
@@ -209,7 +206,10 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
@Override
public String getPlayerServerName(UUID uuid) {
return null;
final Player player = Bukkit.getPlayer(uuid);
if (player == null) { return null; }
return player.getWorld().getName();
}
@Override
@@ -280,87 +280,81 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
}, 20L, 20L * Storage.ConfigSections.Settings.UPDATE.PERIOD);
}
public static void handleUpdateCommandsPacket(CommunicationPackets.UpdateCommandsPacket packet) {
public static void handleNotificationPacket(CommunicationPackets.Proxy2Backend.NotificationPacket packet) {
if (!Storage.SEND_CONSOLE_NOTIFICATION) { return; }
if (!packet.hasTargetUUID()) {
Bukkit.getOnlinePlayers().forEach(Player::updateCommands);
final Player player = Bukkit.getPlayer(packet.playerId());
if (player == null) {
return;
}
Player player = Bukkit.getPlayer(packet.getTargetUUID());
if (player != null && Reflection.getMinor() >= 13) {
player.updateCommands();
}
final List<String> notificationMessage = MessageTranslator.replaceMessageList(
Storage.ConfigSections.Messages.NOTIFICATION.ALERT,
"%player%", player.getName(),
"%command%", packet.command(),
"%server%", Storage.SERVER_NAME,
"%world%", player.getWorld().getName());
Logger.info(notificationMessage);
}
public static void synchronize(CommunicationPackets.PacketBundle packetBundle) {
Storage.LAST_SYNC = System.currentTimeMillis();
Communicator.sendFeedback();
CommunicationPackets.UnknownCommandPacket unknownCommandPacket = packetBundle.getUnknownCommandPacket();
CommunicationPackets.CommandsPacket commandsPacket = packetBundle.getCommandsPacket();
CommunicationPackets.GroupsPacket groupsPacket = packetBundle.getGroupsPacket();
CommunicationPackets.NamespaceCommandsPacket namespaceCommandsPacket = packetBundle.getNamespaceCommandsPacket();
CommunicationPackets.MessagePacket messagePacket = packetBundle.getMessagePacket();
boolean updatedList = false;
if (!messagePacket.getBaseBlockedMessage().getLines().isEmpty())
Storage.ConfigSections.Settings.CANCEL_COMMAND.BASE_COMMAND_RESPONSE = messagePacket.getBaseBlockedMessage();
if (!messagePacket.getSubBlockedMessage().getLines().isEmpty())
Storage.ConfigSections.Settings.CANCEL_COMMAND.SUB_COMMAND_RESPONSE = messagePacket.getSubBlockedMessage();
if (!messagePacket.getPrefix().isEmpty())
Storage.ConfigSections.Messages.PREFIX.PREFIX = messagePacket.getPrefix();
if (Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.ENABLED != namespaceCommandsPacket.isEnabled())
Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.ENABLED = namespaceCommandsPacket.isEnabled();
if (commandsPacket.getCommands() == null || commandsPacket.getCommands().isEmpty())
Storage.Blacklist.getBlacklist().setList(new ArrayList<>());
else if (!ArrayUtils.compareStringArrays(Storage.Blacklist.getBlacklist().getCommands(), commandsPacket.getCommands())) {
updatedList = true;
Storage.Blacklist.getBlacklist().setList(commandsPacket.getCommands());
public static void handleUpdateCommandsPacket(CommunicationPackets.Proxy2Backend.UpdatePacket packet) {
if (Reflection.isBefore(1, 13)) {
return;
}
if (Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED != commandsPacket.turnBlacklistToWhitelistEnabled())
Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED = commandsPacket.turnBlacklistToWhitelistEnabled();
Map<String, List<String>> cpyCache = new HashMap<>();
GroupManager.getGroups().forEach(group -> {
cpyCache.put(group.getGroupName(), group.getCommands());
});
GroupManager.clearAllGroups();
for (TinyGroup group : groupsPacket.getGroups()) {
List<String> currentExistingList = cpyCache.get(group.getGroupName());
if (
!updatedList
&& currentExistingList != null
&& !ArrayUtils.compareStringArrays(currentExistingList, group.getCommands())
) {
updatedList = true;
PATScheduler.createScheduler(() -> {
if (packet.forEveryone()) {
BukkitAntiTabListener.updateCommands();
return;
}
GroupManager.setGroup(group.getGroupName(), group.getPriority(), group.getCommands());
Player player = Bukkit.getPlayer(packet.playerId());
if (player != null) {
BukkitAntiTabListener.updateCommands(player);
}
});
}
public static void handlePlayerExecuteCommandPacket(CommunicationPackets.Proxy2Backend.ExecutePlayerCommandPacket packet) {
if (isP2BDisabled()) return;
final Player player = Bukkit.getPlayer(packet.playerId());
if (player == null) return;
PATScheduler.execute(() -> Bukkit.dispatchCommand(player, packet.command()), player);
}
public static void handleConsoleExecuteCommandPacket(CommunicationPackets.Proxy2Backend.ExecuteConsoleCommandPacket packet) {
if (isP2BDisabled()) return;
PATScheduler.execute(() -> Bukkit.dispatchCommand(Bukkit.getConsoleSender(), packet.command()), null);
}
public static void handleConsoleMessagePacket(CommunicationPackets.Proxy2Backend.ConsoleMessagePacket packet) {
if (isP2BDisabled()) return;
Logger.info(packet.message());
}
private static boolean isP2BDisabled() {
if (!Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ALLOW_P2B_ACTIONS) {
Logger.warning("P2B actions are currently disabled! You need to enable them manually.");
Logger.warning("For that, go to your 'plugins/ProAntiTab/config.yml' file and enable 'handle-through-proxy -> allow-p2b-actions'.");
return true;
}
Storage.ConfigSections.Settings.CUSTOM_UNKNOWN_COMMAND.MESSAGE = unknownCommandPacket.getMessage();
if (Storage.ConfigSections.Settings.CUSTOM_UNKNOWN_COMMAND.ENABLED != unknownCommandPacket.isEnabled())
Storage.ConfigSections.Settings.CUSTOM_UNKNOWN_COMMAND.ENABLED = unknownCommandPacket.isEnabled();
return false;
}
if (!loaded) {
loaded = true;
}
public static void handleDataSyncPacket(CommunicationPackets.Proxy2Backend.DataSyncPacket packet) {
Storage.ConfigSections.Messages.PREFIX.PREFIX = packet.messages().prefix();
Storage.ConfigSections.Settings.AUTO_LOWERCASE_COMMANDS.ENABLED = packet.autoLowerCase().enabled();
Storage.ConfigSections.Settings.CUSTOM_UNKNOWN_COMMAND.ENABLED = packet.unknownCommand().enabled();
Storage.ConfigSections.Settings.CUSTOM_UNKNOWN_COMMAND.MESSAGE = packet.unknownCommand().message();
if (Reflection.getMinor() >= 13 && updatedList) {
BukkitAntiTabListener.updateCommands();
}
PATEventHandler.callReceiveSyncEvents(packetBundle);
PATEventHandler.callReceiveSyncEvents(packet);
}
public static List<String> getAllCommands() {
@@ -501,10 +495,6 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
return commandsMap;
}
public static boolean useSuggestions() {
return suggestions;
}
public static Plugin getPlugin() {
return plugin;
}
@@ -512,8 +502,4 @@ public class BukkitLoader extends JavaPlugin implements PluginLoader {
public static java.util.logging.Logger getPluginLogger() {
return logger;
}
public static boolean isLoaded() {
return loaded;
}
}
@@ -2,6 +2,7 @@ package de.rayzs.pat.plugin;
import de.rayzs.pat.api.brand.CustomServerBrand;
import de.rayzs.pat.api.communication.impl.BungeeClient;
import de.rayzs.pat.plugin.converter.StorageConverter;
import de.rayzs.pat.plugin.process.CommandProcess;
import de.rayzs.pat.plugin.subarguments.SubArguments;
@@ -50,11 +51,10 @@ public class BungeeLoader extends Plugin implements PluginLoader {
plugin = this;
logger = getLogger();
CommandProcess.initialize();
Reflection.initialize(getProxy());
ConfigUpdater.initialize();
Storage.USE_SIMPLECLOUD = Reflection.doesClassExist("eu.thesimplecloud.plugin.startup.CloudPlugin");
CommandProcess.initialize();
ConfigUpdater.initialize();
Storage.initialize(this, getDescription().getVersion());
VersionComparer.get().setCurrentVersion(Storage.CURRENT_VERSION);
@@ -79,9 +79,6 @@ public class BungeeLoader extends Plugin implements PluginLoader {
startUpdaterTask();
if (!Storage.ConfigSections.Settings.DISABLE_SYNC.DISABLED)
ProxyServer.getInstance().getScheduler().schedule(this, Communicator::syncData, 5, TimeUnit.SECONDS);
Storage.PLUGIN_OBJECT = this;
if (manager.getPlugin("LuckPerms") != null)
@@ -92,9 +89,6 @@ public class BungeeLoader extends Plugin implements PluginLoader {
Logger.info("Successfully hooked into PAPIProxyBridge!");
}
if(Storage.USE_SIMPLECLOUD)
Logger.warning("Detected SimpleCloud and therefore MiniMessages by Kyori are disabled!");
BungeePacketAnalyzer.injectAll();
Storage.broadcastPermissionsPluginNotice();
@@ -105,6 +99,8 @@ public class BungeeLoader extends Plugin implements PluginLoader {
StorageConverter.initialize();
Communicator.initialize(new BungeeClient());
// Reload proxy commands after 1, 5, and 15 seconds.
for (int i : new Integer[] { 1, 5, 15 }) {
ProxyServer.getInstance().getScheduler().schedule(this, BungeePacketAnalyzer::loadProxyCommands, i, TimeUnit.SECONDS);
@@ -137,7 +133,7 @@ public class BungeeLoader extends Plugin implements PluginLoader {
PermissionUtil.reloadPermissions();
Storage.getLoader().updateCommandCache();
Communicator.sendRequest();
Communicator.Proxy2Backend.sendUpdateCommand();
}, 1, TimeUnit.SECONDS);
}
@@ -178,10 +174,16 @@ public class BungeeLoader extends Plugin implements PluginLoader {
@Override
public String getPlayerServerName(UUID uuid) {
final String cachedServerName = Storage.getCachedPlayerServername(uuid);
if (cachedServerName != null) {
return cachedServerName;
}
ProxiedPlayer player = ProxyServer.getInstance().getPlayer(uuid);
if (player == null || player.getServer() == null || player.getServer().getInfo() == null)
if (player == null || player.getServer() == null || player.getServer().getInfo() == null) {
return null;
}
return player.getServer().getInfo().getName();
}
@@ -5,6 +5,7 @@ import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import de.rayzs.pat.api.brand.CustomServerBrand;
import de.rayzs.pat.api.communication.impl.VelocityClient;
import de.rayzs.pat.api.event.PATEventHandler;
import de.rayzs.pat.api.netty.proxy.VelocityPacketAnalyzer;
import de.rayzs.pat.plugin.converter.StorageConverter;
@@ -39,7 +40,7 @@ import java.util.*;
@Plugin(name = "ProAntiTab",
id = "proantitab",
version = "2.2.1",
version = "2.3.2",
authors = "Rayzs_YT",
description = "Hides more than just your plugins.",
url = "https://www.rayzs.de/products/proantitab/page",
@@ -79,11 +80,11 @@ public class VelocityLoader implements PluginLoader {
Configurator.createResourcedFile("files\\proxy-placeholders.yml", "placeholders.yml", false);
Configurator.createResourcedFile("files\\proxy-custom-responses.yml", "custom-responses.yml", false);
CommandProcess.initialize();
Reflection.initialize(server);
CommandProcess.initialize();
ConfigUpdater.initialize();
Storage.USE_SIMPLECLOUD = Reflection.doesClassExist("eu.thesimplecloud.plugin.startup.CloudPlugin");
Storage.initialize(this, pluginContainer.getDescription().getVersion().get());
VersionComparer.get().setCurrentVersion(Storage.CURRENT_VERSION);
@@ -102,9 +103,6 @@ public class VelocityLoader implements PluginLoader {
startUpdaterTask();
if (!Storage.ConfigSections.Settings.DISABLE_SYNC.DISABLED)
server.getScheduler().buildTask(this, () -> Communicator.syncData()).delay(5, TimeUnit.SECONDS).schedule();
Storage.PLUGIN_OBJECT = this;
if (server.getPluginManager().getPlugin("luckperms").isPresent())
@@ -115,9 +113,6 @@ public class VelocityLoader implements PluginLoader {
Logger.info("Successfully hooked into PAPIProxyBridge!");
}
if (Storage.USE_SIMPLECLOUD)
Logger.warning("Detected SimpleCloud and therefore MiniMessages by Kyori are disabled!");
Storage.broadcastPermissionsPluginNotice();
ConfigUpdater.broadcastMissingParts();
@@ -126,6 +121,8 @@ public class VelocityLoader implements PluginLoader {
StorageConverter.initialize();
Communicator.initialize(new VelocityClient());
VelocityPacketAnalyzer.injectAll();
}
@@ -221,6 +218,11 @@ public class VelocityLoader implements PluginLoader {
@Override
public String getPlayerServerName(UUID uuid) {
final String cachedServerName = Storage.getCachedPlayerServername(uuid);
if (cachedServerName != null) {
return cachedServerName;
}
Optional<Player> optPlayer = server.getPlayer(uuid);
if (optPlayer.isEmpty())
@@ -229,8 +231,9 @@ public class VelocityLoader implements PluginLoader {
Player player = optPlayer.get();
Optional<ServerConnection> optConnection = player.getCurrentServer();
if (optConnection.isEmpty())
if (optConnection.isEmpty()) {
return null;
}
ServerConnection connection = optConnection.get();
return connection.getServer().getServerInfo().getName();
@@ -24,7 +24,10 @@ public class CommandWhitelistConverter extends Converter {
List<String> commands = new ArrayList<>();
final List<String> l1 = (ArrayList<String>) config.get("groups." + groupName + ".commands");
final List<String> l2 = (ArrayList<String>) config.get("groups." + groupName + ".subcommands");
final List<String> l2 = ((ArrayList<String>) config.get("groups." + groupName + ".subcommands"))
.stream()
.map(c -> Storage.Blacklist.BlockType.NEGATE + c)
.toList();
commands.addAll(l1);
commands.addAll(l2);
@@ -3,6 +3,7 @@ package de.rayzs.pat.plugin.listeners.bukkit;
import de.rayzs.pat.api.event.events.FilteredSuggestionEvent;
import de.rayzs.pat.utils.group.Group;
import de.rayzs.pat.utils.group.GroupManager;
import de.rayzs.pat.utils.scheduler.PATScheduler;
import de.rayzs.pat.utils.sender.CommandSender;
import de.rayzs.pat.utils.sender.CommandSenderHandler;
import org.bukkit.event.player.PlayerCommandSendEvent;
@@ -29,7 +30,7 @@ public class BukkitAntiTabListener implements Listener {
final UUID uuid = player.getUniqueId();
if (Storage.USE_VELOCITY) {
if (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) {
return;
}
@@ -41,15 +42,6 @@ public class BukkitAntiTabListener implements Listener {
return;
}
if (!BukkitLoader.isLoaded()) {
event.getCommands().clear();
return;
}
if (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED) {
return;
}
if (event.getCommands().isEmpty()) {
return;
}
@@ -59,13 +51,25 @@ public class BukkitAntiTabListener implements Listener {
if (!player.isOp() && knownOperators.contains(uuid)) {
knownOperators.remove(uuid);
PermissionUtil.reloadPermissions(player.getUniqueId());
if (Reflection.isCraftbukkit() && sender != null) {
PermissionUtil.reloadPermissions(sender);
} else {
PermissionUtil.reloadPermissions(uuid);
}
}
if (PermissionUtil.hasBypassPermission(sender)) {
return;
}
if (Reflection.isCraftbukkit() && !Bukkit.getOnlinePlayers().contains(player)) {
event.getCommands().clear();
PATScheduler.createScheduler(player::updateCommands, 10);
return;
}
final List<Group> groups = GroupManager.getPlayerGroups(sender);
final List<String> playerCommands = COMMANDS_CACHE.getPlayerCommands(new ArrayList<>(event.getCommands()), sender, groups);
final FilteredSuggestionEvent filteredSuggestionEvent = PATEventHandler.callFilteredSuggestionEvents(player, playerCommands);
@@ -93,7 +97,7 @@ public class BukkitAntiTabListener implements Listener {
}
private static boolean notUpdatablePlayer(UUID uuid) {
return Storage.USE_VIAVERSION && Reflection.getMinor() >= 16 && ViaVersionAdapter.getPlayerProtocol(uuid) < 754;
return Storage.USE_VIAVERSION && Reflection.isAtLeast(1, 16) && ViaVersionAdapter.getPlayerProtocol(uuid) < 754;
}
@@ -104,7 +108,7 @@ public class BukkitAntiTabListener implements Listener {
}
public static void updateCommands(Player player) {
if (Reflection.getMinor() >= 13 && !notUpdatablePlayer(player.getUniqueId()))
if (!notUpdatablePlayer(player.getUniqueId()))
player.updateCommands();
}
@@ -7,6 +7,7 @@ import de.rayzs.pat.api.netty.bukkit.BukkitPacketAnalyzer;
import de.rayzs.pat.api.communication.BackendUpdater;
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.permission.PermissionPlugin;
import de.rayzs.pat.utils.permission.PermissionUtil;
@@ -51,7 +52,7 @@ public class BukkitPlayerListener implements Listener {
PermissionUtil.reloadPermissions(sender);
}
if (Reflection.getMinor() >= 13) {
if (Reflection.isAtLeast(1, 13)) {
BukkitAntiTabListener.handleTabCompletion(player);
}
}, 20);
@@ -63,15 +64,26 @@ public class BukkitPlayerListener implements Listener {
PATScheduler.createScheduler(() -> {
if (player.isOnline()) {
if (!BukkitPacketAnalyzer.inject(player)) {
Logger.warning("Failed to inject into player! (" + player.getName() + ")" );
player.kickPlayer("Failed to inject player!");
if (Storage.ConfigSections.Settings.INJECTION_FAILED.ENABLED) {
Logger.info(MessageTranslator.replaceMessage(
sender,
Storage.ConfigSections.Settings.INJECTION_FAILED.CONSOLE_MESSAGE
));
player.kickPlayer(MessageTranslator.replaceMessage(
sender,
Storage.ConfigSections.Settings.INJECTION_FAILED.KICK_MESSAGE
));
}
}
}
}, 10);
}
// Update sub arguments for <1.12.2 servers.
if (Reflection.getMinor() < 13) {
if (Reflection.isBefore(1, 13)) {
Storage.quickSubArgumentUpdate(uuid);
}
@@ -107,7 +119,7 @@ public class BukkitPlayerListener implements Listener {
assert sender != null;
PermissionUtil.reloadPermissions(sender);
if (Reflection.getMinor() >= 13) {
if (Reflection.isAtLeast(1, 13)) {
BukkitAntiTabListener.handleTabCompletion(player);
}
}
@@ -1,5 +1,6 @@
package de.rayzs.pat.plugin.listeners.bungee;
import de.rayzs.pat.api.communication.Communicator;
import de.rayzs.pat.api.event.events.ExecuteCommandEvent;
import de.rayzs.pat.utils.group.Group;
import de.rayzs.pat.utils.group.GroupManager;
@@ -40,6 +41,10 @@ public class BungeeBlockCommandListener implements Listener {
command = command.startsWith("/") ? command.substring(1) : command;
command = StringUtils.getFirstArg(command);
if (Communicator.get().hasConnectedClients() && Storage.ConfigSections.Settings.AUTO_LOWERCASE_COMMANDS.isCommand(command)) {
command = command.toLowerCase();
}
final String displayCommand = StringUtils.replaceTriggers(command, "", "\\", "<", ">", "&");
@@ -51,6 +56,8 @@ public class BungeeBlockCommandListener implements Listener {
if (Storage.ConfigSections.Settings.CUSTOM_PLUGIN.isCommand(command)) {
Communicator.Proxy2Backend.sendNotification(player.getUniqueId(), serverName, displayCommand);
MessageTranslator.send(
player,
Storage.ConfigSections.Settings.CUSTOM_PLUGIN.MESSAGE,
@@ -73,6 +80,8 @@ public class BungeeBlockCommandListener implements Listener {
if (Storage.ConfigSections.Settings.CUSTOM_VERSION.isCommand(command)) {
Communicator.Proxy2Backend.sendNotification(player.getUniqueId(), serverName, displayCommand);
MessageTranslator.send(
player,
Storage.ConfigSections.Settings.CUSTOM_VERSION.MESSAGE,
@@ -125,6 +134,8 @@ public class BungeeBlockCommandListener implements Listener {
if (!executeCommandEvent.doesNotify())
return;
Communicator.Proxy2Backend.sendNotification(player.getUniqueId(), serverName, displayCommand);
if (Storage.SEND_CONSOLE_NOTIFICATION)
Logger.info(notificationMessage);
@@ -3,6 +3,7 @@ package de.rayzs.pat.plugin.listeners.velocity;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.command.CommandExecuteEvent;
import com.velocitypowered.api.command.CommandSource;
import de.rayzs.pat.api.communication.Communicator;
import de.rayzs.pat.api.event.events.ExecuteCommandEvent;
import de.rayzs.pat.utils.group.Group;
import de.rayzs.pat.utils.group.GroupManager;
@@ -45,7 +46,12 @@ public class VelocityBlockCommandListener {
? player.getCurrentServer().get().getServerInfo().getName()
: "unknown";
final String command = StringUtils.getFirstArg(event.getCommand());
String tmpCommand = StringUtils.getFirstArg(event.getCommand());
if (Communicator.get().hasConnectedClients() && Storage.ConfigSections.Settings.AUTO_LOWERCASE_COMMANDS.isCommand(tmpCommand)) {
tmpCommand = tmpCommand.toLowerCase();
}
final String command = tmpCommand;
if (PermissionUtil.hasBypassPermission(sender, command) || Storage.Blacklist.isDisabledServer(serverName))
return event;
@@ -62,6 +68,8 @@ public class VelocityBlockCommandListener {
if (Storage.ConfigSections.Settings.CUSTOM_PLUGIN.isCommand(command)) {
Communicator.Proxy2Backend.sendNotification(player.getUniqueId(), serverName, displayCommand);
MessageTranslator.send(
player,
Storage.ConfigSections.Settings.CUSTOM_PLUGIN.MESSAGE,
@@ -84,6 +92,8 @@ public class VelocityBlockCommandListener {
if (Storage.ConfigSections.Settings.CUSTOM_VERSION.isCommand(command)) {
Communicator.Proxy2Backend.sendNotification(player.getUniqueId(), serverName, displayCommand);
MessageTranslator.send(
player,
Storage.ConfigSections.Settings.CUSTOM_VERSION.MESSAGE,
@@ -138,6 +148,8 @@ public class VelocityBlockCommandListener {
if (!executeCommandEvent.doesNotify())
return event;
Communicator.Proxy2Backend.sendNotification(player.getUniqueId(), serverName, displayCommand);
if (Storage.SEND_CONSOLE_NOTIFICATION)
MessageTranslator.send(consoleSender, notificationMessage);
@@ -1,6 +1,7 @@
package de.rayzs.pat.plugin.listeners.velocity;
import com.velocitypowered.api.event.connection.DisconnectEvent;
import com.velocitypowered.api.proxy.server.ServerInfo;
import de.rayzs.pat.api.brand.CustomServerBrand;
import de.rayzs.pat.api.event.PATEventHandler;
import de.rayzs.pat.api.event.events.ServerPlayersChangeEvent;
@@ -33,8 +34,14 @@ public class VelocityConnectionListener {
public void onServerPreConnect(ServerPreConnectEvent event) {
final Player player = event.getPlayer();
final CommandSender sender = CommandSenderHandler.from(player);
sender.updateSenderObject(player);
if (Storage.ConfigSections.Settings.UPDATE_GROUPS_PER_SERVER.ENABLED) {
final ServerInfo serverInfo = event.getOriginalServer().getServerInfo();
if (serverInfo != null) Storage.tempCachePlayerToServer(player.getUniqueId(), serverInfo.getName());
}
PATEventHandler.callServerPlayersChangeEvents(player, ServerPlayersChangeEvent.Type.JOINED);
if(CustomServerBrand.isEnabled())
@@ -54,17 +61,28 @@ public class VelocityConnectionListener {
@Subscribe
public void onServerSwitch(ServerConnectedEvent event) {
Player player = event.getPlayer();
final Player player = event.getPlayer();
if (!VelocityPacketAnalyzer.isInjected(player)) {
if (!VelocityPacketAnalyzer.inject(player)) {
Logger.warning("Attempting delayed injection for " + player.getUsername());
server.getScheduler().buildTask(loader, () -> {
if (!VelocityPacketAnalyzer.inject(player)) {
Logger.warning("Second injection for " + player.getUsername() + " failed as well!");
player.disconnect(Component.text("Failed to inject player!"));
if (Storage.ConfigSections.Settings.INJECTION_FAILED.ENABLED) {
Logger.info(MessageTranslator.replaceMessage(
player,
Storage.ConfigSections.Settings.INJECTION_FAILED.CONSOLE_MESSAGE
));
player.disconnect(Component.text(
MessageTranslator.replaceMessage(
player,
Storage.ConfigSections.Settings.INJECTION_FAILED.KICK_MESSAGE
)
));
}
}
}).delay(1, TimeUnit.SECONDS).schedule();
@@ -72,8 +90,10 @@ public class VelocityConnectionListener {
}
if (Storage.ConfigSections.Settings.UPDATE_GROUPS_PER_SERVER.ENABLED) {
CommandSender sender = CommandSenderHandler.from(player);
final ServerInfo serverInfo = event.getServer().getServerInfo();
if (serverInfo != null) Storage.tempCachePlayerToServer(player.getUniqueId(), serverInfo.getName());
CommandSender sender = CommandSenderHandler.from(player);
assert sender != null;
PermissionUtil.reloadPermissions(sender);
}
@@ -22,9 +22,9 @@ public class Logger {
private static final String LOG_HEADER;
static {
final String software = Reflection.isProxyServer()
? Reflection.isVelocityServer() ? "Velocity" : "Bungeecord"
: (Reflection.isPaper() ? "Paper" : Reflection.isFoliaServer() ? "Folia" : "Spigot/Bukkit");
final String software = Reflection.getSoftware().isProxySoftware()
? Reflection.getSoftware().toString()
: Reflection.getVersionName();
final String version = Reflection.isProxyServer() ? "" : " " + Reflection.getRawVersionName().replace("_", ".");
@@ -82,6 +82,12 @@ public class Logger {
private static String createInfo() {
StringBuilder builder = new StringBuilder();
if (!Reflection.isProxyServer()) {
builder.append("Detected Software-API: ")
.append(Reflection.getSoftware().toString())
.append("\n\n");
}
builder.append("Updated: ")
.append(!Storage.OUTDATED)
.append("\n\n");
@@ -90,16 +96,6 @@ public class Logger {
.append(Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED ? "WHITELIST" : "BLACKLIST")
.append("\n");
builder.append("Detected Software-API: ");
if (Reflection.isProxyServer()) {
builder.append(Reflection.isPaper() ? "Waterfall" : Reflection.isVelocityServer() ? "Velocity" : "Bungeecord");
} else {
builder.append(Reflection.isFoliaServer() ? "Folia" : Reflection.isPaper() ? "Paper" : "Spigot");
}
builder.append("\n");
builder.append("Installed plugins: \n ")
.append(String.join("\n ", Storage.getLoader().getPluginNames("%n (%v)")))
.append("\n\n");
@@ -131,7 +127,11 @@ public class Logger {
.append("\n");
builder.append("last-received-sync: ")
.append(Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED ? TimeConverter.calcAndGetTime(Storage.LAST_SYNC) : "Deactivated")
.append(Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED ? TimeConverter.calcAndGetTime(Communicator.get().getLastSync()) : "Deactivated")
.append("\n");
builder.append("last-received-alive-response-packet: ")
.append(Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED ? TimeConverter.calcAndGetTime(Communicator.get().getLastReceivedKeepAliveResponse()) : "Deactivated")
.append("\n");
}
@@ -145,13 +145,22 @@ public class Logger {
.append("\n");
builder.append("last-sent-sync: ")
.append(Storage.ConfigSections.Settings.DISABLE_SYNC.DISABLED ? "Deactivated" : (TimeConverter.calcAndGetTime(Storage.LAST_SYNC)))
.append(Storage.ConfigSections.Settings.DISABLE_SYNC.DISABLED ? "Deactivated" : (TimeConverter.calcAndGetTime(Communicator.get().getLastSync())))
.append("\n\n");
for (ClientInfo client : Communicator.CLIENTS) {
builder.append("synced-server: ")
.append(client.getName() + " (" + client.getSyncTime() + ")")
.append(", ");
builder.append("synced-server: ");
Iterator<ClientInfo> iterator = Communicator.get().getClients().iterator();
while (iterator.hasNext()) {
ClientInfo clientInfo = iterator.next();
builder.append(clientInfo.getServerName())
.append(" (")
.append(clientInfo.getFormattedLastReceivedKeepAlivePacketTime() + " / " + clientInfo.getFormattedSyncTime())
.append(")");
if (iterator.hasNext()) {
builder.append(", ");
}
}
builder.append("\n\n");
@@ -1,5 +1,6 @@
package de.rayzs.pat.plugin.process.impl.local.info;
import de.rayzs.pat.api.communication.BackendUpdater;
import de.rayzs.pat.api.communication.Communicator;
import de.rayzs.pat.api.command.ProCommand;
import de.rayzs.pat.api.storage.Storage;
@@ -22,17 +23,33 @@ public class InfoCommand extends ProCommand {
String message = StringUtils.getStringList(Storage.ConfigSections.Messages.INFO.MESSAGE.getLines(), "\n");
String syncTime = Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED || Reflection.isProxyServer()
? Storage.ConfigSections.Messages.INFO.SYNC_TIME.replace("%time%", TimeConverter.calcAndGetTime(Reflection.isProxyServer()
? Communicator.LAST_DATA_UPDATE : Communicator.LAST_BUKKIT_SYNC))
String syncTime = Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED ||
Reflection.isProxyServer()
? Storage.ConfigSections.Messages.INFO.SYNC_TIME.replace("%time%", TimeConverter.calcAndGetTime(Communicator.get().getLastSync()))
: Storage.ConfigSections.Messages.INFO.SYNC_DISABLED;
String versionStatus = Storage.OUTDATED
String lastAlivePacketTime = Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED ||
Reflection.isProxyServer()
? Storage.ConfigSections.Messages.INFO.SYNC_TIME.replace("%time%", TimeConverter.calcAndGetTime(Communicator.get().getLastReceivedKeepAliveResponse()))
: Storage.ConfigSections.Messages.INFO.SYNC_DISABLED;
if (!Reflection.isProxyServer()
&& !BackendUpdater.isConnected()
&& Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED)
{
syncTime = Storage.ConfigSections.Messages.INFO.SYNC_WAITING;
lastAlivePacketTime = Storage.ConfigSections.Messages.INFO.SYNC_WAITING;
}
final String versionStatus = Storage.OUTDATED
? Storage.ConfigSections.Messages.INFO.VERSION_OUTDATED
: Storage.ConfigSections.Messages.INFO.VERSION_UPDATED;
message = StringUtils.replace(message,
"%sync_time%", syncTime,
"%last_alive_response%", lastAlivePacketTime,
"%version_status%", versionStatus
);
@@ -7,7 +7,9 @@ import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.utils.*;
import de.rayzs.pat.utils.sender.CommandSender;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class StatsCommand extends ProCommand {
@@ -29,26 +31,28 @@ public class StatsCommand extends ProCommand {
return true;
}
final int length = Communicator.CLIENTS.size() - 1;
boolean tmpFound = false;
final Set<ClientInfo> clients = Communicator.get().getClients();
final Iterator<ClientInfo> iterator = clients.iterator();
boolean tmpFound = false;
StringBuilder statsBuilder = new StringBuilder();
for (int i = 0; i < Communicator.CLIENTS.size(); i++) {
ClientInfo client = Communicator.CLIENTS.get(i);
while (iterator.hasNext()) {
ClientInfo client = iterator.next();
if (!client.hasSentFeedback())
continue;
if (!tmpFound)
if (!tmpFound) {
tmpFound = true;
}
statsBuilder.append(StringUtils.replace(Storage.ConfigSections.Messages.STATS.SERVER,
"%updated%", client.getSyncTime(), "%servername%", client.getName()
"%updated%", client.getFormattedSyncTime(),
"%servername%", client.getServerName(),
"%last_alive_response%", client.getFormattedLastReceivedKeepAlivePacketTime()
));
if (i <= length)
if (iterator.hasNext()) {
statsBuilder.append(Storage.ConfigSections.Messages.STATS.SPLITTER);
}
}
final boolean found = tmpFound;
@@ -56,8 +60,9 @@ public class StatsCommand extends ProCommand {
Storage.ConfigSections.Messages.STATS.STATISTIC.getLines().forEach(message -> {
message = StringUtils.replace(message,
"%server_count%", String.valueOf(Communicator.SERVER_DATA_SYNC_COUNT),
"%last_sync_time%", TimeConverter.calcAndGetTime(Communicator.LAST_DATA_UPDATE),
"%server_count%", String.valueOf(Communicator.get().getClients().size()),
"%last_sync_time%", TimeConverter.calcAndGetTime(Communicator.get().getLastSync()),
"%last_alive_response_time%", TimeConverter.calcAndGetTime(Communicator.get().getLastReceivedKeepAliveResponse()),
"%servers%", found ? statsBuilder.toString() : Storage.ConfigSections.Messages.STATS.NO_SERVER
);
@@ -18,20 +18,20 @@ public class NotifyCommand extends ProCommand {
@Override
public boolean execute(CommandSender sender, String[] args) {
boolean backend = Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED && !Reflection.isProxyServer();
if (backend) {
sender.sendMessage(Storage.ConfigSections.Messages.NO_PROXY.MESSAGE);
return true;
}
boolean enabled = false;
boolean enabled;
if (sender.isConsole()) {
enabled = Storage.SEND_CONSOLE_NOTIFICATION;
Storage.SEND_CONSOLE_NOTIFICATION = !Storage.SEND_CONSOLE_NOTIFICATION;
} else {
boolean backend = Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED && !Reflection.isProxyServer();
if (backend) {
sender.sendMessage(Storage.ConfigSections.Messages.NO_PROXY.MESSAGE);
return true;
}
enabled = Storage.NOTIFY_PLAYERS.contains(sender.getUniqueId());
if (enabled)
@@ -1,5 +1,6 @@
package de.rayzs.pat.plugin.process.impl.local.system;
import de.rayzs.pat.api.communication.Communicator;
import de.rayzs.pat.plugin.listeners.bukkit.BukkitAntiTabListener;
import de.rayzs.pat.utils.Reflection;
import de.rayzs.pat.utils.permission.PermissionUtil;
@@ -33,8 +34,10 @@ public class UpdateCommand extends ProCommand {
}
});
if (!Reflection.isProxyServer() && Reflection.getMinor() >= 13) {
if (!Reflection.isProxyServer() && Reflection.isAtLeast(1, 13)) {
BukkitAntiTabListener.handleTabCompletion();
} else if (Reflection.isProxyServer()) {
Communicator.Proxy2Backend.sendUpdateCommand();
}
sender.sendMessage(Storage.ConfigSections.Messages.UPDATE_PERMISSIONS.UPDATE_ALL);
@@ -62,8 +65,10 @@ public class UpdateCommand extends ProCommand {
PermissionUtil.reloadPermissions(targetSender);
if (!Reflection.isProxyServer() && Reflection.getMinor() >= 13) {
if (!Reflection.isProxyServer() && Reflection.isAtLeast(1, 13)) {
BukkitAntiTabListener.handleTabCompletion(uuid);
} else if (Reflection.isProxyServer()) {
Communicator.Proxy2Backend.sendUpdateCommand(uuid, targetSender.getServerName());
}
}
@@ -65,8 +65,7 @@ public class SubArguments {
}
public static void handleCommandNode(UUID uuid, ProxyCommandNodeHelper helper) {
if (!Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED)
return;
final boolean turn = Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED;
Arguments arguments = PLAYER_COMMANDS.get(uuid);
if (arguments == null) {
@@ -78,32 +77,51 @@ public class SubArguments {
return;
}
List<String> inputs = source.getAllInputs();
List<String> allEntries = inputs.stream().map(StringUtils::getFirstArg).toList();
final List<String> inputs = source.getAllInputs();
final List<String> actuallyExistingCommands = helper.getChildrenNames();
helper.removeIf(allEntries::contains);
if (turn) {
List<String> allEntries = inputs.stream().map(StringUtils::getFirstArg).toList();
helper.removeIf(allEntries::contains);
}
final int length = inputs.size();
for (int i = 0; i < length; i++) {
String input;
try {
input = inputs.get(i);
} catch (IndexOutOfBoundsException indexOutOfBoundsException) {
break;
}
for (String input : inputs) {
final boolean negated = Storage.Blacklist.BlockTypeFetcher.isNegated(input);
if (!negated) {
helper.add(input, true);
if (turn && actuallyExistingCommands.contains(StringUtils.getFirstArg(input))) {
helper.add(input, true);
} else helper.removeSubArguments(input);
continue;
}
final Storage.Blacklist.BlockType type = Storage.Blacklist.BlockTypeFetcher.getType(input);
if (type != Storage.Blacklist.BlockType.BOTH && type != Storage.Blacklist.BlockType.TAB) {
if (type == Storage.Blacklist.BlockType.CHAT) {
continue;
}
input = Storage.Blacklist.BlockTypeFetcher.cleanse(input);
helper.removeSubArguments(input);
if (turn) helper.removeSubArguments(input);
else if (actuallyExistingCommands.contains(StringUtils.getFirstArg(input))) {
helper.add(input, true);
}
}
}
public static void handleCommandNode(UUID uuid, BukkitCommandNodeHelper helper) throws Exception {
if (!Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED)
return;
final boolean turn = Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED;
Arguments arguments = PLAYER_COMMANDS.get(uuid);
if (arguments == null) {
@@ -115,10 +133,19 @@ public class SubArguments {
return;
}
List<String> inputs = source.getAllInputs();
List<String> argumentsList = new ArrayList<>();
final List<String> inputs = new ArrayList<>(source.getAllInputs());
final List<String> argumentsList = new ArrayList<>();
final int length = inputs.size();
for (int i = 0; i < length; i++) {
String input;
try {
input = inputs.get(i);
} catch (IndexOutOfBoundsException indexOutOfBoundsException) {
break;
}
for (String input : inputs) {
final Storage.Blacklist.BlockType type = Storage.Blacklist.BlockTypeFetcher.getType(input);
if (type == Storage.Blacklist.BlockType.CHAT) {
continue;
@@ -128,11 +155,15 @@ public class SubArguments {
input = Storage.Blacklist.BlockTypeFetcher.cleanse(input);
if (!negated) {
argumentsList.add(input);
if (turn) argumentsList.add(input);
else helper.removeSubArguments(input);
continue;
}
helper.removeSubArguments(input);
if (turn) helper.removeSubArguments(input);
else argumentsList.add(input);
}
if (argumentsList.isEmpty()) {
@@ -205,11 +236,6 @@ public class SubArguments {
online = Storage.getLoader().isPlayerOnline(s),
general = Storage.getLoader().doesPlayerExist(s);
if (number) {
split[i] = "%numbers%";
continue;
}
if (online && general) {
split[i] = "%both_players%";
continue;
@@ -220,8 +246,14 @@ public class SubArguments {
continue;
}
if (general)
if (general) {
split[i] = "%players%";
continue;
}
if (number) {
split[i] = "%numbers%";
}
}
return String.join(" ", split);
@@ -34,13 +34,15 @@ public class ExecuteCommand extends ExecuteCommandEvent {
return;
UUID uuid = sender.getUniqueId();
String serverName = sender.getServerName();
String playerName = sender.getName();
if (isBlocked(sender, command)) {
event.setBlocked(true);
event.setCancelled(true);
MessageTranslator.send(event.getSenderObj(),
ResponseHandler.getResponse(uuid, event.getCommand()),
ResponseHandler.getResponse(uuid, playerName, serverName, event.getCommand()),
"%command%", displayCommand);
return;
@@ -53,7 +55,7 @@ public class ExecuteCommand extends ExecuteCommandEvent {
MessageTranslator.send(
event.getSenderObj(),
ResponseHandler.getResponse(uuid, event.getCommand(), Storage.ConfigSections.Settings.CANCEL_COMMAND.BASE_COMMAND_RESPONSE.getLines()),
ResponseHandler.getResponse(uuid, playerName, serverName, event.getCommand(), Storage.ConfigSections.Settings.CANCEL_COMMAND.BASE_COMMAND_RESPONSE.getLines()),
"%command%", StringUtils.getFirstArg(displayCommand)
);
@@ -136,6 +138,24 @@ public class ExecuteCommand extends ExecuteCommandEvent {
cpyCommand = StringUtils.replace(command, "%both_players%", "%players%");
}
if (c.contains("%offline_players%")) {
final String[] cSplit = c.split(" ");
final String[] cpyCommandSplit = cpyCommand.split(" ");
for (int i = 0; i < cSplit.length; i++) {
if (i >= cpyCommandSplit.length) {
break;
}
if (cSplit[i].equals("%offline_players%") && !cpyCommandSplit[i].endsWith("players%")) {
cpyCommandSplit[i] = "%offline_players%";
}
}
cpyCommand = String.join(" ", cpyCommandSplit);
}
boolean ends = c.endsWith("_-");
if (ends) {
c = StringUtils.replace(c, "_-", "");
@@ -17,6 +17,12 @@ public class TabCompletion extends FilteredTabCompletionEvent {
if (event.getCompletion().isEmpty()) return;
if (Storage.ConfigSections.Settings.CUSTOM_PLUGIN.isCommand(cursor) || Storage.ConfigSections.Settings.CUSTOM_VERSION.isCommand(cursor)) {
event.setCompletion(List.of());
event.setCancelled(true);
return;
}
final boolean turn = Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED;
final UUID uuid = event.getSenderObj() instanceof UUID
? (UUID) event.getSenderObj()
@@ -75,6 +81,11 @@ public class TabCompletion extends FilteredTabCompletionEvent {
possibilities.addAll(SubArguments.getOnlinePlayerNames());
}
if (result.contains("%offline_players%")) {
possibilities.remove("%offline_players%");
possibilities.removeAll(SubArguments.getOnlinePlayerNames());
}
if (result.contains("%hidden_players%")) {
possibilities.remove("%hidden_players%");
@@ -111,6 +122,9 @@ public class TabCompletion extends FilteredTabCompletionEvent {
if (result.contains("%players%"))
possibilities.removeIf(possibility -> SubArguments.getPlayerNames().contains(possibility));
if (result.contains("%offline_players%"))
possibilities.removeIf(possibility -> !SubArguments.getPlayerNames().contains(possibility));
if (result.contains("%online_players%"))
possibilities.removeIf(possibility -> SubArguments.getOnlinePlayerNames().contains(possibility));
@@ -2,6 +2,7 @@ package de.rayzs.pat.plugin.subarguments.events;
import de.rayzs.pat.plugin.subarguments.SubArguments;
import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.utils.Reflection;
import de.rayzs.pat.utils.sender.CommandSenderHandler;
import de.rayzs.pat.api.event.events.*;
import de.rayzs.pat.utils.subargs.Arguments;
@@ -45,54 +46,46 @@ public class UpdateList {
argument.clearArguments();
if (Storage.ConfigSections.Settings.TURN_BLACKLIST_TO_WHITELIST.ENABLED) {
for (String command : event.getCommands())
for (String command : event.getCommands()) {
argument.buildArgumentStacks(command);
final List<String> chatInputs = new ArrayList<>(argument.CHAT_ARGUMENTS.getGeneralArgument().getInputs());
final List<String> tabInput = new ArrayList<>(argument.TAB_ARGUMENTS.getGeneralArgument().getInputs());
for (String command : chatInputs) {
Storage.Blacklist.BlockType type = Storage.Blacklist.BlockTypeFetcher.getType(command);
if (type != Storage.Blacklist.BlockType.NEGATE) {
command = Storage.Blacklist.BlockTypeFetcher.modify(command, type);
}
argument.CHAT_ARGUMENTS.buildArguments(command);
}
for (String command : tabInput) {
Storage.Blacklist.BlockType type = Storage.Blacklist.BlockTypeFetcher.getType(command);
if (type != Storage.Blacklist.BlockType.NEGATE)
command = Storage.Blacklist.BlockTypeFetcher.modify(command, type);
argument.TAB_ARGUMENTS.buildArguments(command);
}
for (String command : SubArguments.getGroupCommands(uuid, serverName))
for (String command : SubArguments.getGroupCommands(uuid, serverName)) {
argument.buildArgumentStacks(command);
}
for (String command : SubArguments.getServerCommands(uuid)) {
argument.buildArgumentStacks(command);
}
} else {
List<String> groupCommands = SubArguments.getGroupCommands(uuid, serverName);
for (String command : argument.CHAT_ARGUMENTS.getGeneralArgument().getInputs()) {
if (groupCommands.contains(command)) continue;
final List<String> groupCommands = SubArguments.getGroupCommands(uuid, serverName);
argument.CHAT_ARGUMENTS.buildArguments(Storage.Blacklist.BlockTypeFetcher.modify(command));
if (Reflection.isProxyServer()) {
final List<String> commands = SubArguments.getServerCommands(uuid);
commands.removeIf(groupCommands::contains);
for (String command : commands) {
argument.buildArgumentStacks(command);
}
} else {
for (String command : Arguments.ARGUMENTS.CHAT_ARGUMENTS.getGeneralArgument().getInputs()) {
if (groupCommands.contains(command)) continue;
argument.CHAT_ARGUMENTS.buildArguments(Storage.Blacklist.BlockTypeFetcher.modify(command));
}
for (String command : Arguments.ARGUMENTS.TAB_ARGUMENTS.getGeneralArgument().getInputs()) {
if (groupCommands.contains(command)) continue;
argument.TAB_ARGUMENTS.buildArguments(Storage.Blacklist.BlockTypeFetcher.modify(command));
}
}
for (String command : argument.TAB_ARGUMENTS.getGeneralArgument().getInputs()) {
if (groupCommands.contains(command)) continue;
argument.TAB_ARGUMENTS.buildArguments(Storage.Blacklist.BlockTypeFetcher.modify(command));
}
}
SubArguments.PLAYER_COMMANDS.putIfAbsent(uuid, argument);
@@ -1,296 +1,194 @@
package de.rayzs.pat.utils;
import de.rayzs.pat.utils.configuration.helper.MultipleMessagesHelper;
import de.rayzs.pat.utils.group.TinyGroup;
import de.rayzs.pat.api.communication.Communicator;
import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.utils.configuration.helper.MultipleMessagesHelper;
import java.util.*;
import java.io.*;
public class CommunicationPackets {
public static byte[] convertToBytes(Object obj) {
ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
private static final byte INIT_PACKET = 0;
private static final byte NOT_INIT_PACKET = 1;
public static byte[] preparePacket(Object object) {
return preparePacket(object, Communicator.get().getId());
}
public static byte[] preparePacket(Object object, UUID id) {
if (!isValidPacket(object)) {
return null;
}
final boolean isInitialPacket = isInitialPacket(object);
final ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
try (ObjectOutputStream outputStream = new ObjectOutputStream(arrayOutputStream)) {
outputStream.writeObject(obj);
outputStream.writeObject(object);
outputStream.flush();
return arrayOutputStream.toByteArray();
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;
}
public static Object buildFromBytes(byte[] bytes) {
ByteArrayInputStream arrayInputStream = new ByteArrayInputStream(bytes);
public static Object readPacket(byte[] bytes) {
return readPacket(bytes, Communicator.get().getId());
}
public static Object readPacket(byte[] bytes, UUID id) {
if (bytes.length == 0) {
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)) {
Object object = input.readObject();
if (object.getClass() == null) return null;
final Object object = input.readObject();
if (object.getClass() == null || !isValidPacket(object)) {
return null;
}
return object;
} catch (Throwable ignored) { }
} catch (Exception ignored) { }
return null;
}
public static boolean isPacket(Object object) {
return object instanceof CommunicationPacket;
// 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();
int pos = 0;
for (int i = 0; i < bytes.length; i++) {
output[i] = (byte) (bytes[i] ^ secret[pos]);
pos += 1;
if (pos >= secret.length) {
pos = 0;
}
}
return output;
}
public interface CommunicationPacket {}
public static boolean isValidPacket(Object object) {
return object instanceof PATPacket;
}
public static class BackendDataPacket implements CommunicationPacket, Serializable {
private final String proxyToken, serverName, serverId;
public static boolean isP2BPacket(Object object) {
return object instanceof P2BPacket;
}
public BackendDataPacket(String proxyToken, String serverId, String serverName) {
this.proxyToken = proxyToken;
this.serverId = serverId;
this.serverName = serverName;
}
public static boolean isB2PPacket(Object object) {
return object instanceof B2PPacket;
}
public String getServerId() {
return serverId;
}
public static boolean isInitialPacket(Object object) {
return object instanceof InitialPacket;
}
public String getServerName() {
return serverName;
}
public static boolean isInitialPacket(byte[] bytes) {
return bytes.length > 0 && isInitialPacket(bytes[0]);
}
public boolean isToken(String token) {
return proxyToken.equals(token);
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);
}
}
public static class UpdateCommandsPacket implements CommunicationPacket, Serializable {
private final String proxyToken;
private final UUID targetUUID;
public UpdateCommandsPacket(String proxyToken) {
this.proxyToken = proxyToken;
this.targetUUID = null;
private interface InitialPacket extends PATPacket {}
private interface Synchronizable extends Serializable {}
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 UpdateCommandsPacket(String proxyToken, UUID targetUUID) {
this.proxyToken = proxyToken;
this.targetUUID = targetUUID;
}
public record IdentityPacket(UUID targetServerId, String serverName) implements InitialPacket, P2BPacket { }
public boolean hasTargetUUID() {
return targetUUID != null;
}
public record NotificationPacket(UUID playerId, String command) implements P2BPacket { }
public UUID getTargetUUID() {
return targetUUID;
}
public record ExecuteConsoleCommandPacket(String command) implements P2BPacket { }
public boolean isToken(String token) {
return proxyToken.equals(token);
}
}
public record ExecutePlayerCommandPacket(UUID playerId, String command) implements P2BPacket { }
public static class FeedbackPacket implements CommunicationPacket, Serializable {
private final String proxyToken, serverId;
public record ConsoleMessagePacket(String message) implements P2BPacket { }
public FeedbackPacket(String proxyToken, String serverId) {
this.proxyToken = proxyToken;
this.serverId = serverId;
}
public record KeepAliveResponsePacket() implements P2BPacket { }
public String getServerId() {
return serverId;
}
public record DataSyncPacket(
Messages messages,
AutoLowerCase autoLowerCase,
UnknownCommand unknownCommand
) implements P2BPacket {
public boolean isToken(String token) {
return proxyToken.equals(token);
}
}
public record Messages(String prefix)
implements Synchronizable {}
public static class RequestPacket implements CommunicationPacket, Serializable {
private final String proxyToken, serverId;
public record AutoLowerCase(boolean enabled)
implements Synchronizable {}
public RequestPacket(String proxyToken, String serverId) {
this.proxyToken = proxyToken;
this.serverId = serverId;
}
public record UnknownCommand(boolean enabled, MultipleMessagesHelper message)
implements Synchronizable {}
public String getServerId() {
return serverId;
}
public boolean isToken(String token) {
return proxyToken.equals(token);
}
}
public static class ForcePermissionResetPacket implements Serializable {
private final String proxyToken;
private UUID targetUUID = null;
public ForcePermissionResetPacket(String proxyToken) {
this.proxyToken = proxyToken;
}
public ForcePermissionResetPacket(String proxyToken, UUID targetUUID) {
this.proxyToken = proxyToken;
this.targetUUID = targetUUID;
}
public UUID getTargetUUID() {
return targetUUID;
}
public boolean hasTarget() {
return targetUUID != null;
}
public boolean isToken(String token) {
return proxyToken.equals(token);
}
}
public static class PacketBundle implements CommunicationPacket, Serializable {
private final CommandsPacket commandsPacket;
private final GroupsPacket groupsPacket;
private final UnknownCommandPacket unknownCommandPacket;
private final NamespaceCommandsPacket namespaceCommandsPacket;
private final MessagePacket messagePacket;
private final String proxyToken, serverId;
private final boolean velocity;
public PacketBundle(String proxyToken, String serverId, CommandsPacket commandsPacket, GroupsPacket groupsPacket) {
this.proxyToken = proxyToken;
this.serverId = serverId;
this.commandsPacket = commandsPacket;
this.groupsPacket = groupsPacket;
this.unknownCommandPacket = new UnknownCommandPacket();
this.namespaceCommandsPacket = new NamespaceCommandsPacket();
this.messagePacket = new MessagePacket();
this.velocity = Reflection.isVelocityServer();
}
public boolean isVelocity() {
return velocity;
}
public boolean isToken(String token) {
return proxyToken.equals(token);
}
public boolean isId(String id) {
return idIgnored() || serverId.equals(id);
}
public boolean idIgnored() {
return serverId == null;
}
public CommandsPacket getCommandsPacket() {
return commandsPacket;
}
public GroupsPacket getGroupsPacket() {
return groupsPacket;
}
public UnknownCommandPacket getUnknownCommandPacket() { return unknownCommandPacket; }
public MessagePacket getMessagePacket() {
return messagePacket;
}
public NamespaceCommandsPacket getNamespaceCommandsPacket() {
return namespaceCommandsPacket;
}
}
public static class MessagePacket implements Serializable {
private final String prefix;
private final MultipleMessagesHelper baseBlockedMessage, subBlockedMessage;
public MessagePacket() {
prefix = Storage.ConfigSections.Messages.PREFIX.PREFIX;
baseBlockedMessage = Storage.ConfigSections.Settings.CANCEL_COMMAND.BASE_COMMAND_RESPONSE;
subBlockedMessage = Storage.ConfigSections.Settings.CANCEL_COMMAND.SUB_COMMAND_RESPONSE;
}
public String getPrefix() {
return prefix;
}
public MultipleMessagesHelper getBaseBlockedMessage() {
return baseBlockedMessage;
}
public MultipleMessagesHelper getSubBlockedMessage() {
return subBlockedMessage;
}
}
public static class NamespaceCommandsPacket implements Serializable {
public static class Backend2Proxy {
private final boolean enabled;
private Backend2Proxy() { }
public NamespaceCommandsPacket() {
enabled = Storage.ConfigSections.Settings.BLOCK_NAMESPACE_COMMANDS.ENABLED;
}
public record IdentityRequestPacket(UUID serverId) implements InitialPacket, B2PPacket { }
public boolean isEnabled() {
return enabled;
}
}
public record IdentityResponsePacket(UUID serverId) implements InitialPacket, B2PPacket { }
public static class UnknownCommandPacket implements Serializable {
public record DataSyncReceivedPacket() implements B2PPacket { }
private final MultipleMessagesHelper message;
private final boolean enabled;
public record KeepAlivePacket() implements B2PPacket { }
public UnknownCommandPacket() {
enabled = Storage.ConfigSections.Settings.CUSTOM_UNKNOWN_COMMAND.ENABLED;
message = Storage.ConfigSections.Settings.CUSTOM_UNKNOWN_COMMAND.MESSAGE;
}
public MultipleMessagesHelper getMessage() {
return message;
}
public boolean isEnabled() {
return enabled;
}
}
public static class CommandsPacket implements Serializable {
private List<String> commands;
private boolean turnBlacklistToWhitelist;
public void setCommands(List<String> commands) {
this.commands = commands;
}
public void setTurnBlacklistToWhitelist(boolean turnBlacklistToWhitelist) {
this.turnBlacklistToWhitelist = turnBlacklistToWhitelist;
}
public boolean turnBlacklistToWhitelistEnabled() {
return turnBlacklistToWhitelist;
}
public List<String> getCommands() {
return commands;
}
}
public static class GroupsPacket implements Serializable {
private final List<TinyGroup> groups;
public GroupsPacket(List<TinyGroup> groups) {
this.groups = groups;
}
public List<TinyGroup> getGroups() {
return groups;
}
}
}
@@ -5,58 +5,10 @@ import io.netty.buffer.*;
public class PacketUtils {
/*
Copyright (c) 2012, md_5. All rights reserved.
Original code from Bungeecord source:
https://github.com/SpigotMC/BungeeCord/blob/master/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java#L72-L94
*/
public static String readString(ByteBuf buf) throws Exception {
return readString( buf, Short.MAX_VALUE );
}
public static String readString(ByteBuf byteBuf, int maxLength) throws Exception {
int len = readVarInt(byteBuf);
if ( len > maxLength * 3 )
throw new Exception("Cannot receive string longer than " + maxLength * 3 + " (got " + len + " bytes)" );
String string = byteBuf.toString(byteBuf.readerIndex(), len, StandardCharsets.UTF_8);
byteBuf.readerIndex(byteBuf.readerIndex() + len );
if (string.length() > maxLength)
throw new Exception( "Cannot receive string longer than " + maxLength + " (got " + string.length() + " characters)" );
return string;
}
/*
Copyright (c) 2012, md_5. All rights reserved.
Original code from Bungeecord source:
https://github.com/SpigotMC/BungeeCord/blob/master/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java#L233-L261
*/
public static int readVarInt(ByteBuf input) throws Exception {
return readVarInt(input, 5);
}
public static int readVarInt(ByteBuf input, int maxBytes) throws Exception {
int out = 0, bytes = 0;
byte in;
while (true) {
in = input.readByte();
out |= (in & 0x7F) << (bytes++ * 7);
if (bytes > maxBytes) throw new Exception( "VarInt too big (max " + maxBytes + ")" );
if ((in & 0x80) != 0x80) break;
}
return out;
}
/*
Copyright (c) 2012, md_5. All rights reserved.
Original code from Bungeecord source:
https://github.com/SpigotMC/BungeeCord/blob/master/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java#L263C1-L283C6
https://github.com/SpigotMC/BungeeCord/blob/master/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java#L307-L327
*/
public static void writeVarInt(int value, ByteBuf output) {
@@ -75,7 +27,7 @@ public class PacketUtils {
/*
Copyright (c) 2012, md_5. All rights reserved.
Original code from Bungeecord source:
https://github.com/SpigotMC/BungeeCord/blob/master/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java#L50C4-L71C1
https://github.com/SpigotMC/BungeeCord/blob/master/protocol/src/main/java/net/md_5/bungee/protocol/DefinedPacket.java#L88-L108
*/
public static void writeString(String string, ByteBuf byteBuf) throws Exception {
+126 -81
View File
@@ -9,53 +9,40 @@ import java.util.*;
public class Reflection {
private static boolean legacy, proxy, velocity, paper, folia, weird, oldChannelMethod;
private static String versionName, fullVersionName, rawVersionName, versionPackageName;
private static Version version;
private static boolean legacy, weird, oldChannelMethod;
private static String versionName, rawVersionName, versionPackageName;
private static int major, minor, release;
private static Software software;
public static void initialize(Object serverObj) {
try {
Class.forName("org.bukkit.Server");
loadVersionName(serverObj);
loadAges();
loadVersionEnum();
legacy = minor <= 16;
weird = Reflection.getMinor() == 20 && Reflection.getRelease() >= 6 || Reflection.getMinor() > 20;
proxy = false;
} catch (Throwable ignored) { proxy = true; }
if (!proxy) {
if (doesClassExist("org.bukkit.Server")) {
try {
Class.forName("io.papermc.paper.threadedregions.RegionizedServer");
folia = true;
} catch (Throwable throwable) {
folia = false;
software = doesClassExist("io.papermc.paper.threadedregions.RegionizedServer")
? Software.FOLIA : doesClassExist("com.destroystokyo.paper.Metrics")
? Software.PAPER : doesClassExist("org.spigotmc.SpigotConfig")
? Software.SPIGOT : Software.BUKKIT;
loadVersionName(serverObj);
loadAges();
legacy = isAtMost(1, 16);
weird = isAtLeast(1, 20, 6);
oldChannelMethod = software.isPaperBased() && weird;
} catch (Exception exception) {
exception.printStackTrace();
}
return;
}
try {
Class.forName("com.destroystokyo.paper.Metrics");
paper = true;
} catch (Throwable throwable) {
try {
Class.forName("io.github.waterfallmc.waterfall.QueryResult");
paper = true;
} catch (Throwable throwable1) {
paper = false;
}
}
if (proxy) {
try {
Class.forName("com.velocitypowered.api.proxy.ProxyServer");
velocity = true;
} catch (ClassNotFoundException ignored) { velocity = false; }
}
if (proxy) version = Version.UNKNOWN;
oldChannelMethod = folia || paper && Reflection.isWeird();
software = doesClassExist("com.velocitypowered.api.proxy.ProxyServer")
? Software.VELOCITY : doesClassExist("io.github.waterfallmc.waterfall.QueryResult")
? Software.WATERFALL : Software.BUNGEECORD;
}
public static void toggleInjectionMethod() {
@@ -67,22 +54,31 @@ public class Reflection {
public static int[] getAges() { return new int[]{major, minor, release}; }
public static String getVersionName() { return versionName; }
public static String getRawVersionName() { return rawVersionName; }
public static Version getVersion() { return version; }
public static boolean isModern() { return !legacy; }
public static boolean isLegacy() { return legacy; }
public static boolean isWeird() { return weird; }
public static Software getSoftware() {
return software;
}
public static boolean isFoliaServer() {
return folia;
return software == Software.FOLIA;
}
public static boolean isCraftbukkit() {
return software == Software.BUKKIT;
}
public static boolean isProxyServer() {
return proxy;
return software.isProxySoftware();
}
public static boolean isVelocityServer() {
return velocity;
return software == Software.VELOCITY;
}
public static boolean isPaper() {
return software == Software.PAPER;
}
public static boolean isPaper() { return paper; }
public static Class<?> getClass(String clazzPath) {
Class<?> clazz = null;
@@ -301,7 +297,7 @@ public class Reflection {
}
public static Object getPlayerNetworkManager(Object playerConnection) throws Exception {
Optional<Field> optional = getFieldsByType(Reflection.getMinor() == 20 && Reflection.getRelease() > 2 || Reflection.getMinor() > 20 ? playerConnection.getClass().getSuperclass() : playerConnection.getClass(), "NetworkManager", SearchOption.ENDS).stream().findFirst();
Optional<Field> optional = getFieldsByType(Reflection.isAfter(1, 20, 2) ? playerConnection.getClass().getSuperclass() : playerConnection.getClass(), "NetworkManager", SearchOption.ENDS).stream().findFirst();
if(!optional.isPresent()) return null;
return optional.get().get(playerConnection);
}
@@ -352,57 +348,106 @@ public class Reflection {
private static void loadVersionName(Object serverObject) throws Exception {
versionName = proxy ? ProxyServer.getInstance().getName() : Bukkit.getName();
versionName = software.proxySoftware ? ProxyServer.getInstance().getName() : Bukkit.getName();
rawVersionName = (String) serverObject.getClass().getMethod("getBukkitVersion").invoke(serverObject);
fullVersionName = rawVersionName;
rawVersionName = rawVersionName.split("-")[0].replace(".", "_");
versionPackageName = serverObject.getClass().getPackage().getName();
versionPackageName = versionPackageName.substring(versionPackageName.lastIndexOf('.') + 1);
}
private static void loadVersionEnum() {
try {
final String primaryVersionName, fullVersionName;
StringBuilder builder = new StringBuilder("v_");
builder.append(major).append("_").append(minor);
primaryVersionName = builder.toString();
if (release != 0) builder.append("_").append(release);
fullVersionName = builder.toString();
boolean couldFindOriginalVersion = Arrays.stream(Version.values()).anyMatch(searchingVersion -> searchingVersion.toString().equals(fullVersionName));
version = Version.valueOf(couldFindOriginalVersion ? fullVersionName : primaryVersionName);
} catch (Exception exception) {
version = Version.UNSUPPORTED;
}
}
private static void loadAges() {
String[] versionArgs = rawVersionName.split("_");
final String[] versionArgs = rawVersionName.split("_");
major = Integer.parseInt(versionArgs[0]);
minor = Integer.parseInt(versionArgs[1]);
release = versionArgs.length > 2 ? Integer.parseInt(versionArgs[2]) : 0;
if (versionArgs.length >= 3) {
try {
release = Integer.parseInt(versionArgs[2]);
return;
} catch (NumberFormatException ignored) {}
}
release = 0;
}
public static int getMajor() { return major; }
public static int getMinor() { return minor; }
public static int getRelease() { return release; }
public enum Version {
UNKNOWN, UNSUPPORTED,
v_1_8, v_1_8_8,
v_1_9, v_1_9_4,
v_1_10, v_1_10_2,
v_1_11, v_1_11_2,
v_1_12, v_1_12_2,
v_1_13, v_1_13_2,
v_1_14, v_1_14_4,
v_1_15, v_1_15_2,
v_1_16, v_1_16_4, v_1_16_5,
v_1_17, v_1_17_1, v_1_18,
v_1_18_1, v_1_18_2,
v_1_19, v_1_19_1, v_1_19_2, v_1_19_3, v_1_19_4,
v_1_20, v_1_20_1, v_1_20_2, v_1_20_3, v_1_20_4, v_1_20_5, v_1_20_6,
v_1_21, v_1_21_1, v_1_21_2, v_1_21_3, v_1_21_4, v_1_21_5, v_1_21_6, v_1_21_7, v_1_21_8,
v_1_22, v_1_22_1, v_1_22_2
public static boolean isAtLeast(int major, int minor) {
return Reflection.getMajor() > major || (Reflection.getMajor() == major && Reflection.getMinor() >= minor);
}
public static boolean isAtLeast(int major, int minor, int release) {
return Reflection.getMajor() > major
|| (Reflection.getMajor() == major && Reflection.getMinor() > minor)
|| (Reflection.getMajor() == major && Reflection.getMinor() == minor && Reflection.getRelease() >= release);
}
public static boolean isAtMost(int major, int minor) {
return Reflection.getMajor() < major || (Reflection.getMajor() == major && Reflection.getMinor() <= minor);
}
public static boolean isAtMost(int major, int minor, int release) {
return Reflection.getMajor() < major
|| (Reflection.getMajor() == major && Reflection.getMinor() < minor)
|| (Reflection.getMajor() == major && Reflection.getMinor() == minor && Reflection.getRelease() <= release);
}
public static boolean isAfter(int major, int minor) {
return Reflection.getMajor() > major || (Reflection.getMajor() == major && Reflection.getMinor() > minor);
}
public static boolean isAfter(int major, int minor, int release) {
return Reflection.getMajor() > major
|| (Reflection.getMajor() == major && Reflection.getMinor() > minor)
|| (Reflection.getMajor() == major && Reflection.getMinor() == minor && Reflection.getRelease() > release);
}
public static boolean isBefore(int major, int minor) {
return Reflection.getMajor() < major || (Reflection.getMajor() == major && Reflection.getMinor() < minor);
}
public static boolean isBefore(int major, int minor, int release) {
return Reflection.getMajor() < major
|| (Reflection.getMajor() == major && Reflection.getMinor() < minor)
|| (Reflection.getMajor() == major && Reflection.getMinor() == minor && Reflection.getRelease() < release);
}
public enum Software {
BUKKIT(false, false),
SPIGOT(false, false),
PAPER(true, false),
FOLIA(true, false),
BUNGEECORD(false, true),
WATERFALL(true, true),
VELOCITY(true, true);
private final String name;
private final boolean paperBased, proxySoftware;
Software(final boolean paperBased, final boolean proxySoftware) {
this.paperBased = paperBased;
this.proxySoftware = proxySoftware;
this.name = Character.toUpperCase(this.name().charAt(0)) + this.name().substring(1).toLowerCase();
}
@Override
public String toString() {
return name;
}
public boolean isPaperBased() {
return paperBased;
}
public boolean isProxySoftware() {
return proxySoftware;
}
}
public enum SearchOption { CONTAINS, EQUALS, ENDS, STARTS }
@@ -34,12 +34,32 @@ public class TimeConverter {
}
StringBuilder uptimeText = new StringBuilder();
if (weeks > 0) uptimeText.append(weeks + "w, ");
else if (days > 0) uptimeText.append(days + "d, ");
else if (hours > 0) uptimeText.append(hours + "h, ");
else if (minutes > 0) uptimeText.append(minutes + "m, ");
else if (seconds > 0) uptimeText.append(seconds + "s");
else uptimeText.append(ms + "ms");
if (weeks > 0) {
uptimeText.append(weeks).append("w");
}
if (days > 0) {
if (weeks > 0) uptimeText.append(", ");
uptimeText.append(days).append("d");
}
if (hours > 0) {
if (days > 0) uptimeText.append(", ");
uptimeText.append(hours).append("h");
}
if (minutes > 0) {
if (hours > 0) uptimeText.append(", ");
uptimeText.append(minutes).append("m");
}
if (seconds > 0) {
if (minutes > 0) uptimeText.append(", ");
uptimeText.append(seconds).append("s");
} else {
uptimeText.append(ms).append("ms");
}
return uptimeText.toString();
}
@@ -46,7 +46,7 @@ public class GroupManagerAdapter implements Listener {
.filter(permission -> permission.startsWith("proantitab."))
.forEach(permission -> PermissionUtil.setPermission(uuid, permission, true));
if (Reflection.getMinor() >= 13) {
if (Reflection.isAtLeast(1, 13)) {
BukkitAntiTabListener.handleTabCompletion(uuid);
}
}
@@ -4,6 +4,7 @@ import de.rayzs.pat.api.communication.Communicator;
import de.rayzs.pat.plugin.listeners.bukkit.BukkitAntiTabListener;
import de.rayzs.pat.utils.permission.PermissionPlugin;
import de.rayzs.pat.utils.scheduler.PATScheduler;
import net.luckperms.api.context.ImmutableContextSet;
import net.luckperms.api.event.sync.PreNetworkSyncEvent;
import de.rayzs.pat.utils.permission.PermissionUtil;
import de.rayzs.pat.plugin.VelocityLoader;
@@ -15,6 +16,8 @@ import net.luckperms.api.event.node.*;
import de.rayzs.pat.utils.Reflection;
import net.luckperms.api.node.*;
import net.luckperms.api.*;
import net.luckperms.api.query.QueryOptions;
import java.util.*;
public class LuckPermsAdapter {
@@ -44,17 +47,29 @@ public class LuckPermsAdapter {
}
public static Map<String, Boolean> getPermissions(UUID uuid) {
User user = getUser(uuid);
if (user == null) return null;
final User user = PROVIDER.getUserManager().getUser(uuid);
return user.getCachedData().getPermissionData().getPermissionMap();
if (user == null) {
return null;
}
final ImmutableContextSet.Builder builder = ImmutableContextSet.builder();
if (Storage.ConfigSections.Settings.UPDATE_GROUPS_PER_SERVER.ENABLED || Storage.ConfigSections.Settings.UPDATE_GROUPS_PER_WORLD.ENABLED) {
final String contextValue = Storage.getLoader().getPlayerServerName(uuid);
if (contextValue != null) {
builder.add("server", contextValue).add("world", contextValue);
}
}
return user.getCachedData().getPermissionData(QueryOptions.contextual(builder.build())).getPermissionMap();
}
public static void setPermissions(UUID uuid) {
Map<String, Boolean> permissions = getPermissions(uuid);
if (permissions == null) return;
permissions.forEach((permission, permitted) -> {
if (permission.startsWith("proantitab.") || permission.equals("*"))
@@ -67,7 +82,7 @@ public class LuckPermsAdapter {
return;
}
if (Reflection.getMinor() >= 13)
if (Reflection.isAtLeast(1, 13))
BukkitAntiTabListener.handleTabCompletion(uuid);
}
@@ -92,10 +107,11 @@ public class LuckPermsAdapter {
if (event.isUser() && event.getTarget() instanceof User) {
User user = (User) event.getTarget();
UUID uuid = user.getUniqueId();
String serverName = Storage.getLoader().getPlayerServerName(uuid);
if (Reflection.isProxyServer()) {
PermissionUtil.reloadPermissions(user.getUniqueId());
Communicator.sendUpdateCommand(uuid);
Communicator.Proxy2Backend.sendUpdateCommand(uuid, serverName);
if (Reflection.isVelocityServer()) {
VelocityLoader.delayedPlayerReload(uuid);
@@ -41,12 +41,13 @@ public class MessageTranslator {
for (Map.Entry<Character, String> entry : colors.entrySet())
endingColors.put(entry.getKey(), "</" + entry.getValue().substring(1));
support = !Storage.USE_SIMPLECLOUD && (Reflection.getMinor() >= 18 || Reflection.isProxyServer());
support = !Reflection.isCraftbukkit() && (Reflection.isAtLeast(1, 18) || Reflection.isProxyServer());
if(support)
if (support) {
translator = Reflection.isVelocityServer() ? new VelocityMessageTranslator()
: Reflection.isProxyServer() ? new BungeeMessageTranslator()
: new BukkitMessageTranslator();
}
}
public static String translateLegacy(String text) {
@@ -128,7 +129,7 @@ public class MessageTranslator {
: sender.getName();
String token = (Storage.ConfigSections.Settings.HANDLE_THROUGH_PROXY.ENABLED || Reflection.isProxyServer())
? Storage.TOKEN
? Storage.CENSORED_TOKEN
: "/";
String serverName = Storage.SERVER_NAME == null ? "/" : Storage.SERVER_NAME;
@@ -141,6 +142,7 @@ public class MessageTranslator {
"%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
);
@@ -73,7 +73,14 @@ public class BukkitCommandNodeHelper {
}
public void spareRecursively(List<String> spares) throws Exception {
spareRecursively("", root, spares);
final Set<String> sparesSet = new HashSet<>(spares.stream().map(StringUtils::getFirstArg).toList());
for (String childName : sparesSet) {
Node child = root.getChild(childName);
if (child != null) {
spareRecursively(child.getName(), child, spares);
}
}
}
private void spareRecursively(String str, Node parent, List<String> spares) throws Exception {
@@ -88,12 +95,6 @@ public class BukkitCommandNodeHelper {
}
for (final Node child : children) {
if (parent.isRoot()) {
spareRecursively(child.getName(), child, spares);
continue;
}
final String command = str + " " + child.getName();
final String[] commandArgs = command.split(" ");
@@ -146,7 +147,7 @@ public class BukkitCommandNodeHelper {
final int max = args.length - 1;
final int nextIndex = index + 1;
if (index > max || nextIndex > max) {
if (parent == null || index > max || nextIndex > max) {
return;
}
@@ -150,8 +150,13 @@ public class ProxyCommandNodeHelper<T> {
String part = args[index];
if (index == 0)
if (index == 0) {
part = Storage.Blacklist.BlockTypeFetcher.modify(Storage.Blacklist.BlockTypeFetcher.modify(part));
}
if (part.length() > 1 && part.startsWith("%") && part.endsWith("%")) {
return;
}
String next = index + 1 >= args.length ? null : args[index + 1];
CommandNode<T> childNode = parent.getChild(part);
@@ -1,5 +1,6 @@
package de.rayzs.pat.utils.response;
import de.rayzs.pat.api.communication.Communicator;
import de.rayzs.pat.plugin.subarguments.SubArguments;
import de.rayzs.pat.plugin.logger.Logger;
import de.rayzs.pat.api.storage.Storage;
@@ -106,11 +107,11 @@ public class ResponseHandler {
return replaceArgsVariables(input, command);
}
public static List<String> getResponse(UUID uuid, String input) {
return getResponse(uuid, input, Storage.ConfigSections.Settings.CANCEL_COMMAND.SUB_COMMAND_RESPONSE.getLines());
public static List<String> getResponse(UUID uuid, String playerName, String serverName, String input) {
return getResponse(uuid, playerName, serverName, input, Storage.ConfigSections.Settings.CANCEL_COMMAND.SUB_COMMAND_RESPONSE.getLines());
}
public static List<String> getResponse(UUID uuid, String input, List<String> defaultMessage) {
public static List<String> getResponse(UUID uuid, String playerName, String serverName, String input, List<String> defaultMessage) {
final String finalInput = input.startsWith("/") && input.length() > 1
? input.substring(1)
: input;
@@ -124,7 +125,7 @@ public class ResponseHandler {
}).findFirst();
if (uuid != null && optionalResponse.isPresent()) {
optionalResponse.get().executeAction(uuid, finalInput);
optionalResponse.get().executeAction(uuid, playerName, serverName, finalInput);
return new ArrayList<>(optionalResponse.get().message)
.stream().map(s -> replaceArgsVariables(s, finalInput))
@@ -144,10 +145,16 @@ public class ResponseHandler {
this.actions = (List<String>) Storage.Files.CUSTOM_RESPONSES.getOrSet(key + ".actions", new ArrayList<>());
}
public void executeAction(UUID uuid, String command) {
public void executeAction(UUID uuid, String playerName, String serverName, String command) {
String[] split;
for (String action : actions) {
if (action.equals("alert")) {
ActionHandler.alert(uuid, playerName, serverName, command);
continue;
}
if (!action.contains("::")) {
Logger.warning("! Could not recognise action: " + action);
Logger.warning(" > Syntax does not match at all. Have you used the splitters (::) correctly?");
@@ -291,9 +298,11 @@ public class ResponseHandler {
Logger.warning(" > Here's an example to compare with:");
Logger.warning(" > console::command");
Logger.warning(" > e.g: console::say Hello world!");
continue;
}
ActionHandler.executeConsoleCommand(action, uuid, command, split[1]);
continue;
case "execute":
if (split.length == 1) {
@@ -302,9 +311,11 @@ public class ResponseHandler {
Logger.warning(" > Here's an example to compare with:");
Logger.warning(" > execute::command");
Logger.warning(" > e.g: execute::help");
continue;
}
ActionHandler.executePlayerCommand(action, uuid, command, split[1]);
continue;
case "actionbar":
if (split.length == 1) {
@@ -313,9 +324,114 @@ public class ResponseHandler {
Logger.warning(" > Here's an example to compare with:");
Logger.warning(" > actionbar::text");
Logger.warning(" > e.g: actionbar::I like COOKIES");
continue;
}
ActionHandler.sendActionbar(action, uuid, command, split[1]);
continue;
case "p2b-message":
if (!Reflection.isProxyServer()) {
Logger.warning("! Could not execute action: " + action);
Logger.warning(" > Cannot send p2b-packets on a backend server!");
Logger.warning(" > This only works on proxy servers!");
Logger.warning(" > P2B -> Proxy to Backend");
continue;
}
if (serverName == null) {
Logger.warning("! Failed to read action: " + action);
Logger.warning(" > Failed to fetch servername player is on!");
continue;
}
if (split.length == 1) {
Logger.warning("! Failed to read action: " + action);
Logger.warning(" > Action requires 1 arguments but only has " + split.length);
Logger.warning(" > Here's an example to compare with:");
Logger.warning(" > p2b-message::text");
Logger.warning(" > e.g: p2b-message::&cUser %player% is evil!");
continue;
}
Communicator.Proxy2Backend.sendConsoleMessage(
serverName,
ResponseHandler.replaceArgsVariables(
StringUtils.replace(split[1], "%player%", playerName),
command
)
);
continue;
case "p2b-execute":
if (!Reflection.isProxyServer()) {
Logger.warning("! Could not execute action: " + action);
Logger.warning(" > Cannot send p2b-packets on a backend server!");
Logger.warning(" > This only works on proxy servers!");
Logger.warning(" > P2B -> Proxy to Backend");
continue;
}
if (serverName == null) {
Logger.warning("! Failed to read action: " + action);
Logger.warning(" > Failed to fetch servername player is on!");
continue;
}
if (split.length == 1) {
Logger.warning("! Failed to read action: " + action);
Logger.warning(" > Action requires 1 arguments but only has " + split.length);
Logger.warning(" > Here's an example to compare with:");
Logger.warning(" > p2b-execute::command");
Logger.warning(" > e.g: p2b-execute::help");
continue;
}
Communicator.Proxy2Backend.sendExecutePlayerCommand(
serverName,
uuid,
ResponseHandler.replaceArgsVariables(
StringUtils.replace(split[1], "%player%", playerName),
command
)
);
continue;
case "p2b-console":
if (!Reflection.isProxyServer()) {
Logger.warning("! Could not execute action: " + action);
Logger.warning(" > Cannot send p2b-packets on a backend server!");
Logger.warning(" > This only works on proxy servers!");
Logger.warning(" > P2B -> Proxy to Backend");
continue;
}
if (serverName == null) {
Logger.warning("! Failed to read action: " + action);
Logger.warning(" > Failed to fetch servername player is on!");
continue;
}
if (split.length == 1) {
Logger.warning("! Failed to read action: " + action);
Logger.warning(" > Action requires 1 arguments but only has " + split.length);
Logger.warning(" > Here's an example to compare with:");
Logger.warning(" > p2b-console::command");
Logger.warning(" > e.g: p2b-console::help");
continue;
}
Communicator.Proxy2Backend.sendExecuteConsoleCommand(
serverName,
ResponseHandler.replaceArgsVariables(
StringUtils.replace(split[1], "%player%", playerName),
command
)
);
}
}
@@ -1,5 +1,12 @@
package de.rayzs.pat.utils.response.action;
import de.rayzs.pat.api.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 java.util.List;
import java.util.UUID;
public interface Action {
@@ -11,4 +18,29 @@ public interface Action {
void playSound(String action, UUID uuid, String soundName, float volume, float pitch);
void sendActionbar(String action, UUID uuid, String command, String message);
default void alert(UUID uuid, String playerName, String serverName, String command) {
command = command.startsWith("/") ? command.substring(1) : command;
command = StringUtils.getFirstArg(command);
final String displayCommand = StringUtils.replaceTriggers(command, "", "\\", "<", ">", "&");
final List<String> notificationMessage = MessageTranslator.replaceMessageList(
Storage.ConfigSections.Messages.NOTIFICATION.ALERT,
"%player%", playerName,
"%command%", displayCommand,
"%server%", serverName);
Communicator.Proxy2Backend.sendNotification(uuid, serverName, displayCommand);
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);
}
});
}
}
@@ -8,7 +8,7 @@ public class ActionHandler {
private static final Action ACTION = Reflection.isProxyServer() ? Reflection.isVelocityServer()
? new VelocityAction() : new BungeeAction()
: Reflection.getMinor() <= 16
: Reflection.isAtMost(1, 16)
? new OldBukkitAction() : new ModernBukkitAction();
public static void initialize() {}
@@ -36,4 +36,8 @@ public class ActionHandler {
public static void sendActionbar(String action, UUID uuid, String command, String message) {
ACTION.sendActionbar(action, uuid, command, message);
}
public static void alert(UUID uuid, String playerName, String serverName, String command) {
ACTION.alert(uuid, playerName, serverName, command);
}
}
@@ -2,9 +2,16 @@ package de.rayzs.pat.utils.scheduler;
import de.rayzs.pat.utils.scheduler.impl.*;
import de.rayzs.pat.utils.Reflection;
import org.bukkit.entity.Player;
public class PATScheduler {
public static void execute(Runnable runnable, Player player) {
if (Reflection.isFoliaServer())
new FoliaScheduler().getInstance(runnable, player);
else createScheduler(runnable);
}
public static PATSchedulerTask createScheduler(Runnable runnable, long time, long period) {
return Reflection.isFoliaServer()
? new FoliaScheduler().getInstance(false, runnable, time, period)
@@ -1,5 +1,7 @@
package de.rayzs.pat.utils.scheduler;
import org.bukkit.entity.Player;
public interface PATSchedulerTask {
PATSchedulerTask getInstance(boolean async, Runnable runnable, long time, long period);
@@ -3,6 +3,7 @@ package de.rayzs.pat.utils.scheduler.impl;
import de.rayzs.pat.utils.scheduler.PATSchedulerTask;
import de.rayzs.pat.plugin.BukkitLoader;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public class BukkitScheduler implements PATSchedulerTask {
@@ -4,6 +4,7 @@ import de.rayzs.pat.utils.scheduler.PATSchedulerTask;
import io.papermc.paper.threadedregions.scheduler.*;
import de.rayzs.pat.plugin.BukkitLoader;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public class FoliaScheduler implements PATSchedulerTask {
@@ -11,6 +12,15 @@ public class FoliaScheduler implements PATSchedulerTask {
private ScheduledTask task;
public void getInstance(Runnable runnable, Player player) {
if (player == null) {
SCHEDULER.execute(BukkitLoader.getPlugin(), runnable);
} else {
player.getScheduler().run(BukkitLoader.getPlugin(), scheduledTask -> runnable.run(), null);
}
}
@Override
public PATSchedulerTask getInstance(boolean async, Runnable runnable, long time, long period) {
this.task = SCHEDULER.runAtFixedRate(BukkitLoader.getPlugin(), __ -> runnable.run(), time, period);
@@ -1,6 +1,7 @@
package de.rayzs.pat.utils.sender.impl;
import de.rayzs.pat.api.storage.Storage;
import de.rayzs.pat.utils.Reflection;
import de.rayzs.pat.utils.message.MessageTranslator;
import de.rayzs.pat.utils.sender.CommandSenderAbstract;
import de.rayzs.pat.utils.sender.CommandSenderHandler;
@@ -108,6 +109,17 @@ public class BukkitSender extends CommandSenderAbstract {
return;
}
// To prevent color-code overlapping on Bukkit consoles.
if (Reflection.isCraftbukkit() && isConsole()) {
String[] lines = message.split("\n");
for (String line : lines) {
sender.sendMessage(MessageTranslator.replaceMessage(sender, line));
}
return;
}
sender.sendMessage(MessageTranslator.replaceMessage(sender, message));
}
}
+1 -1
View File
@@ -3,7 +3,7 @@ description: Hides more than just your plugins.
website: https://www.rayzs.de/products/proantitab/page
author: Rayzs_YT
version: 2.2.1
version: 2.3.2
main: de.rayzs.pat.plugin.BungeeLoader
softDepends: [LuckPerms, PAPIProxyBridge]
@@ -41,6 +41,14 @@ handle-through-proxy:
enabled: false
token: insert-token-of-proxy-here
# Enabling this allows you to remotely execute
# console/player commands and send console messages from
# the proxy to a backend server.
#
# It's only for all the p2b actions inside the custom-responses.yml
# and is disabled by default as a security measurement.
allow-p2b-actions: false
# Advanced option:
# Loads the token from an ENV variable instead.
# (!) Warning: Do NOT enable this option, unless you know what you're doing!
@@ -161,6 +169,8 @@ custom-plugins:
commands:
- pl
- plugins
- bukkit:pl
- bukkit:plugins
message:
- '&fPlugins (0):'
@@ -178,6 +188,9 @@ custom-version:
- about
- version
- ver
- bukkit:about
- bukkit:version
- bukkit:ver
message:
- '&fThis server is running CraftBukkit version git-NasaSpigot-294 (MC: X)'
@@ -205,6 +218,17 @@ patch-exploits:
alert-message: '%prefix% &4%player% &ctried to crash/lag the server.'
kick-message: '&cFailed to read packet! Please reconnect.'
# Small extra option on how to respond to players who failed
# the injection process. ONLY necessary for those who are using
# a "spoofer plugins" which creates fake players with a corrupt
# pipeline and does not provide any information on if a player is
# spoofed or not.
injection-failed:
kick-on-failure: true
suppress-exceptions: false
kick-message: '&cInjection process failed! Please reconnect.'
console-message: '&cInjection process failed! (%player%)'
#>> HTP (Overwritten)
# This feature allows you to customize your server brand you see when you press F3.
# Normally there is something like 'Purpur', or 'Spigot'.
@@ -319,6 +343,7 @@ info:
proxy-sync:
time: '&e%time%'
waiting: '&cWaiting to establish connection...'
disabled: '&cDisabled!'
message:
@@ -326,6 +351,7 @@ info:
- '&7 Version: &e%current_version%'
- '&7 Status: %version_status%'
- '&7 Last sync with proxy: %sync_time%'
- '&7 Last received alive packet: %last_alive_response%'
- '&7 Proxy sync-token: &e%token%'
- '&7 Proxy-received server name: &e%sync_server_name%'
@@ -6,16 +6,19 @@
# custom-responses.yml
#
# Here you can configure a few of the blocked commands a bit further.
# But what exactly is this here? Every command that would normally respond with the typical "command is blocked" message, can be configured in here!
# And how does it work? It's simple. You just provide the a trigger of the command that would be normally blocked.
# Commands that would normally work won't send the messages you have set here.
# This way PAT can offer you full control over certain commands and their normal responses.
# But what exactly does that mean? Well, this simply means that you can create unique custom-responses
# for certain or even all commands that are blocked by PAT.
# Just add the commands that you want your custom response for that would be blocked by PAT
# and make your boring blocked-message more unique! :D
#
# ----------------------------------------------------------------------
#
# What are these action section at each block?
# This is an additional feature to make your responses much more alive.
# Example actions that can be used are the following:
# Send alert notification:
# Syntax: alert
# Example: alert
# Execute console command:
# Syntax: console::command
# Example: console::say %player% is an evil player
@@ -35,7 +38,7 @@
# Syntax: effect::potionEffect::duration::amplifier
# Example: effect::BLINDNESS::45::1
# Possible variable:
# Variables to work with:
# %args[from-to]% to get the command arguments
# Example if you've typed: /shop open gui user
# A:
@@ -56,10 +59,14 @@
# Here are a few examples:
# Example for all blocked commands.
# In here we only trigger this response in any case.
# This applies to all commands, as well as sub-commands,
# This applies to all commands as well as sub-arguments,
# unless you have specified another custom response.
# (!) Make sure to put this custom-response on the very bottom of all
# your custom-responses, since PAT iterates through each
# custom-response by order. Otherwise, this one will
# override all the custom-responses below.
#example-with-everything:
# triggers:
# - "*"
@@ -69,10 +76,25 @@
# - "actionbar::&cSorry %player%, but this command is blocked."
# - "sound::ENTITY_ENDER_DRAGON_GROWL::1.0::1.0"
# Example for only one command and all its sub-arguments.
# Only triggers if "help" or "help ..." is executed and also blocked by PAT.
#example-with-help:
# triggers:
# - "help"
# - "help *"
# message:
# - "&aSorry, but help isn't here."
# actions:
# - "actionbar::&aSorry %player%, but there's no help."
# - "sound::ENTITY_ENDER_DRAGON_GROWL::1.0::1.0"
# Example with kits.
# In here we only trigger the given message, if the player would type "/kit ...".
# If this command would work through sub-arguments, then the player would only able to execute the command with the
# listed sub-arguments assigned to it. Everything else will result with the set message in there.
# Only triggers if the player executes the "kit" command with a sub-argument that
# is blocked by PAT.
# --
#example-with-kits:
# triggers:
@@ -82,10 +104,10 @@
# actions:
# - "actionbar::&cSorry %player%, but this kit does not exist!"
# Here another example with an auctionhouse plugin.
# In here we only trigger the given message, if the player would type "/ah plugin".
# Normally it would print out the "command is blocked" message, because PAT would have blocked it in our case.
# Therefore, we can also assign a custom response message to it.
# Only triggers when "ah plugin" is executed and also blocked by PAT:
# ---
#example-with-auctionhouse:
# triggers:
+37 -3
View File
@@ -56,6 +56,19 @@ base-command-case-sensitive: true
# inside a PAT group.
allow-group-overruling: false
# Enabling this updates player groups on each server switch, meaning you can
# give a user the permission to a PAT group with a server context to only
# give the player the PAT group when he's on a certain server.
#
# Example command:
# lpv (...) permission set proantitab.group.<group> server=<server>
update-groups-per-server: 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
# Here you can customize the server version that is displayed on a ping. (The text at the player-count)
custom-protocol-ping:
enabled: true
@@ -129,6 +142,8 @@ custom-plugins:
commands:
- pl
- plugins
- bukkit:pl
- bukkit:plugins
message:
- '&fPlugins (0):'
@@ -145,6 +160,9 @@ custom-version:
- about
- version
- ver
- bukkit:about
- bukkit:version
- bukkit:ver
message:
- '&fThis server is running CraftBukkit version git-NasaSpigot-294 (MC: X)'
@@ -157,14 +175,30 @@ block-namespace-commands:
# 'cancel-blocked-commands' is enabled or not.
always-block-command: true
# Auto lowercase all commands when being executed,
# such that something like /PAY turns into /pay.
auto-lowercase-commands:
enabled: false
# Patches a small exploit which causes the server to lag.
# Due to the fact that PAT interacts directly with Tab-Completions and their packets,
# it would be a waste not to provide some simple patches like these. ^^
patch-exploits:
enabled: true
suppress-exceptions: false
alert-message: '%prefix% &4%player% &ctried to crash/lag the server.'
kick-message: '&cFailed to read packet! Please reconnect.'
# Small extra option on how to respond to players who failed
# the injection process. ONLY necessary for those who are using
# a "spoofer plugins" which creates fake players with a corrupt
# pipeline and does not provide any information on if a player is
# spoofed or not.
injection-failed:
kick-on-failure: true
kick-message: '&cInjection process failed! Please reconnect.'
console-message: '&cInjection process failed! (%player%)'
# This feature allows you to customize your server brand you see when you press F3.
# Normally there is something like 'Purpur', or 'Spigot'.
# With this feature, you are able to change and even animate it.
@@ -291,13 +325,13 @@ info:
- '&7 Proxy sync-token: &e%token%'
stats:
fail: '&cThis command works on Bungeecord/Velocity servers only!'
no-server: '&cNone!'
message:
splitter: '&7, '
server: '&f%servername% &8(%updated%)'
server: '&f%servername% &8(&a%last_alive_response% &8/ &2%updated%&8)'
statistic:
- '&7Last sync sent to &f%server_count% &7servers. &8&o(%last_sync_time% ago)'
- '&7Format: &eserver (last alive packet / last sync packet)'
- '&7Last sync sent to &f%server_count% &7server(s) &e%last_sync_time% &7ago:'
- '&7Sent to servers: &f%servers%'
server-list:
@@ -6,22 +6,25 @@
# custom-responses.yml
#
# Here you can configure a few of the blocked commands a bit further.
# But what exactly is this here? Every command that would normally respond with the typical "command is blocked" message, can be configured in here!
# And how does it work? It's simple. You just provide the a trigger of the command that would be normally blocked.
# Commands that would normally work won't send the messages you have set here.
# This way PAT can offer you full control over certain commands and their normal responses.
# But what exactly does that mean? Well, this simply means that you can create unique custom-responses
# for certain or even all commands that are blocked by PAT.
# Just add the commands that you want your custom response for that would be blocked by PAT
# and make your boring blocked-message more unique! :D
#
# ----------------------------------------------------------------------
#
# What are these action section at each block?
# This is an additional feature to make your responses much more alive.
# Example actions that can be used are the following:
# Send alert notification:
# Syntax: alert
# Example: alert
# Execute console command:
# Syntax: console::command
# Example: console::send %player% fallback
# Example: console::send %player% lobby
# Execute player command:
# Syntax: execute::command
# Example: execute::help
# Example: execute::server lobby
# Send actionbar:
# Syntax: actionbar::text
# Example: actionbar::&cThis is not cool %player%!
@@ -31,8 +34,17 @@
# Play sound: (Available sounds: https://www.digminecraft.com/lists/sound_list_pc.php)
# Syntax: sound::soundName::volume::pitch
# Example: sound::entity.ender_dragon.growl::1.0::1.0
# Send console message to backend server:
# Syntax: p2b-message::text
# Example: p2b-message::&cPlayer &4%player% &cdid something bad.
# Execute console command on backend:
# Syntax: p2b-console::command
# Example: p2b-console::tp %player% 0 0 0
# Execute player command on backend:
# Syntax: p2b-execute::command
# Example: p2b-execute::help
# Possible variable:
# Variables to work with:
# %args[from-to]% to get the command arguments
# Example if you've typed: /shop open gui user
# A:
@@ -53,10 +65,14 @@
# Here are a few examples:
# Example for all blocked commands.
# In here we only trigger this response in any case.
# This applies to all commands, as well as sub-commands,
# This applies to all commands as well as sub-arguments,
# unless you have specified another custom response.
# (!) Make sure to put this custom-response on the very bottom of all
# your custom-responses, since PAT iterates through each
# custom-response by order. Otherwise, this one will
# override all the custom-responses below.
#example-with-everything:
# triggers:
# - "*"
@@ -64,12 +80,27 @@
# - "&cI'm blocked"
# actions:
# - "actionbar::&cSorry %player%, but this command is blocked."
# - "sound::entity.ender_dragon.growl::1.0::1.0"
# - "sound::ENTITY_ENDER_DRAGON_GROWL::1.0::1.0"
# Example for only one command and all its sub-arguments.
# Only triggers if "help" or "help ..." is executed and also blocked by PAT.
#example-with-help:
# triggers:
# - "help"
# - "help *"
# message:
# - "&aSorry, but help isn't here."
# actions:
# - "actionbar::&aSorry %player%, but there's no help."
# - "sound::ENTITY_ENDER_DRAGON_GROWL::1.0::1.0"
# Example with kits.
# In here we only trigger the given message, if the player would type "/kit ...".
# If this command would work through sub-arguments, then the player would only able to execute the command with the
# listed sub-arguments assigned to it. Everything else will result with the set message in there.
# Only triggers if the player executes the "kit" command with a sub-argument that
# is blocked by PAT.
# --
#example-with-kits:
# triggers:
@@ -79,10 +110,10 @@
# actions:
# - "actionbar::&cSorry %player%, but this kit does not exist!"
# Here another example with an auctionhouse plugin.
# In here we only trigger the given message, if the player would type "/ah plugin".
# Normally it would print out the "command is blocked" message, because PAT would have blocked it in our case.
# Therefore, we can also assign a custom response message to it.
# Only triggers when "ah plugin" is executed and also blocked by PAT:
# ---
#example-with-auctionhouse:
# triggers:
@@ -91,5 +122,6 @@
# - "&cThis sub-command does not exist. Please type: &e/ah help"
# actions:
# - "console::say That's not nice %player%!"
# - "title::Hey!::You can't do that %player%!::30::3000::30"
# - "actionbar::Nop, sorry %player%"
# - "sound::entity.ender_dragon.growl::1.0::1.0"
# - "title::&cHey!::&cYou can't do that %player%!::5::20::5"
# - "actionbar::&cNop, sorry %player%"
+1 -1
View File
@@ -3,7 +3,7 @@ description: Hides more than just your plugins.
website: https://www.rayzs.de/products/proantitab/page
author: Rayzs_YT
version: 2.2.1
version: 2.3.2
api-version: 1.13
folia-supported: true
main: de.rayzs.pat.plugin.BukkitLoader