diff --git a/paper/build.gradle.kts b/paper/build.gradle.kts index e72b7c1..a8bf9a2 100644 --- a/paper/build.gradle.kts +++ b/paper/build.gradle.kts @@ -32,7 +32,7 @@ dependencies { tasks { shadowJar { - archiveFileName.set("AuthMeVelocity-Paper-${project.version}.jar") + archiveBaseName.set("AuthMeVelocity-Paper") archiveClassifier.set("") relocate("net.byteflux.libby", "io.github._4drian3d.authmevelocity.libs.libby") diff --git a/paper/src/main/resources/paper-plugin.yml b/paper/src/main/resources/paper-plugin.yml index 270131c..ffe73ba 100644 --- a/paper/src/main/resources/paper-plugin.yml +++ b/paper/src/main/resources/paper-plugin.yml @@ -1,6 +1,7 @@ name: AuthMeVelocity version: '${version}' main: io.github._4drian3d.authmevelocity.paper.AuthMeVelocityPlugin +bootstrapper: io.github._4drian3d.authmevelocity.paper.AuthMeVelocityBootstrap description: AuthMeReloaded Support for Velocity authors: - xQuickGlare diff --git a/velocity/build.gradle.kts b/velocity/build.gradle.kts index 15202b7..684f788 100644 --- a/velocity/build.gradle.kts +++ b/velocity/build.gradle.kts @@ -39,7 +39,7 @@ tasks { shadowJar { duplicatesStrategy = DuplicatesStrategy.EXCLUDE - archiveFileName.set("AuthMeVelocity-Proxy-${project.version}.jar") + archiveBaseName.set("AuthMeVelocity-Velocity") archiveClassifier.set("") relocate("org.bstats", "io.github._4drian3d.authmevelocity.libs.bstats") diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/AuthMeVelocityPlugin.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/AuthMeVelocityPlugin.java index 2b9f69e..0eca487 100644 --- a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/AuthMeVelocityPlugin.java +++ b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/AuthMeVelocityPlugin.java @@ -20,7 +20,6 @@ package io.github._4drian3d.authmevelocity.velocity; import com.google.inject.Inject; import com.google.inject.Injector; import com.velocitypowered.api.command.CommandSource; -import com.velocitypowered.api.event.EventManager; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.proxy.ProxyInitializeEvent; import com.velocitypowered.api.plugin.Dependency; @@ -40,10 +39,16 @@ import io.github._4drian3d.authmevelocity.common.LibsManager; import io.github._4drian3d.authmevelocity.common.configuration.ConfigurationContainer; import io.github._4drian3d.authmevelocity.common.configuration.ProxyConfiguration; import io.github._4drian3d.authmevelocity.velocity.commands.AuthMeCommand; -import io.github._4drian3d.authmevelocity.velocity.listener.ConnectListener; -import io.github._4drian3d.authmevelocity.velocity.listener.FastLoginListener; -import io.github._4drian3d.authmevelocity.velocity.listener.PluginMessageListener; -import io.github._4drian3d.authmevelocity.velocity.listener.ProxyListener; +import io.github._4drian3d.authmevelocity.velocity.listener.Listener; +import io.github._4drian3d.authmevelocity.velocity.listener.compat.FastLoginListener; +import io.github._4drian3d.authmevelocity.velocity.listener.connection.DisconnectListener; +import io.github._4drian3d.authmevelocity.velocity.listener.connection.InitialServerListener; +import io.github._4drian3d.authmevelocity.velocity.listener.connection.PostConnectListener; +import io.github._4drian3d.authmevelocity.velocity.listener.connection.PreConnectListener; +import io.github._4drian3d.authmevelocity.velocity.listener.data.PluginMessageListener; +import io.github._4drian3d.authmevelocity.velocity.listener.input.ChatListener; +import io.github._4drian3d.authmevelocity.velocity.listener.input.CommandListener; +import io.github._4drian3d.authmevelocity.velocity.listener.input.TabCompleteListener; import net.byteflux.libby.VelocityLibraryManager; import net.kyori.adventure.text.minimessage.MiniMessage; import org.bstats.charts.SimplePie; @@ -84,8 +89,6 @@ public final class AuthMeVelocityPlugin implements AuthMeVelocityAPI { @Inject private ProxyServer proxy; @Inject - private EventManager eventManager; - @Inject private PluginManager pluginManager; @Inject private Logger logger; @@ -123,17 +126,22 @@ public final class AuthMeVelocityPlugin implements AuthMeVelocityAPI { proxy.getChannelRegistrar().register(MODERN_CHANNEL, LEGACY_CHANNEL); Stream.of( - ProxyListener.class, - ConnectListener.class, - PluginMessageListener.class + PluginMessageListener.class, + DisconnectListener.class, + InitialServerListener.class, + PostConnectListener.class, + PreConnectListener.class, + ChatListener.class, + CommandListener.class, + TabCompleteListener.class ).map(injector::getInstance) - .forEach(listener -> eventManager.register(this, listener)); + .forEach(Listener::register); final boolean fastlogin = pluginManager.isLoaded("fastlogin"); metrics.addCustomChart(new SimplePie("fastlogin_compatibility", () -> Boolean.toString(fastlogin))); if (fastlogin) { logDebug("Register FastLogin compatibility"); - eventManager.register(this, injector.getInstance(FastLoginListener.class)); + injector.getInstance(FastLoginListener.class).register(); } final boolean miniplaceholders = pluginManager.isLoaded("miniplaceholders"); diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/ConnectListener.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/ConnectListener.java deleted file mode 100644 index 57dcfc9..0000000 --- a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/ConnectListener.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2023 AuthMeVelocity Contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package io.github._4drian3d.authmevelocity.velocity.listener; - -import com.google.common.io.ByteArrayDataOutput; -import com.google.common.io.ByteStreams; -import com.google.inject.Inject; -import com.velocitypowered.api.event.Continuation; -import com.velocitypowered.api.event.PostOrder; -import com.velocitypowered.api.event.Subscribe; -import com.velocitypowered.api.event.player.PlayerChooseInitialServerEvent; -import com.velocitypowered.api.event.player.ServerPostConnectEvent; -import com.velocitypowered.api.event.player.ServerPreConnectEvent; -import com.velocitypowered.api.proxy.Player; -import com.velocitypowered.api.proxy.ProxyServer; -import com.velocitypowered.api.proxy.ServerConnection; -import com.velocitypowered.api.proxy.server.RegisteredServer; -import io.github._4drian3d.authmevelocity.common.configuration.ProxyConfiguration; -import io.github._4drian3d.authmevelocity.velocity.AuthMeVelocityPlugin; -import io.github._4drian3d.authmevelocity.velocity.utils.AuthMeUtils; -import io.github._4drian3d.authmevelocity.velocity.utils.Pair; -import org.slf4j.Logger; - -import java.util.Optional; - -public final class ConnectListener { - @Inject - private ProxyServer proxy; - @Inject - private Logger logger; - @Inject - private AuthMeVelocityPlugin plugin; - - @Subscribe(order = PostOrder.LATE) - public void onInitialServer( - final PlayerChooseInitialServerEvent event, - Continuation continuation - ) { - if (!plugin.config().get().ensureAuthServer().ensureFirstServerIsAuthServer()) { - continuation.resume(); - plugin.logDebug("PlayerChooseInitialServerEvent | Not enabled"); - return; - } - - final Optional optionalSV = event.getInitialServer(); - if (optionalSV.isPresent() && plugin.isAuthServer(optionalSV.get())) { - continuation.resume(); - plugin.logDebug("PlayerChooseInitialServerEvent | Player is in auth server"); - return; - } - final ProxyConfiguration config = plugin.config().get(); - final Pair server = AuthMeUtils.serverToSend( - config.ensureAuthServer().sendMode(), proxy, config.authServers(), config.advanced().randomAttempts()); - - // Velocity takes over in case the initial server is not present - event.setInitialServer(server.object()); - continuation.resume(); - if (server.isEmpty()) { - plugin.logDebug("PlayerChooseInitialServerEvent | Null server"); - logger.error("Cannot send the player {} to an auth server", event.getPlayer().getUsername()); - } - } - - @Subscribe - public void onServerPreConnect( - final ServerPreConnectEvent event, - final Continuation continuation - ) { - if (plugin.isLogged(event.getPlayer())) { - plugin.logDebug("ServerPreConnectEvent | Player already logged"); - continuation.resume(); - return; - } - - final RegisteredServer server = event.getResult().getServer().orElse(null); - if (server == null) { - plugin.logDebug("ServerPreConnectEvent | Null Server"); - continuation.resume(); - return; - } - // this should be present, "event.getResult().isAllowed()" is the "isPresent" check - if (!plugin.isAuthServer(server)) { - plugin.logDebug("ServerPreConnectEvent | Server "+server.getServerInfo().getName()+" is not an auth server"); - event.setResult(ServerPreConnectEvent.ServerResult.denied()); - } else { - plugin.logDebug("ServerPreConnectEvent | Server "+server.getServerInfo().getName()+" is an auth server"); - } - continuation.resume(); - } - - @SuppressWarnings("UnstableApiUsage") - @Subscribe - public void onServerPostConnect(final ServerPostConnectEvent event) { - final Player player = event.getPlayer(); - - final boolean isLogged = plugin.isLogged(player); - plugin.logDebug("ServerPostConnectEvent | Player "+player.getUsername()+" is logged: " + isLogged); - final RegisteredServer server = player.getCurrentServer().map(ServerConnection::getServer).orElse(null); - if (server == null) { - plugin.logDebug("ServerPostConnectEvent | Player "+player.getUsername()+" is not in a server"); - return; - } - final boolean isInAuthServer = plugin.isInAuthServer(player); - plugin.logDebug("ServerPostConnectEvent | Player "+player.getUsername()+" is in AuthServer: " + isInAuthServer); - - if (!(isLogged && isInAuthServer)) { - return; - } - - plugin.logDebug("ServerPostConnectEvent | Already logged player and connected to an Auth server"); - final ByteArrayDataOutput buf = ByteStreams.newDataOutput(); - buf.writeUTF("LOGIN"); - - final byte[] byteArray = buf.toByteArray(); - plugin.logDebug("ServerPostConnectEvent | Sending LOGIN data"); - if (server.sendPluginMessage(AuthMeVelocityPlugin.MODERN_CHANNEL, byteArray)) { - plugin.logDebug("ServerPostConnectEvent | Correctly send data"); - } else { - plugin.logDebug("ServerPostConnectEvent | Failed to send data"); - } - } -} diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/Listener.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/Listener.java new file mode 100644 index 0000000..cecd96c --- /dev/null +++ b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/Listener.java @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2023 AuthMeVelocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github._4drian3d.authmevelocity.velocity.listener; + +import com.velocitypowered.api.event.AwaitingEventExecutor; + +public interface Listener extends AwaitingEventExecutor { + void register(); +} diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/PluginMessageListener.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/PluginMessageListener.java deleted file mode 100644 index 4630ccf..0000000 --- a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/PluginMessageListener.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2023 AuthMeVelocity Contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package io.github._4drian3d.authmevelocity.velocity.listener; - -import com.google.common.io.ByteArrayDataInput; -import com.google.inject.Inject; -import com.velocitypowered.api.event.Continuation; -import com.velocitypowered.api.event.EventManager; -import com.velocitypowered.api.event.Subscribe; -import com.velocitypowered.api.event.connection.PluginMessageEvent; -import com.velocitypowered.api.proxy.Player; -import com.velocitypowered.api.proxy.ProxyServer; -import com.velocitypowered.api.proxy.ServerConnection; -import com.velocitypowered.api.proxy.server.RegisteredServer; -import io.github._4drian3d.authmevelocity.api.velocity.event.*; -import io.github._4drian3d.authmevelocity.common.MessageType; -import io.github._4drian3d.authmevelocity.common.configuration.ProxyConfiguration; -import io.github._4drian3d.authmevelocity.velocity.AuthMeVelocityPlugin; -import io.github._4drian3d.authmevelocity.velocity.utils.AuthMeUtils; -import io.github._4drian3d.authmevelocity.velocity.utils.Pair; -import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; - -import java.util.Locale; - -public class PluginMessageListener { - @Inject - private ProxyServer proxy; - @Inject - private EventManager eventManager; - @Inject - private Logger logger; - @Inject - private AuthMeVelocityPlugin plugin; - - @Subscribe - public void onPluginMessage(final PluginMessageEvent event, Continuation continuation) { - final boolean cancelled = !event.getResult().isAllowed() - || !(event.getSource() instanceof ServerConnection) - || !(event.getIdentifier().equals(AuthMeVelocityPlugin.MODERN_CHANNEL) - || event.getIdentifier().equals(AuthMeVelocityPlugin.LEGACY_CHANNEL)); - if (cancelled) { - continuation.resume(); - plugin.logDebug("PluginMessageEvent | Not allowed"); - return; - } - - final ServerConnection connection = (ServerConnection) event.getSource(); - - event.setResult(PluginMessageEvent.ForwardResult.handled()); - - final ByteArrayDataInput input = event.dataAsDataStream(); - final String message = input.readUTF(); - final MessageType type = MessageType.valueOf( - message.toUpperCase(Locale.ROOT)); - final String name = input.readUTF(); - final @Nullable Player player = proxy.getPlayer(name).orElse(null); - - switch (type) { - case LOGIN -> { - plugin.logDebug("PluginMessageEvent | Login type"); - if (player != null && plugin.addPlayer(player)) { - eventManager.fireAndForget(new ProxyLoginEvent(player)); - if (plugin.config().get().sendOnLogin().sendToServerOnLogin()) { - this.createServerConnectionRequest(player, connection); - } - plugin.logDebug("PluginMessageEvent | Player not null"); - } - } - case LOGOUT -> { - plugin.logDebug("PluginMessageEvent | Logout type"); - if (player != null && plugin.removePlayer(player)){ - eventManager.fireAndForget(new ProxyLogoutEvent(player)); - plugin.logDebug("PluginMessageEvent | Player not null"); - } - } - case REGISTER -> { - plugin.logDebug("PluginMessageEvent | Register"); - if (player != null) { - eventManager.fireAndForget(new ProxyRegisterEvent(player)); - plugin.logDebug("PluginMessageEvent | Player not null"); - } - } - case UNREGISTER -> { - plugin.logDebug("PluginMessageEvent | Unregister type"); - if (player != null) { - plugin.logDebug("PluginMessageEvent | Player not null"); - eventManager.fireAndForget(new ProxyUnregisterEvent(player)); - } - } - case FORCE_UNREGISTER -> { - eventManager.fireAndForget(new ProxyForcedUnregisterEvent(player)); - plugin.logDebug("PluginMessageEvent | Forced Unregister type"); - } - - } - continuation.resume(); - } - - private void createServerConnectionRequest(Player player, ServerConnection connection){ - final RegisteredServer loginServer = player.getCurrentServer().orElse(connection).getServer(); - - final ProxyConfiguration config = plugin.config().get(); - - final Pair toSend = AuthMeUtils.serverToSend( - config.sendOnLogin().sendMode(), proxy, config.sendOnLogin().teleportServers(), config.advanced().randomAttempts()); - - if (toSend.isEmpty()) { - if (toSend.string() != null) { - logger.warn("The server {} does not exist", toSend.string()); - } else { - logger.warn("There is not valid server to send"); - } - return; - } - - eventManager.fire(new PreSendOnLoginEvent(player, loginServer, toSend.object())) - .thenAccept(event -> { - if (!event.getResult().isAllowed()) { - return; - } - player.createConnectionRequest(event.getResult().getServer()) - .connect() - .thenAcceptAsync(result -> { - if (!result.isSuccessful()) { - logger.info("Unable to connect the player {} to the server {}", - player.getUsername(), - result.getAttemptedConnection().getServerInfo().getName()); - } - }); - }); - } -} diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/ProxyListener.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/ProxyListener.java deleted file mode 100644 index 8447e7c..0000000 --- a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/ProxyListener.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2023 AuthMeVelocity Contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package io.github._4drian3d.authmevelocity.velocity.listener; - -import com.google.inject.Inject; -import com.velocitypowered.api.event.Continuation; -import com.velocitypowered.api.event.EventTask; -import com.velocitypowered.api.event.PostOrder; -import com.velocitypowered.api.event.Subscribe; -import com.velocitypowered.api.event.command.CommandExecuteEvent; -import com.velocitypowered.api.event.connection.DisconnectEvent; -import com.velocitypowered.api.event.player.PlayerChatEvent; -import com.velocitypowered.api.event.player.TabCompleteEvent; -import com.velocitypowered.api.proxy.Player; -import io.github._4drian3d.authmevelocity.velocity.AuthMeVelocityPlugin; -import io.github._4drian3d.authmevelocity.velocity.utils.AuthMeUtils; -import net.kyori.adventure.text.minimessage.MiniMessage; - -public final class ProxyListener { - @Inject - private AuthMeVelocityPlugin plugin; - - @Subscribe - public EventTask onDisconnect(final DisconnectEvent event) { - if (event.getLoginStatus() == DisconnectEvent.LoginStatus.CONFLICTING_LOGIN) { - return null; - } - - return EventTask.async(() -> plugin.removePlayer(event.getPlayer())); - } - - @Subscribe(order = PostOrder.FIRST) - public void onCommandExecute(final CommandExecuteEvent event, Continuation continuation) { - if (!(event.getCommandSource() instanceof final Player player)){ - plugin.logDebug("CommandExecuteEvent | CommandSource is not a player"); - continuation.resume(); - return; - } - - if (plugin.isLogged(player)) { - plugin.logDebug("CommandExecuteEvent | Player is already logged"); - continuation.resume(); - return; - } - - if (plugin.isInAuthServer(player)) { - plugin.logDebug("CommandExecuteEvent | Player is in Auth Server"); - String command = AuthMeUtils.getFirstArgument(event.getCommand()); - if (!plugin.config().get().commands().allowedCommands().contains(command)) { - plugin.logDebug("CommandExecuteEvent | Player executed an blocked command"); - sendBlockedMessage(player); - event.setResult(CommandExecuteEvent.CommandResult.denied()); - } - } else { - plugin.logDebug("CommandExecuteEven | Player is not in auth server"); - sendBlockedMessage(player); - event.setResult(CommandExecuteEvent.CommandResult.denied()); - } - continuation.resume(); - } - - @Subscribe(order = PostOrder.FIRST) - public void onPlayerChat(final PlayerChatEvent event, Continuation continuation) { - if (plugin.isLogged(event.getPlayer())) { - plugin.logDebug("PlayerChatEvent | Player is already logged"); - continuation.resume(); - return; - } - - plugin.logDebug("PlayerChatEvent | Player is not logged"); - - event.setResult(PlayerChatEvent.ChatResult.denied()); - continuation.resume(); - } - - @Subscribe(order = PostOrder.FIRST) - public void onTabComplete(TabCompleteEvent event){ - if (plugin.isLogged(event.getPlayer())) { - plugin.logDebug("TabCompleteEvent | Player is already logged"); - return; - } - - final String command = event.getPartialMessage(); - for (final String allowed : plugin.config().get().commands().allowedCommands()) { - if (allowed.startsWith(command)) { - return; - } - } - - plugin.logDebug("TabCompleteEvent | Not allowed tab-completion"); - event.getSuggestions().clear(); - } - - void sendBlockedMessage(Player player){ - String blockedMessage = plugin.config().get().commands().blockedCommandMessage(); - if (!blockedMessage.isBlank()){ - player.sendMessage(MiniMessage.miniMessage().deserialize(blockedMessage)); - } - } - -} diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/FastLoginListener.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/compat/FastLoginListener.java similarity index 58% rename from velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/FastLoginListener.java rename to velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/compat/FastLoginListener.java index 7781575..28863c1 100644 --- a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/FastLoginListener.java +++ b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/compat/FastLoginListener.java @@ -15,23 +15,31 @@ * along with this program. If not, see . */ -package io.github._4drian3d.authmevelocity.velocity.listener; +package io.github._4drian3d.authmevelocity.velocity.listener.compat; import com.github.games647.fastlogin.velocity.event.VelocityFastLoginAutoLoginEvent; import com.google.inject.Inject; -import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.EventTask; import com.velocitypowered.api.proxy.ProxyServer; import io.github._4drian3d.authmevelocity.velocity.AuthMeVelocityPlugin; +import io.github._4drian3d.authmevelocity.velocity.listener.Listener; -public class FastLoginListener { +public final class FastLoginListener implements Listener { @Inject private ProxyServer proxy; @Inject private AuthMeVelocityPlugin plugin; - @Subscribe - public void onAutoLogin(VelocityFastLoginAutoLoginEvent event){ - plugin.logDebug("VelocityFastLoginAutoLoginEvent | Attempt to auto register player"); - proxy.getPlayer(event.getProfile().getName()).ifPresent(plugin::addPlayer); + @Override + public void register() { + proxy.getEventManager().register(plugin, VelocityFastLoginAutoLoginEvent.class, this); + } + + @Override + public EventTask executeAsync(final VelocityFastLoginAutoLoginEvent event) { + return EventTask.async(() -> { + plugin.logDebug("VelocityFastLoginAutoLoginEvent | Attempt to auto register player"); + proxy.getPlayer(event.getProfile().getName()).ifPresent(plugin::addPlayer); + }); } } diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/connection/DisconnectListener.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/connection/DisconnectListener.java new file mode 100644 index 0000000..7029ff9 --- /dev/null +++ b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/connection/DisconnectListener.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2023 AuthMeVelocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github._4drian3d.authmevelocity.velocity.listener.connection; + +import com.google.inject.Inject; +import com.velocitypowered.api.event.EventManager; +import com.velocitypowered.api.event.EventTask; +import com.velocitypowered.api.event.connection.DisconnectEvent; +import io.github._4drian3d.authmevelocity.velocity.AuthMeVelocityPlugin; +import io.github._4drian3d.authmevelocity.velocity.listener.Listener; +import org.checkerframework.checker.nullness.qual.Nullable; + +public final class DisconnectListener implements Listener { + @Inject + private AuthMeVelocityPlugin plugin; + @Inject + private EventManager eventManager; + + @Override + public void register() { + eventManager.register(plugin, DisconnectEvent.class, this); + } + + @Override + public @Nullable EventTask executeAsync(final DisconnectEvent event) { + if (event.getLoginStatus() == DisconnectEvent.LoginStatus.CONFLICTING_LOGIN) { + return null; + } + + return EventTask.async(() -> plugin.removePlayer(event.getPlayer())); + } +} diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/connection/InitialServerListener.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/connection/InitialServerListener.java new file mode 100644 index 0000000..28150fb --- /dev/null +++ b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/connection/InitialServerListener.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2023 AuthMeVelocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github._4drian3d.authmevelocity.velocity.listener.connection; + +import com.google.inject.Inject; +import com.velocitypowered.api.event.EventManager; +import com.velocitypowered.api.event.EventTask; +import com.velocitypowered.api.event.PostOrder; +import com.velocitypowered.api.event.player.PlayerChooseInitialServerEvent; +import com.velocitypowered.api.proxy.ProxyServer; +import com.velocitypowered.api.proxy.server.RegisteredServer; +import io.github._4drian3d.authmevelocity.common.configuration.ProxyConfiguration; +import io.github._4drian3d.authmevelocity.velocity.AuthMeVelocityPlugin; +import io.github._4drian3d.authmevelocity.velocity.listener.Listener; +import io.github._4drian3d.authmevelocity.velocity.utils.AuthMeUtils; +import io.github._4drian3d.authmevelocity.velocity.utils.Pair; +import org.slf4j.Logger; + +import java.util.Optional; + +public final class InitialServerListener implements Listener { + @Inject + private AuthMeVelocityPlugin plugin; + @Inject + private EventManager eventManager; + @Inject + private ProxyServer proxy; + @Inject + private Logger logger; + + @Override + public void register() { + eventManager.register(plugin, PlayerChooseInitialServerEvent.class, PostOrder.LATE, this); + } + + @Override + public EventTask executeAsync(final PlayerChooseInitialServerEvent event) { + return EventTask.withContinuation(continuation -> { + final ProxyConfiguration config = plugin.config().get(); + if (!config.ensureAuthServer().ensureFirstServerIsAuthServer()) { + continuation.resume(); + plugin.logDebug("PlayerChooseInitialServerEvent | Not enabled"); + return; + } + + final Optional optionalSV = event.getInitialServer(); + if (optionalSV.isPresent() && plugin.isAuthServer(optionalSV.get())) { + continuation.resume(); + plugin.logDebug("PlayerChooseInitialServerEvent | Player is in auth server"); + return; + } + + final Pair server = AuthMeUtils.serverToSend( + config.ensureAuthServer().sendMode(), proxy, config.authServers(), config.advanced().randomAttempts()); + + // Velocity takes over in case the initial server is not present + event.setInitialServer(server.object()); + continuation.resume(); + if (server.isEmpty()) { + plugin.logDebug("PlayerChooseInitialServerEvent | Null server"); + logger.error("Cannot send the player {} to an auth server", event.getPlayer().getUsername()); + } + }); + } +} diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/connection/PostConnectListener.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/connection/PostConnectListener.java new file mode 100644 index 0000000..8730b3d --- /dev/null +++ b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/connection/PostConnectListener.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2023 AuthMeVelocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github._4drian3d.authmevelocity.velocity.listener.connection; + +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; +import com.google.inject.Inject; +import com.velocitypowered.api.event.EventManager; +import com.velocitypowered.api.event.EventTask; +import com.velocitypowered.api.event.player.ServerPostConnectEvent; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.ServerConnection; +import com.velocitypowered.api.proxy.server.RegisteredServer; +import io.github._4drian3d.authmevelocity.velocity.AuthMeVelocityPlugin; +import io.github._4drian3d.authmevelocity.velocity.listener.Listener; + +public final class PostConnectListener implements Listener { + @Inject + private AuthMeVelocityPlugin plugin; + @Inject + private EventManager eventManager; + + @Override + public void register() { + eventManager.register(plugin, ServerPostConnectEvent.class, this); + } + + @Override + public EventTask executeAsync(final ServerPostConnectEvent event) { + return EventTask.async(() -> { + final Player player = event.getPlayer(); + + final boolean isLogged = plugin.isLogged(player); + plugin.logDebug("ServerPostConnectEvent | Player "+player.getUsername()+" is logged: " + isLogged); + final RegisteredServer server = player.getCurrentServer().map(ServerConnection::getServer).orElse(null); + if (server == null) { + plugin.logDebug("ServerPostConnectEvent | Player "+player.getUsername()+" is not in a server"); + return; + } + final boolean isInAuthServer = plugin.isInAuthServer(player); + plugin.logDebug("ServerPostConnectEvent | Player "+player.getUsername()+" is in AuthServer: " + isInAuthServer); + + if (!(isLogged && isInAuthServer)) { + return; + } + + plugin.logDebug("ServerPostConnectEvent | Already logged player and connected to an Auth server"); + final ByteArrayDataOutput buf = ByteStreams.newDataOutput(); + buf.writeUTF("LOGIN"); + + final byte[] byteArray = buf.toByteArray(); + plugin.logDebug("ServerPostConnectEvent | Sending LOGIN data"); + if (server.sendPluginMessage(AuthMeVelocityPlugin.MODERN_CHANNEL, byteArray)) { + plugin.logDebug("ServerPostConnectEvent | Correctly send data"); + } else { + plugin.logDebug("ServerPostConnectEvent | Failed to send data"); + } + }); + } +} diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/connection/PreConnectListener.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/connection/PreConnectListener.java new file mode 100644 index 0000000..d055e57 --- /dev/null +++ b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/connection/PreConnectListener.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2023 AuthMeVelocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github._4drian3d.authmevelocity.velocity.listener.connection; + +import com.google.inject.Inject; +import com.velocitypowered.api.event.EventManager; +import com.velocitypowered.api.event.EventTask; +import com.velocitypowered.api.event.player.ServerPreConnectEvent; +import com.velocitypowered.api.proxy.server.RegisteredServer; +import io.github._4drian3d.authmevelocity.velocity.AuthMeVelocityPlugin; +import io.github._4drian3d.authmevelocity.velocity.listener.Listener; + +public final class PreConnectListener implements Listener { + @Inject + private AuthMeVelocityPlugin plugin; + @Inject + private EventManager eventManager; + + @Override + public void register() { + eventManager.register(plugin, ServerPreConnectEvent.class, this); + } + + @Override + public EventTask executeAsync(final ServerPreConnectEvent event) { + return EventTask.withContinuation(continuation -> { + if (plugin.isLogged(event.getPlayer())) { + plugin.logDebug("ServerPreConnectEvent | Player already logged"); + continuation.resume(); + return; + } + + final RegisteredServer server = event.getResult().getServer().orElse(null); + if (server == null) { + plugin.logDebug("ServerPreConnectEvent | Null Server"); + continuation.resume(); + return; + } + // this should be present, "event.getResult().isAllowed()" is the "isPresent" check + if (!plugin.isAuthServer(server)) { + plugin.logDebug("ServerPreConnectEvent | Server "+server.getServerInfo().getName()+" is not an auth server"); + event.setResult(ServerPreConnectEvent.ServerResult.denied()); + } else { + plugin.logDebug("ServerPreConnectEvent | Server "+server.getServerInfo().getName()+" is an auth server"); + } + continuation.resume(); + }); + } +} diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/data/PluginMessageListener.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/data/PluginMessageListener.java new file mode 100644 index 0000000..093dc98 --- /dev/null +++ b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/data/PluginMessageListener.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2023 AuthMeVelocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github._4drian3d.authmevelocity.velocity.listener.data; + +import com.google.common.io.ByteArrayDataInput; +import com.google.inject.Inject; +import com.velocitypowered.api.event.EventManager; +import com.velocitypowered.api.event.EventTask; +import com.velocitypowered.api.event.connection.PluginMessageEvent; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.ProxyServer; +import com.velocitypowered.api.proxy.ServerConnection; +import com.velocitypowered.api.proxy.server.RegisteredServer; +import io.github._4drian3d.authmevelocity.api.velocity.event.*; +import io.github._4drian3d.authmevelocity.common.MessageType; +import io.github._4drian3d.authmevelocity.common.configuration.ProxyConfiguration; +import io.github._4drian3d.authmevelocity.velocity.AuthMeVelocityPlugin; +import io.github._4drian3d.authmevelocity.velocity.listener.Listener; +import io.github._4drian3d.authmevelocity.velocity.utils.AuthMeUtils; +import io.github._4drian3d.authmevelocity.velocity.utils.Pair; +import net.kyori.adventure.util.Index; +import org.slf4j.Logger; + +import java.util.Locale; + +public final class PluginMessageListener implements Listener { + private static final Index TYPES = Index.create(MessageType.class, Enum::toString); + @Inject + private ProxyServer proxy; + @Inject + private EventManager eventManager; + @Inject + private Logger logger; + @Inject + private AuthMeVelocityPlugin plugin; + + @Override + public void register() { + eventManager.register(plugin, PluginMessageEvent.class, this); + } + + @Override + public EventTask executeAsync(final PluginMessageEvent event) { + return EventTask.async(() -> { + final boolean cancelled = !event.getResult().isAllowed() + || !(event.getSource() instanceof ServerConnection) + || !(event.getIdentifier().equals(AuthMeVelocityPlugin.MODERN_CHANNEL) + || event.getIdentifier().equals(AuthMeVelocityPlugin.LEGACY_CHANNEL)); + if (cancelled) { + plugin.logDebug("PluginMessageEvent | Not allowed"); + return; + } + + final ServerConnection connection = (ServerConnection) event.getSource(); + + event.setResult(PluginMessageEvent.ForwardResult.handled()); + + final ByteArrayDataInput input = event.dataAsDataStream(); + final String message = input.readUTF(); + final MessageType type = TYPES.valueOrThrow(message.toUpperCase(Locale.ROOT)); + final String name = input.readUTF(); + final Player player = proxy.getPlayer(name).orElse(null); + + switch (type) { + case LOGIN -> { + plugin.logDebug("PluginMessageEvent | Login type"); + if (player != null && plugin.addPlayer(player)) { + eventManager.fireAndForget(new ProxyLoginEvent(player)); + if (plugin.config().get().sendOnLogin().sendToServerOnLogin()) { + this.createServerConnectionRequest(player, connection); + } + plugin.logDebug("PluginMessageEvent | Player not null"); + } + } + case LOGOUT -> { + plugin.logDebug("PluginMessageEvent | Logout type"); + if (player != null && plugin.removePlayer(player)){ + eventManager.fireAndForget(new ProxyLogoutEvent(player)); + plugin.logDebug("PluginMessageEvent | Player not null"); + } + } + case REGISTER -> { + plugin.logDebug("PluginMessageEvent | Register"); + if (player != null) { + eventManager.fireAndForget(new ProxyRegisterEvent(player)); + plugin.logDebug("PluginMessageEvent | Player not null"); + } + } + case UNREGISTER -> { + plugin.logDebug("PluginMessageEvent | Unregister type"); + if (player != null) { + plugin.logDebug("PluginMessageEvent | Player not null"); + eventManager.fireAndForget(new ProxyUnregisterEvent(player)); + } + } + case FORCE_UNREGISTER -> { + eventManager.fireAndForget(new ProxyForcedUnregisterEvent(player)); + plugin.logDebug("PluginMessageEvent | Forced Unregister type"); + } + + } + }); + } + + private void createServerConnectionRequest(final Player player, final ServerConnection connection){ + final RegisteredServer loginServer = player.getCurrentServer().orElse(connection).getServer(); + + final ProxyConfiguration config = plugin.config().get(); + + final Pair toSend = AuthMeUtils.serverToSend( + config.sendOnLogin().sendMode(), proxy, config.sendOnLogin().teleportServers(), config.advanced().randomAttempts()); + + if (toSend.isEmpty()) { + if (toSend.string() != null) { + logger.warn("The server {} does not exist", toSend.string()); + } else { + logger.warn("There is not valid server to send"); + } + return; + } + + eventManager.fire(new PreSendOnLoginEvent(player, loginServer, toSend.object())) + .thenAccept(event -> { + if (!event.getResult().isAllowed()) { + return; + } + player.createConnectionRequest(event.getResult().getServer()) + .connect() + .thenAcceptAsync(result -> { + if (!result.isSuccessful()) { + logger.info("Unable to connect the player {} to the server {}", + player.getUsername(), + result.getAttemptedConnection().getServerInfo().getName()); + } + }); + }); + } +} diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/input/ChatListener.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/input/ChatListener.java new file mode 100644 index 0000000..5d20f4a --- /dev/null +++ b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/input/ChatListener.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2023 AuthMeVelocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github._4drian3d.authmevelocity.velocity.listener.input; + +import com.google.inject.Inject; +import com.velocitypowered.api.event.EventManager; +import com.velocitypowered.api.event.EventTask; +import com.velocitypowered.api.event.PostOrder; +import com.velocitypowered.api.event.player.PlayerChatEvent; +import io.github._4drian3d.authmevelocity.velocity.AuthMeVelocityPlugin; +import io.github._4drian3d.authmevelocity.velocity.listener.Listener; + +public final class ChatListener implements Listener { + @Inject + private AuthMeVelocityPlugin plugin; + @Inject + private EventManager eventManager; + + @Override + public void register() { + eventManager.register(plugin, PlayerChatEvent.class, PostOrder.FIRST, this); + } + + @Override + public EventTask executeAsync(final PlayerChatEvent event) { + return EventTask.withContinuation(continuation -> { + if (plugin.isLogged(event.getPlayer())) { + plugin.logDebug("PlayerChatEvent | Player is already logged"); + continuation.resume(); + return; + } + + plugin.logDebug("PlayerChatEvent | Player is not logged"); + + event.setResult(PlayerChatEvent.ChatResult.denied()); + continuation.resume(); + }); + } +} diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/input/CommandListener.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/input/CommandListener.java new file mode 100644 index 0000000..2590428 --- /dev/null +++ b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/input/CommandListener.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2023 AuthMeVelocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github._4drian3d.authmevelocity.velocity.listener.input; + +import com.google.inject.Inject; +import com.velocitypowered.api.event.EventManager; +import com.velocitypowered.api.event.EventTask; +import com.velocitypowered.api.event.PostOrder; +import com.velocitypowered.api.event.command.CommandExecuteEvent; +import com.velocitypowered.api.proxy.Player; +import io.github._4drian3d.authmevelocity.velocity.AuthMeVelocityPlugin; +import io.github._4drian3d.authmevelocity.velocity.listener.Listener; +import io.github._4drian3d.authmevelocity.velocity.utils.AuthMeUtils; +import net.kyori.adventure.text.minimessage.MiniMessage; + +public final class CommandListener implements Listener { + @Inject + private EventManager eventManager; + @Inject + private AuthMeVelocityPlugin plugin; + + @Override + public void register() { + eventManager.register(plugin, CommandExecuteEvent.class, PostOrder.FIRST, this); + } + + @Override + public EventTask executeAsync(final CommandExecuteEvent event) { + return EventTask.withContinuation(continuation -> { + if (!(event.getCommandSource() instanceof final Player player)) { + plugin.logDebug("CommandExecuteEvent | CommandSource is not a player"); + continuation.resume(); + return; + } + + if (plugin.isLogged(player)) { + plugin.logDebug("CommandExecuteEvent | Player is already logged"); + continuation.resume(); + return; + } + + if (plugin.isInAuthServer(player)) { + plugin.logDebug("CommandExecuteEvent | Player is in Auth Server"); + final String command = AuthMeUtils.getFirstArgument(event.getCommand()); + if (!plugin.config().get().commands().allowedCommands().contains(command)) { + plugin.logDebug("CommandExecuteEvent | Player executed an blocked command"); + sendBlockedMessage(player); + event.setResult(CommandExecuteEvent.CommandResult.denied()); + } + } else { + plugin.logDebug("CommandExecuteEven | Player is not in auth server"); + sendBlockedMessage(player); + event.setResult(CommandExecuteEvent.CommandResult.denied()); + } + continuation.resume(); + }); + } + + private void sendBlockedMessage(Player player){ + String blockedMessage = plugin.config().get().commands().blockedCommandMessage(); + if (!blockedMessage.isBlank()){ + player.sendMessage(MiniMessage.miniMessage().deserialize(blockedMessage)); + } + } +} diff --git a/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/input/TabCompleteListener.java b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/input/TabCompleteListener.java new file mode 100644 index 0000000..f5e267f --- /dev/null +++ b/velocity/src/main/java/io/github/_4drian3d/authmevelocity/velocity/listener/input/TabCompleteListener.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2023 AuthMeVelocity Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package io.github._4drian3d.authmevelocity.velocity.listener.input; + +import com.google.inject.Inject; +import com.velocitypowered.api.event.EventManager; +import com.velocitypowered.api.event.EventTask; +import com.velocitypowered.api.event.PostOrder; +import com.velocitypowered.api.event.player.TabCompleteEvent; +import io.github._4drian3d.authmevelocity.velocity.AuthMeVelocityPlugin; +import io.github._4drian3d.authmevelocity.velocity.listener.Listener; + +public class TabCompleteListener implements Listener { + @Inject + private AuthMeVelocityPlugin plugin; + @Inject + private EventManager eventManager; + + @Override + public void register() { + eventManager.register(plugin, TabCompleteEvent.class, PostOrder.FIRST, this); + } + + @Override + public EventTask executeAsync(final TabCompleteEvent event) { + return EventTask.async(() -> { + if (plugin.isLogged(event.getPlayer())) { + plugin.logDebug("TabCompleteEvent | Player is already logged"); + return; + } + + final String command = event.getPartialMessage(); + for (final String allowed : plugin.config().get().commands().allowedCommands()) { + if (allowed.startsWith(command)) { + return; + } + } + + plugin.logDebug("TabCompleteEvent | Not allowed tab-completion"); + event.getSuggestions().clear(); + }); + } +}