diff --git a/velocity/pom.xml b/velocity/pom.xml index 47b1b263c..4d89bb6cb 100644 --- a/velocity/pom.xml +++ b/velocity/pom.xml @@ -129,6 +129,10 @@ velocity https://repo.papermc.io/repository/maven-public/ + + opencollab-snapshot + https://repo.opencollab.dev/main/ + @@ -153,5 +157,27 @@ mariadb-java-client 3.1.4 + + + + org.geysermc.geyser + core + ${geyser.version} + provided + + + * + * + + + + + + + org.geysermc.floodgate + api + ${floodgate.version} + 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 eee968735..9b1a591ed 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 @@ -27,6 +27,8 @@ import com.github.games647.fastlogin.core.AsyncScheduler; import com.github.games647.fastlogin.core.hooks.bedrock.BedrockService; +import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService; +import com.github.games647.fastlogin.core.hooks.bedrock.GeyserService; import com.github.games647.fastlogin.core.message.ChangePremiumMessage; import com.github.games647.fastlogin.core.message.ChannelMessage; import com.github.games647.fastlogin.core.message.SuccessMessage; @@ -50,6 +52,8 @@ import com.velocitypowered.api.proxy.messages.ChannelRegistrar; import com.velocitypowered.api.proxy.messages.MinecraftChannelIdentifier; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.geysermc.floodgate.api.FloodgateApi; +import org.geysermc.geyser.GeyserImpl; import org.slf4j.Logger; import java.io.IOException; @@ -76,6 +80,8 @@ public class FastLoginVelocity implements PlatformPlugin { private FastLoginCore core; private AsyncScheduler scheduler; + private FloodgateService floodgateService; + private GeyserService geyserService; private UUID proxyId; @Inject @@ -95,6 +101,14 @@ public void onProxyInitialization(ProxyInitializeEvent event) { return; } + if (isPluginInstalled("floodgate")) { + floodgateService = new FloodgateService(FloodgateApi.getInstance(), core); + } + + if (isPluginInstalled("Geyser-Velocity")) { + geyserService = new GeyserService(GeyserImpl.getInstance(), core); + } + server.getEventManager().register(this, new ConnectListener(this, core.getAntiBot())); server.getEventManager().register(this, new PluginMessageListener(this)); @@ -140,9 +154,21 @@ public boolean isPluginInstalled(String name) { return server.getPluginManager().isLoaded(name); } + public FloodgateService getFloodgateService() { + return floodgateService; + } + + public GeyserService getGeyserService() { + return geyserService; + } + @Override public BedrockService getBedrockService() { - return null; + if (floodgateService != null) { + return floodgateService; + } + + return geyserService; } 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 b38831425..c800d4778 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 @@ -30,10 +30,12 @@ import com.github.games647.fastlogin.core.antibot.AntiBotService.Action; import com.github.games647.fastlogin.core.shared.LoginSession; import com.github.games647.fastlogin.core.storage.StoredProfile; +import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService; 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.ForceLoginTask; +import com.github.games647.fastlogin.velocity.task.FloodgateAuthTask; import com.velocitypowered.api.event.Continuation; import com.velocitypowered.api.event.Subscribe; import com.velocitypowered.api.event.connection.DisconnectEvent; @@ -48,6 +50,7 @@ import com.velocitypowered.api.util.GameProfile.Property; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import org.geysermc.floodgate.api.player.FloodgatePlayer; import java.net.InetSocketAddress; import java.util.ArrayList; @@ -141,6 +144,16 @@ public void onServerConnected(ServerConnectedEvent serverConnectedEvent) { Player player = serverConnectedEvent.getPlayer(); RegisteredServer server = serverConnectedEvent.getServer(); + FloodgateService floodgateService = plugin.getFloodgateService(); + if (floodgateService != null) { + FloodgatePlayer floodgatePlayer = floodgateService.getBedrockPlayer(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 58e6a662d..4b7b51dfa 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 @@ -29,6 +29,7 @@ import com.github.games647.fastlogin.core.message.SuccessMessage; import com.github.games647.fastlogin.core.shared.FastLoginCore; import com.github.games647.fastlogin.core.storage.StoredProfile; +import com.github.games647.fastlogin.core.hooks.bedrock.FloodgateService; import com.github.games647.fastlogin.velocity.FastLoginVelocity; import com.github.games647.fastlogin.velocity.VelocityLoginSession; import com.github.games647.fastlogin.velocity.task.AsyncToggleMessage; @@ -115,7 +116,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.isBedrockPlayer(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..239983b4f --- /dev/null +++ b/velocity/src/main/java/com/github/games647/fastlogin/velocity/task/FloodgateAuthTask.java @@ -0,0 +1,85 @@ +/* + * SPDX-License-Identifier: MIT + * + * The MIT License (MIT) + * + * Copyright (c) 2015-2023 games647 and contributors + * + * 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(); + } +}