diff --git a/velocity/pom.xml b/velocity/pom.xml index 4c5229f90..33e9da478 100644 --- a/velocity/pom.xml +++ b/velocity/pom.xml @@ -129,5 +129,14 @@ mariadb-java-client 2.7.4 + + + + + org.geysermc.floodgate + api + 2.0-SNAPSHOT + provided + diff --git a/velocity/src/main/java/com/github/games647/fastlogin/velocity/FastLoginVelocity.java b/velocity/src/main/java/com/github/games647/fastlogin/velocity/FastLoginVelocity.java index 68edf7a05..01f49ca91 100644 --- a/velocity/src/main/java/com/github/games647/fastlogin/velocity/FastLoginVelocity.java +++ b/velocity/src/main/java/com/github/games647/fastlogin/velocity/FastLoginVelocity.java @@ -62,6 +62,7 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.geysermc.floodgate.api.FloodgateApi; import org.slf4j.Logger; //TODO: Support for floodgate @@ -78,6 +79,7 @@ public class FastLoginVelocity implements PlatformPlugin { private FastLoginCore core; private AsyncScheduler scheduler; private UUID proxyId; + private FloodgateService floodgateService; @Inject public FastLoginVelocity(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) { @@ -96,6 +98,10 @@ public void onProxyInitialization(ProxyInitializeEvent event) { return; } + if (isPluginInstalled("floodgate")) { + floodgateService = new FloodgateService(FloodgateApi.getInstance(), core); + } + server.getEventManager().register(this, new ConnectListener(this, core.getRateLimiter())); server.getEventManager().register(this, new PluginMessageListener(this)); server.getChannelRegistrar().register(MinecraftChannelIdentifier.create(getName(), ChangePremiumMessage.CHANGE_CHANNEL)); @@ -141,7 +147,7 @@ public boolean isPluginInstalled(String name) { @Override public FloodgateService getFloodgateService() { - return null; + return floodgateService; } public FastLoginCore getCore() { diff --git a/velocity/src/main/java/com/github/games647/fastlogin/velocity/listener/ConnectListener.java b/velocity/src/main/java/com/github/games647/fastlogin/velocity/listener/ConnectListener.java index acb24c7b0..0d5852645 100644 --- a/velocity/src/main/java/com/github/games647/fastlogin/velocity/listener/ConnectListener.java +++ b/velocity/src/main/java/com/github/games647/fastlogin/velocity/listener/ConnectListener.java @@ -28,10 +28,12 @@ import com.github.games647.craftapi.UUIDAdapter; import com.github.games647.fastlogin.core.RateLimiter; import com.github.games647.fastlogin.core.StoredProfile; +import com.github.games647.fastlogin.core.hooks.FloodgateService; import com.github.games647.fastlogin.core.shared.LoginSession; import com.github.games647.fastlogin.velocity.FastLoginVelocity; import com.github.games647.fastlogin.velocity.VelocityLoginSession; import com.github.games647.fastlogin.velocity.task.AsyncPremiumCheck; +import com.github.games647.fastlogin.velocity.task.FloodgateAuthTask; import com.github.games647.fastlogin.velocity.task.ForceLoginTask; import com.velocitypowered.api.event.Continuation; import com.velocitypowered.api.event.Subscribe; @@ -43,6 +45,7 @@ import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.server.RegisteredServer; import com.velocitypowered.api.util.GameProfile; +import org.geysermc.floodgate.api.player.FloodgatePlayer; import java.util.ArrayList; import java.util.List; @@ -118,6 +121,16 @@ public void onServerConnected(ServerConnectedEvent serverConnectedEvent) { Player player = serverConnectedEvent.getPlayer(); RegisteredServer server = serverConnectedEvent.getServer(); + FloodgateService floodgateService = plugin.getFloodgateService(); + if (floodgateService != null) { + FloodgatePlayer floodgatePlayer = floodgateService.getFloodgatePlayer(player.getUniqueId()); + if (floodgatePlayer != null) { + Runnable floodgateAuthTask = new FloodgateAuthTask(plugin.getCore(), player, floodgatePlayer, server); + plugin.getScheduler().runAsync(floodgateAuthTask); + return; + } + } + VelocityLoginSession session = plugin.getSession().get(player.getRemoteAddress()); if (session == null) { return; diff --git a/velocity/src/main/java/com/github/games647/fastlogin/velocity/listener/PluginMessageListener.java b/velocity/src/main/java/com/github/games647/fastlogin/velocity/listener/PluginMessageListener.java index b9df0a8ae..79a987f2a 100644 --- a/velocity/src/main/java/com/github/games647/fastlogin/velocity/listener/PluginMessageListener.java +++ b/velocity/src/main/java/com/github/games647/fastlogin/velocity/listener/PluginMessageListener.java @@ -26,6 +26,7 @@ package com.github.games647.fastlogin.velocity.listener; import com.github.games647.fastlogin.core.StoredProfile; +import com.github.games647.fastlogin.core.hooks.FloodgateService; import com.github.games647.fastlogin.core.message.ChangePremiumMessage; import com.github.games647.fastlogin.core.message.SuccessMessage; import com.github.games647.fastlogin.core.shared.FastLoginCore; @@ -113,7 +114,15 @@ private void readMessage(Player forPlayer, String channel, byte[] data) { } private void onSuccessMessage(Player forPlayer) { - if (forPlayer.isOnlineMode()){ + boolean shouldPersist = forPlayer.isOnlineMode(); + + FloodgateService floodgateService = plugin.getFloodgateService(); + if (!shouldPersist && floodgateService != null) { + // always save floodgate players to lock this username + shouldPersist = floodgateService.isFloodgatePlayer(forPlayer.getUniqueId()); + } + + if (shouldPersist){ //bukkit module successfully received and force logged in the user //update only on success to prevent corrupt data VelocityLoginSession loginSession = plugin.getSession().get(forPlayer.getRemoteAddress()); diff --git a/velocity/src/main/java/com/github/games647/fastlogin/velocity/task/FloodgateAuthTask.java b/velocity/src/main/java/com/github/games647/fastlogin/velocity/task/FloodgateAuthTask.java new file mode 100644 index 000000000..d0350d90d --- /dev/null +++ b/velocity/src/main/java/com/github/games647/fastlogin/velocity/task/FloodgateAuthTask.java @@ -0,0 +1,86 @@ +/* + * SPDX-License-Identifier: MIT + * + * The MIT License (MIT) + * + * Copyright (c) 2015-2021 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.github.games647.fastlogin.velocity.task; + +import com.github.games647.fastlogin.core.shared.FastLoginCore; +import com.github.games647.fastlogin.core.shared.FloodgateManagement; +import com.github.games647.fastlogin.velocity.FastLoginVelocity; +import com.github.games647.fastlogin.velocity.VelocityLoginSession; +import com.velocitypowered.api.command.CommandSource; +import com.velocitypowered.api.proxy.Player; +import com.velocitypowered.api.proxy.server.RegisteredServer; +import org.geysermc.floodgate.api.player.FloodgatePlayer; + +import java.net.InetSocketAddress; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +public class FloodgateAuthTask + extends FloodgateManagement { + + private final RegisteredServer server; + + public FloodgateAuthTask(FastLoginCore core, Player player, + FloodgatePlayer floodgatePlayer, RegisteredServer server) { + super(core, player, floodgatePlayer); + this.server = server; + } + + @Override + protected void startLogin() { + VelocityLoginSession session = new VelocityLoginSession(player.getUsername(), isRegistered, profile); + core.getPlugin().getSession().put(player.getRemoteAddress(), session); + + // enable auto login based on the value of 'autoLoginFloodgate' in config.yml + boolean forcedOnlineMode = autoLoginFloodgate.equals("true") + || (autoLoginFloodgate.equals("linked") && isLinked); + + // delay sending force command, because Paper will process the login event asynchronously + // In this case it means that the force command (plugin message) is already received and processed while + // player is still in the login phase and reported to be offline. + Runnable loginTask = new ForceLoginTask(core.getPlugin().getCore(), player, server, session, forcedOnlineMode); + core.getPlugin().getProxy().getScheduler() + .buildTask(core.getPlugin(), () -> core.getPlugin().getScheduler().runAsync(loginTask)) + .delay(1L, TimeUnit.SECONDS) // Delay at least one second, otherwise the login command can be missed + .schedule(); + } + + @Override + protected String getName(Player player) { + return player.getUsername(); + } + + @Override + protected UUID getUUID(Player player) { + return player.getUniqueId(); + } + + @Override + protected InetSocketAddress getAddress(Player player) { + return player.getRemoteAddress(); + } + +}