From 3741fffd23660ac8c913a18ecf2075e3d71a7b55 Mon Sep 17 00:00:00 2001 From: mdxd44 Date: Fri, 31 Dec 2021 04:09:11 +0900 Subject: Add floodgate support, release candidate 2. --- .../java/net/elytrium/limboauth/LimboAuth.java | 127 ++++++++++++++------- src/main/java/net/elytrium/limboauth/Settings.java | 29 ++++- .../limboauth/command/LimboAuthCommand.java | 8 +- .../java/net/elytrium/limboauth/config/Config.java | 18 ++- .../limboauth/floodgate/FloodgateApiHolder.java | 37 ++++++ .../elytrium/limboauth/listener/AuthListener.java | 36 ++++-- .../elytrium/limboauth/utils/UpdatesChecker.java | 2 +- 7 files changed, 189 insertions(+), 68 deletions(-) create mode 100644 src/main/java/net/elytrium/limboauth/floodgate/FloodgateApiHolder.java (limited to 'src/main/java/net/elytrium/limboauth') diff --git a/src/main/java/net/elytrium/limboauth/LimboAuth.java b/src/main/java/net/elytrium/limboauth/LimboAuth.java index a86f3c5..85c3b08 100644 --- a/src/main/java/net/elytrium/limboauth/LimboAuth.java +++ b/src/main/java/net/elytrium/limboauth/LimboAuth.java @@ -18,7 +18,6 @@ package net.elytrium.limboauth; import com.google.inject.Inject; -import com.google.inject.name.Named; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.dao.DaoManager; import com.j256.ormlite.field.FieldType; @@ -34,7 +33,6 @@ import com.velocitypowered.api.plugin.PluginContainer; import com.velocitypowered.api.plugin.annotation.DataDirectory; import com.velocitypowered.api.proxy.Player; import com.velocitypowered.api.proxy.ProxyServer; -import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; import java.io.File; import java.io.IOException; import java.net.InetAddress; @@ -54,6 +52,7 @@ import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -73,12 +72,14 @@ import net.elytrium.limboauth.command.LimboAuthCommand; import net.elytrium.limboauth.command.PremiumCommand; import net.elytrium.limboauth.command.TotpCommand; import net.elytrium.limboauth.command.UnregisterCommand; +import net.elytrium.limboauth.floodgate.FloodgateApiHolder; import net.elytrium.limboauth.handler.AuthSessionHandler; import net.elytrium.limboauth.listener.AuthListener; import net.elytrium.limboauth.model.RegisteredPlayer; import net.elytrium.limboauth.utils.UpdatesChecker; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; +import net.kyori.adventure.title.Title; import org.bstats.velocity.Metrics; import org.slf4j.Logger; @@ -87,13 +88,20 @@ import org.slf4j.Logger; name = "LimboAuth", version = BuildConstants.AUTH_VERSION, url = "https://elytrium.net/", - authors = {"hevav", "mdxd44"}, - dependencies = {@Dependency(id = "limboapi")} + authors = { + "hevav", + "mdxd44" + }, + dependencies = { + @Dependency(id = "limboapi"), + @Dependency(id = "floodgate", optional = true) + } ) -@SuppressFBWarnings({"EI_EXPOSE_REP", "MS_EXPOSE_REP"}) public class LimboAuth { - private static LimboAuth instance; + private final Map cachedAuthChecks = new ConcurrentHashMap<>(); + private final Map postLoginTasks = new ConcurrentHashMap<>(); + private final Set unsafePasswords = new HashSet<>(); private final HttpClient client = HttpClient.newHttpClient(); private final ProxyServer server; @@ -101,25 +109,27 @@ public class LimboAuth { private final Metrics.Factory metricsFactory; private final Path dataDirectory; private final LimboFactory factory; + private final FloodgateApiHolder floodgateApi; - private final Set unsafePasswords = new HashSet<>(); - private Map cachedAuthChecks; private Dao playerDao; private Pattern nicknameValidationPattern; private Limbo authServer; private Component nicknameInvalid; @Inject - @SuppressWarnings("OptionalGetWithoutIsPresent") - public LimboAuth(ProxyServer server, Logger logger, Metrics.Factory metricsFactory, - @Named("limboapi") PluginContainer factory, @DataDirectory Path dataDirectory) { - setInstance(this); - + public LimboAuth(ProxyServer server, Logger logger, Metrics.Factory metricsFactory, @DataDirectory Path dataDirectory) { this.server = server; this.logger = logger; this.metricsFactory = metricsFactory; this.dataDirectory = dataDirectory; - this.factory = (LimboFactory) factory.getInstance().get(); + + this.factory = (LimboFactory) this.server.getPluginManager().getPlugin("limboapi").flatMap(PluginContainer::getInstance).orElseThrow(); + + if (this.server.getPluginManager().getPlugin("floodgate").isPresent()) { + this.floodgateApi = new FloodgateApiHolder(); + } else { + this.floodgateApi = null; + } } @Subscribe @@ -136,17 +146,21 @@ public class LimboAuth { public void reload() throws Exception { Settings.IMP.reload(new File(this.dataDirectory.toFile().getAbsoluteFile(), "config.yml")); + if (this.floodgateApi == null && !Settings.IMP.MAIN.FLOODGATE_NEED_AUTH) { + throw new IllegalStateException("If you don't need to auth floodgate players please install floodgate plugin."); + } + if (Settings.IMP.MAIN.CHECK_PASSWORD_STRENGTH) { this.unsafePasswords.clear(); - Path unsafePasswordsFile = Paths.get(this.dataDirectory.toFile().getAbsolutePath(), Settings.IMP.MAIN.UNSAFE_PASSWORDS_FILE); - if (!unsafePasswordsFile.toFile().exists()) { - Files.copy(Objects.requireNonNull(this.getClass().getResourceAsStream("/unsafe_passwords.txt")), unsafePasswordsFile); + Path unsafePasswordsPath = Paths.get(this.dataDirectory.toFile().getAbsolutePath(), Settings.IMP.MAIN.UNSAFE_PASSWORDS_FILE); + if (!unsafePasswordsPath.toFile().exists()) { + Files.copy(Objects.requireNonNull(this.getClass().getResourceAsStream("/unsafe_passwords.txt")), unsafePasswordsPath); } - this.unsafePasswords.addAll(Files.lines(unsafePasswordsFile).collect(Collectors.toSet())); + this.unsafePasswords.addAll(Files.lines(unsafePasswordsPath).collect(Collectors.toSet())); } - this.cachedAuthChecks = new ConcurrentHashMap<>(); + this.cachedAuthChecks.clear(); Settings.DATABASE dbConfig = Settings.IMP.DATABASE; JdbcPooledConnectionSource connectionSource; @@ -205,7 +219,7 @@ public class LimboAuth { if (Settings.IMP.MAIN.ENABLE_TOTP) { manager.register("2fa", new TotpCommand(this.playerDao), "totp"); } - manager.register("limboauth", new LimboAuthCommand(), "la", "auth", "lauth"); + manager.register("limboauth", new LimboAuthCommand(this), "la", "auth", "lauth"); Settings.MAIN.AUTH_COORDS authCoords = Settings.IMP.MAIN.AUTH_COORDS; VirtualWorld authWorld = this.factory.createVirtualWorld( @@ -242,7 +256,7 @@ public class LimboAuth { this.nicknameInvalid = LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.NICKNAME_INVALID_KICK); this.server.getEventManager().unregisterListeners(this); - this.server.getEventManager().register(this, new AuthListener(this.playerDao)); + this.server.getEventManager().register(this, new AuthListener(this, this.playerDao)); Executors.newScheduledThreadPool(1, task -> new Thread(task, "purge-cache")).scheduleAtFixedRate(() -> this.checkCache(this.cachedAuthChecks, Settings.IMP.MAIN.PURGE_CACHE_MILLIS), @@ -282,7 +296,7 @@ public class LimboAuth { tables.forEach(t -> { try { String columnDefinition = t.getColumnDefinition(); - StringBuilder builder = new StringBuilder("ALTER TABLE `auth` ADD "); + StringBuilder builder = new StringBuilder("ALTER TABLE `AUTH` ADD "); List dummy = new ArrayList<>(); if (columnDefinition == null) { playerDao.getConnectionSource().getDatabaseType().appendColumnArg(t.getTableName(), builder, t, dummy, dummy, dummy, dummy); @@ -313,12 +327,11 @@ public class LimboAuth { public boolean needAuth(Player player) { String username = player.getUsername(); - if (!this.cachedAuthChecks.containsKey(username)) { return true; + } else { + return !this.cachedAuthChecks.get(username).getInetAddress().equals(player.getRemoteAddress().getAddress()); } - - return !this.cachedAuthChecks.get(username).getInetAddress().equals(player.getRemoteAddress().getAddress()); } public void authPlayer(Player player) { @@ -329,10 +342,41 @@ public class LimboAuth { } RegisteredPlayer registeredPlayer = AuthSessionHandler.fetchInfo(this.playerDao, nickname); - if (player.isOnlineMode()) { + boolean onlineMode = player.isOnlineMode(); + if (onlineMode || (!Settings.IMP.MAIN.FLOODGATE_NEED_AUTH && this.floodgateApi.isFloodgatePlayer(player.getUniqueId()))) { if (registeredPlayer == null || registeredPlayer.getHash().isEmpty()) { registeredPlayer = AuthSessionHandler.fetchInfo(this.playerDao, player.getUniqueId()); if (registeredPlayer == null || registeredPlayer.getHash().isEmpty()) { + // Due to the current connection state, which is set to LOGIN there, we cannot send the packets. + // We need to wait for the PLAY connection state to set. + this.postLoginTasks.put(player.getUniqueId(), () -> { + if (onlineMode) { + if (!Settings.IMP.MAIN.STRINGS.LOGIN_PREMIUM.isEmpty()) { + player.sendMessage(LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.LOGIN_PREMIUM)); + } + if (!Settings.IMP.MAIN.STRINGS.LOGIN_PREMIUM_TITLE.isEmpty() && !Settings.IMP.MAIN.STRINGS.LOGIN_PREMIUM_SUBTITLE.isEmpty()) { + player.showTitle( + Title.title( + LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.LOGIN_PREMIUM_TITLE), + LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.LOGIN_PREMIUM_SUBTITLE) + ) + ); + } + } else { + if (!Settings.IMP.MAIN.STRINGS.LOGIN_FLOODGATE.isEmpty()) { + player.sendMessage(LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.LOGIN_FLOODGATE)); + } + if (!Settings.IMP.MAIN.STRINGS.LOGIN_FLOODGATE_TITLE.isEmpty() && !Settings.IMP.MAIN.STRINGS.LOGIN_FLOODGATE_SUBTITLE.isEmpty()) { + player.showTitle( + Title.title( + LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.LOGIN_FLOODGATE_TITLE), + LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.LOGIN_FLOODGATE_SUBTITLE) + ) + ); + } + } + }); + this.factory.passLoginLimbo(player); return; } @@ -364,23 +408,24 @@ public class LimboAuth { public boolean isPremium(String nickname) { try { if (this.isPremiumExternal(nickname)) { - QueryBuilder query = this.playerDao.queryBuilder(); - query.where() + QueryBuilder premiumRegisteredQuery = this.playerDao.queryBuilder(); + premiumRegisteredQuery.where() .eq("LOWERCASENICKNAME", nickname.toLowerCase(Locale.ROOT)) .and() .ne("HASH", ""); - query.setCountOf(true); - QueryBuilder query2 = this.playerDao.queryBuilder(); - query2.where() + premiumRegisteredQuery.setCountOf(true); + + QueryBuilder premiumUnregisteredQuery = this.playerDao.queryBuilder(); + premiumUnregisteredQuery.where() .eq("LOWERCASENICKNAME", nickname.toLowerCase(Locale.ROOT)) .and() .eq("HASH", ""); - query2.setCountOf(true); + premiumUnregisteredQuery.setCountOf(true); + if (Settings.IMP.MAIN.ONLINE_MODE_NEED_AUTH) { - return this.playerDao.countOf(query.prepare()) == 0 - && this.playerDao.countOf(query2.prepare()) != 0; + return this.playerDao.countOf(premiumRegisteredQuery.prepare()) == 0 && this.playerDao.countOf(premiumUnregisteredQuery.prepare()) != 0; } else { - return this.playerDao.countOf(query.prepare()) == 0; + return this.playerDao.countOf(premiumRegisteredQuery.prepare()) == 0; } } else { return false; @@ -398,18 +443,14 @@ public class LimboAuth { .forEach(userMap::remove); } - private static void setInstance(LimboAuth instance) { - LimboAuth.instance = instance; - } - - public static LimboAuth getInstance() { - return instance; - } - public Set getUnsafePasswords() { return this.unsafePasswords; } + public Map getPostLoginTasks() { + return this.postLoginTasks; + } + public Logger getLogger() { return this.logger; } diff --git a/src/main/java/net/elytrium/limboauth/Settings.java b/src/main/java/net/elytrium/limboauth/Settings.java index f32279b..bbae307 100644 --- a/src/main/java/net/elytrium/limboauth/Settings.java +++ b/src/main/java/net/elytrium/limboauth/Settings.java @@ -48,7 +48,11 @@ public class Settings extends Config { public boolean CHECK_PASSWORD_STRENGTH = true; public String UNSAFE_PASSWORDS_FILE = "unsafe_passwords.txt"; public boolean ONLINE_MODE_NEED_AUTH = true; + @Comment("Needs floodgate plugin.") + public boolean FLOODGATE_NEED_AUTH = true; public boolean FORCE_OFFLINE_UUID = false; + @Comment("Delay in milliseconds before sending auth-confirming titles and messages to the player. (login-premium-title, login-floodgate, etc.)") + public int PREMIUM_AND_FLOODGATE_MESSAGES_DELAY = 1250; @Comment({ "Forcibly set player's UUID to the value from the database", "If the player had the cracked account, and switched to the premium account, the cracked UUID will be used." @@ -122,7 +126,7 @@ public class Settings extends Config { @Create public MAIN.STRINGS STRINGS; - @Comment("Leave title fields empty to disable.") + @Comment("You can left blank the fields marked with \"*\" comment.") public static class STRINGS { public String RELOAD = "{PRFX} &aReloaded successfully!"; @@ -142,13 +146,30 @@ public class Settings extends Config { public String BOSSBAR = "{PRFX} You have &6{0} &fseconds left to log in."; public String TIMES_UP = "{PRFX}{NL}&cAuthorization time is up."; + @Comment("*") + public String LOGIN_PREMIUM = "{PRFX} You've been logged in automatically using the premium account!"; + @Comment("*") + public String LOGIN_PREMIUM_TITLE = "{PRFX} Welcome!"; + @Comment("*") + public String LOGIN_PREMIUM_SUBTITLE = "&aYou has been logged in as premium player!"; + @Comment("*") + public String LOGIN_FLOODGATE = "{PRFX} You've been logged in automatically using the bedrock account!"; + @Comment("*") + public String LOGIN_FLOODGATE_TITLE = "{PRFX} Welcome!"; + @Comment("*") + public String LOGIN_FLOODGATE_SUBTITLE = "&aYou has been logged in as bedrock player!"; + public String LOGIN = "{PRFX} &aPlease, login using &6/login &a, you have &6{0} &aattempts."; public String LOGIN_WRONG_PASSWORD = "{PRFX} &cYou''ve entered the wrong password, you have &6{0} &cattempts left."; public String LOGIN_WRONG_PASSWORD_KICK = "{PRFX}{NL}&cYou've entered the wrong password numerous times!"; public String LOGIN_SUCCESSFUL = "{PRFX} &aSuccessfully logged in!"; + @Comment("*") public String LOGIN_TITLE = "&fPlease, login using &6/login &a."; + @Comment("*") public String LOGIN_SUBTITLE = "&aYou have &6{0} &aattempts."; + @Comment("*") public String LOGIN_SUCCESSFUL_TITLE = "{PRFX}"; + @Comment("*") public String LOGIN_SUCCESSFUL_SUBTITLE = "&aSuccessfully logged in!"; @Comment("Or if register-need-repeat-password set to false remove the \"\" part.") @@ -158,9 +179,13 @@ public class Settings extends Config { public String REGISTER_PASSWORD_TOO_LONG = "{PRFX} &cYou entered too long password, use a different one!"; public String REGISTER_PASSWORD_UNSAFE = "{PRFX} &cYour password is unsafe, use a different one!"; public String REGISTER_SUCCESSFUL = "{PRFX} &aSuccessfully registered!"; + @Comment("*") public String REGISTER_TITLE = "{PRFX}"; + @Comment("*") public String REGISTER_SUBTITLE = "&aPlease, register using &6/register "; + @Comment("*") public String REGISTER_SUCCESSFUL_TITLE = "{PRFX}"; + @Comment("*") public String REGISTER_SUCCESSFUL_SUBTITLE = "&aSuccessfully registered!"; public String UNREGISTER_SUCCESSFUL = "{PRFX}{NL}&aSuccessfully unregistered!"; @@ -186,7 +211,9 @@ public class Settings extends Config { public String FORCE_CHANGE_PASSWORD_USAGE = "{PRFX} Usage: &6/forcechangepassword "; public String TOTP = "{PRFX} Please, enter your 2FA key using &6/2fa "; + @Comment("*") public String TOTP_TITLE = "{PRFX}"; + @Comment("*") public String TOTP_SUBTITLE = "&aEnter your 2FA key using &6/2fa "; public String TOTP_SUCCESSFUL = "{PRFX} &aSuccessfully enabled 2FA!"; public String TOTP_DISABLED = "{PRFX} &aSuccessfully disabled 2FA!"; diff --git a/src/main/java/net/elytrium/limboauth/command/LimboAuthCommand.java b/src/main/java/net/elytrium/limboauth/command/LimboAuthCommand.java index 611b1c3..1465023 100644 --- a/src/main/java/net/elytrium/limboauth/command/LimboAuthCommand.java +++ b/src/main/java/net/elytrium/limboauth/command/LimboAuthCommand.java @@ -30,6 +30,12 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; public class LimboAuthCommand implements SimpleCommand { + private final LimboAuth plugin; + + public LimboAuthCommand(LimboAuth plugin) { + this.plugin = plugin; + } + @Override public List suggest(SimpleCommand.Invocation invocation) { CommandSource source = invocation.source(); @@ -57,7 +63,7 @@ public class LimboAuthCommand implements SimpleCommand { if (args.length == 1) { if (args[0].equalsIgnoreCase("reload") && source.hasPermission("limboauth.admin.reload")) { try { - LimboAuth.getInstance().reload(); + this.plugin.reload(); source.sendMessage(LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.RELOAD)); } catch (Exception e) { source.sendMessage(LegacyComponentSerializer.legacyAmpersand().deserialize(Settings.IMP.MAIN.STRINGS.RELOAD_FAILED)); diff --git a/src/main/java/net/elytrium/limboauth/config/Config.java b/src/main/java/net/elytrium/limboauth/config/Config.java index 1cb9803..6effa5d 100644 --- a/src/main/java/net/elytrium/limboauth/config/Config.java +++ b/src/main/java/net/elytrium/limboauth/config/Config.java @@ -39,13 +39,14 @@ import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.IntStream; -import net.elytrium.limboauth.LimboAuth; import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.yaml.snakeyaml.Yaml; public class Config { - private static final Logger LOGGER = LimboAuth.getInstance().getLogger(); + private final Logger logger = LoggerFactory.getLogger(Config.class); + private String oldPrefix = ""; private String currentPrefix = ""; @@ -76,7 +77,7 @@ public class Config { } } - LOGGER.debug("Failed to set config option: " + key + ": " + value + " | " + instance + " | " + root.getSimpleName() + ".yml"); + this.logger.debug("Failed to set config option: " + key + ": " + value + " | " + instance + " | " + root.getSimpleName() + ".yml"); } @SuppressWarnings("unchecked") @@ -109,7 +110,7 @@ public class Config { try (InputStreamReader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)) { this.set(new Yaml().load(reader), ""); } catch (IOException e) { - LOGGER.warn("Unable to load config ", e); + this.logger.warn("Unable to load config", e); return false; } @@ -211,7 +212,7 @@ public class Config { private void save(PrintWriter writer, Class clazz, Object instance, int indent) { try { String lineSeparator = System.lineSeparator(); - String spacing = this.repeat(" ", indent); + String spacing = IntStream.range(0, indent).mapToObj(i -> " ").collect(Collectors.joining()); for (Field field : clazz.getFields()) { if (field.getAnnotation(Ignore.class) != null) { @@ -271,7 +272,7 @@ public class Config { this.setAccessible(field); return field; } catch (Throwable ignored) { - LOGGER.debug("Invalid config field: " + this.join(split, ".") + " for " + this.toNodeName(instance.getClass().getSimpleName())); + this.logger.debug("Invalid config field: " + this.join(split, ".") + " for " + this.toNodeName(instance.getClass().getSimpleName())); return null; } } @@ -367,11 +368,6 @@ public class Config { } } - @SuppressWarnings("SameParameterValue") - private String repeat(String s, int n) { - return IntStream.range(0, n).mapToObj(i -> s).collect(Collectors.joining()); - } - @SuppressWarnings("SameParameterValue") private String join(Object[] array, String delimiter) { switch (array.length) { diff --git a/src/main/java/net/elytrium/limboauth/floodgate/FloodgateApiHolder.java b/src/main/java/net/elytrium/limboauth/floodgate/FloodgateApiHolder.java new file mode 100644 index 0000000..8832d4b --- /dev/null +++ b/src/main/java/net/elytrium/limboauth/floodgate/FloodgateApiHolder.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 Elytrium + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package net.elytrium.limboauth.floodgate; + +import java.util.UUID; +import org.geysermc.floodgate.api.FloodgateApi; + +/** + * Holder class for optional floodgate feature, we can't inject of optional plugins without holders due to Velocity structure. + */ +public class FloodgateApiHolder { + + private final FloodgateApi floodgateApi; + + public FloodgateApiHolder() { + this.floodgateApi = FloodgateApi.getInstance(); + } + + public boolean isFloodgatePlayer(UUID uuid) { + return this.floodgateApi.isFloodgatePlayer(uuid); + } +} diff --git a/src/main/java/net/elytrium/limboauth/listener/AuthListener.java b/src/main/java/net/elytrium/limboauth/listener/AuthListener.java index 0b0db2c..62d001c 100644 --- a/src/main/java/net/elytrium/limboauth/listener/AuthListener.java +++ b/src/main/java/net/elytrium/limboauth/listener/AuthListener.java @@ -20,10 +20,13 @@ package net.elytrium.limboauth.listener; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.stmt.UpdateBuilder; import com.velocitypowered.api.event.Subscribe; +import com.velocitypowered.api.event.connection.PostLoginEvent; import com.velocitypowered.api.event.connection.PreLoginEvent; import com.velocitypowered.api.util.UuidUtils; import java.sql.SQLException; +import java.util.Map; import java.util.UUID; +import java.util.concurrent.TimeUnit; import net.elytrium.limboapi.api.event.LoginLimboRegisterEvent; import net.elytrium.limboapi.api.event.SafeGameProfileRequestEvent; import net.elytrium.limboauth.LimboAuth; @@ -34,16 +37,18 @@ import net.elytrium.limboauth.model.RegisteredPlayer; // TODO: Customizable events priority public class AuthListener { + private final LimboAuth plugin; private final Dao playerDao; - public AuthListener(Dao playerDao) { + public AuthListener(LimboAuth plugin, Dao playerDao) { + this.plugin = plugin; this.playerDao = playerDao; } @Subscribe - public void onProxyConnect(PreLoginEvent event) { + public void onPreLoginEvent(PreLoginEvent event) { if (!event.getResult().isForceOfflineMode()) { - if (!LimboAuth.getInstance().isPremium(event.getUsername())) { + if (!this.plugin.isPremium(event.getUsername())) { event.setResult(PreLoginEvent.PreLoginComponentResult.forceOfflineMode()); } else { event.setResult(PreLoginEvent.PreLoginComponentResult.forceOnlineMode()); @@ -52,14 +57,26 @@ public class AuthListener { } @Subscribe - public void onLogin(LoginLimboRegisterEvent event) { - if (LimboAuth.getInstance().needAuth(event.getPlayer())) { - event.addCallback(() -> LimboAuth.getInstance().authPlayer(event.getPlayer())); + public void onPostLogin(PostLoginEvent event) { + Map postLoginTasks = this.plugin.getPostLoginTasks(); + UUID uuid = event.getPlayer().getUniqueId(); + if (postLoginTasks.containsKey(uuid)) { + // We need to delay for player's client to finish switching the server, it takes a little time. + this.plugin.getServer().getScheduler().buildTask( + this.plugin, () -> postLoginTasks.get(uuid).run() + ).delay(Settings.IMP.MAIN.PREMIUM_AND_FLOODGATE_MESSAGES_DELAY, TimeUnit.MILLISECONDS).schedule(); } } @Subscribe - public void onProfile(SafeGameProfileRequestEvent event) { + public void onLoginLimboRegister(LoginLimboRegisterEvent event) { + if (this.plugin.needAuth(event.getPlayer())) { + event.addCallback(() -> this.plugin.authPlayer(event.getPlayer())); + } + } + + @Subscribe + public void onGameProfileRequest(SafeGameProfileRequestEvent event) { if (Settings.IMP.MAIN.SAVE_UUID) { RegisteredPlayer registeredPlayer = AuthSessionHandler.fetchInfo(this.playerDao, event.getOriginalProfile().getId()); @@ -67,15 +84,12 @@ public class AuthListener { event.setGameProfile(event.getOriginalProfile().withId(UUID.fromString(registeredPlayer.getUuid()))); return; } - registeredPlayer = AuthSessionHandler.fetchInfo(this.playerDao, event.getUsername()); if (registeredPlayer != null) { String currentUuid = registeredPlayer.getUuid(); - if (event.isOnlineMode() - && registeredPlayer.getHash().isEmpty() - && registeredPlayer.getPremiumUuid().isEmpty()) { + if (event.isOnlineMode() && registeredPlayer.getHash().isEmpty() && registeredPlayer.getPremiumUuid().isEmpty()) { try { registeredPlayer.setPremiumUuid(event.getOriginalProfile().getId().toString()); this.playerDao.update(registeredPlayer); diff --git a/src/main/java/net/elytrium/limboauth/utils/UpdatesChecker.java b/src/main/java/net/elytrium/limboauth/utils/UpdatesChecker.java index 71af1bb..79a2998 100644 --- a/src/main/java/net/elytrium/limboauth/utils/UpdatesChecker.java +++ b/src/main/java/net/elytrium/limboauth/utils/UpdatesChecker.java @@ -67,7 +67,7 @@ public class UpdatesChecker { private static String getCleanVersion(String version) { int indexOf = version.indexOf("-"); if (indexOf > 0) { - return version.substring(0, indexOf) + "$"; // "$" - Indicates that the version is snapshot + return version.substring(0, indexOf) + "$"; // "$" - Indicates that the version is not release. } else { return version; } -- cgit