From 62ca46fe6a3156942df95bc8d8738c6f276399b0 Mon Sep 17 00:00:00 2001 From: Smart123s <28480228+Smart123s@users.noreply.github.com> Date: Mon, 18 Jul 2022 11:56:10 +0200 Subject: [PATCH 1/6] Add checksytle suppression via comments --- checkstyle.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/checkstyle.xml b/checkstyle.xml index 9bae4d4c4..cca3b330f 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -220,6 +220,14 @@ + + + + + + + + From b0b998d1aa191d68146371376ab53c33b459ee3f Mon Sep 17 00:00:00 2001 From: Smart123s <28480228+Smart123s@users.noreply.github.com> Date: Mon, 18 Jul 2022 11:42:17 +0200 Subject: [PATCH 2/6] Use columnName instead of columnIndex It's safer to rely on names instead of indexes. It's also easier to add new columns at the end of the table. --- .../fastlogin/core/storage/SQLStorage.java | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLStorage.java b/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLStorage.java index 178a2fe89..e1891588c 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLStorage.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLStorage.java @@ -50,19 +50,23 @@ public abstract class SQLStorage implements AuthStorage { + "`UUID` CHAR(36), " + "`Name` VARCHAR(16) NOT NULL, " + "`Premium` BOOLEAN NOT NULL, " + + "`Floodgate` BOOLEAN NOT NULL, " + "`LastIp` VARCHAR(255) NOT NULL, " + "`LastLogin` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, " //the premium shouldn't steal the cracked account by changing the name + "UNIQUE (`Name`) " + ')'; - protected static final String LOAD_BY_NAME = "SELECT * FROM `" + PREMIUM_TABLE + "` WHERE `Name`=? LIMIT 1"; - protected static final String LOAD_BY_UUID = "SELECT * FROM `" + PREMIUM_TABLE + "` WHERE `UUID`=? LIMIT 1"; + protected static final String LOAD_BY_NAME = "SELECT * FROM `" + PREMIUM_TABLE + + "` WHERE `Name`=? LIMIT 1"; + protected static final String LOAD_BY_UUID = "SELECT * FROM `" + PREMIUM_TABLE + + "` WHERE `UUID`=? LIMIT 1"; protected static final String INSERT_PROFILE = "INSERT INTO `" + PREMIUM_TABLE - + "` (`UUID`, `Name`, `Premium`, `LastIp`) " + "VALUES (?, ?, ?, ?) "; + + "` (`UUID`, `Name`, `Premium`, `Floodgate`, `LastIp`) " + "VALUES (?, ?, ?, ?, ?) "; // limit not necessary here, because it's unique protected static final String UPDATE_PROFILE = "UPDATE `" + PREMIUM_TABLE - + "` SET `UUID`=?, `Name`=?, `Premium`=?, `LastIp`=?, `LastLogin`=CURRENT_TIMESTAMP WHERE `UserID`=?"; + + "` SET `UUID`=?, `Name`=?, `Premium`=?, `Floodgate`=?, `LastIp`=?, " + + "`LastLogin`=CURRENT_TIMESTAMP WHERE `UserID`=?"; protected final Logger log; protected final HikariDataSource dataSource; @@ -97,7 +101,7 @@ public StoredProfile loadProfile(String name) { loadStmt.setString(1, name); try (ResultSet resultSet = loadStmt.executeQuery()) { - return parseResult(resultSet).orElseGet(() -> new StoredProfile(null, name, false, "")); + return parseResult(resultSet).orElseGet(() -> new StoredProfile(null, name, false, false, "")); } } catch (SQLException sqlEx) { log.error("Failed to query profile: {}", name, sqlEx); @@ -124,14 +128,14 @@ public StoredProfile loadProfile(UUID uuid) { private Optional parseResult(ResultSet resultSet) throws SQLException { if (resultSet.next()) { - long userId = resultSet.getInt(1); + long userId = resultSet.getInt("UserID"); - UUID uuid = Optional.ofNullable(resultSet.getString(2)).map(UUIDAdapter::parseId).orElse(null); + UUID uuid = Optional.ofNullable(resultSet.getString("UUID")).map(UUIDAdapter::parseId).orElse(null); - String name = resultSet.getString(3); - boolean premium = resultSet.getBoolean(4); - String lastIp = resultSet.getString(5); - Instant lastLogin = resultSet.getTimestamp(6).toInstant(); + String name = resultSet.getString("Name"); + boolean premium = resultSet.getBoolean("Premium"); + String lastIp = resultSet.getString("LastIp"); + Instant lastLogin = resultSet.getTimestamp("LastLogin").toInstant(); return Optional.of(new StoredProfile(userId, uuid, name, premium, lastIp, lastLogin)); } From db5b818a80e5b7095ffbc68da5be1e491e352d2f Mon Sep 17 00:00:00 2001 From: Smart123s <28480228+Smart123s@users.noreply.github.com> Date: Sat, 22 Jan 2022 19:20:36 +0100 Subject: [PATCH 3/6] Add `Floodgate` variable to StoredProfile/Database --- .../fastlogin/core/shared/FloodgateState.java | 70 +++++++++++++++++++ .../fastlogin/core/storage/SQLStorage.java | 57 ++++++++++++--- .../fastlogin/core/storage/SQLiteStorage.java | 23 +++--- .../fastlogin/core/storage/StoredProfile.java | 28 +++++++- 4 files changed, 157 insertions(+), 21 deletions(-) create mode 100644 core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateState.java diff --git a/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateState.java b/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateState.java new file mode 100644 index 000000000..874deb9ba --- /dev/null +++ b/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateState.java @@ -0,0 +1,70 @@ +/* + * SPDX-License-Identifier: MIT + * + * The MIT License (MIT) + * + * Copyright (c) 2015-2022 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.core.shared; + +public enum FloodgateState { + FALSE(0), + TRUE(1), + LINKED(2), + NOT_MIGRATED(3); + + private int value; + + FloodgateState(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + /** + * Convert a number to FloodgateState + *
    + *
  1. False
  2. + *
  3. True
  4. + *
  5. Linked
  6. + *
  7. Not Migrated
  8. + *
+ * @param num the number, most likely loaded from the database + * @return FloodgateStatus on success, null otherwise + */ + public static FloodgateState fromInt(int num) { + // using Enum.values()[i] is expensive as per https://stackoverflow.com/a/8762387/9767089 + switch (num) { + case 0: + return FloodgateState.FALSE; + case 1: + return FloodgateState.TRUE; + case 2: + return FloodgateState.LINKED; + case 3: + return FloodgateState.NOT_MIGRATED; + default: + return null; + } + } +} diff --git a/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLStorage.java b/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLStorage.java index e1891588c..f10a07963 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLStorage.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLStorage.java @@ -26,11 +26,14 @@ package com.github.games647.fastlogin.core.storage; import com.github.games647.craftapi.UUIDAdapter; +import com.github.games647.fastlogin.core.StoredProfile; +import com.github.games647.fastlogin.core.shared.FloodgateState; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; import org.slf4j.Logger; import java.sql.Connection; +import java.sql.DatabaseMetaData; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -50,13 +53,15 @@ public abstract class SQLStorage implements AuthStorage { + "`UUID` CHAR(36), " + "`Name` VARCHAR(16) NOT NULL, " + "`Premium` BOOLEAN NOT NULL, " - + "`Floodgate` BOOLEAN NOT NULL, " + "`LastIp` VARCHAR(255) NOT NULL, " + "`LastLogin` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, " //the premium shouldn't steal the cracked account by changing the name + "UNIQUE (`Name`) " + ')'; + protected static final String ADD_FLOODGATE_COLUMN_STMT = "ALTER TABLE `" + PREMIUM_TABLE + + "` ADD COLUMN `Floodgate` INTEGER(3)"; + protected static final String LOAD_BY_NAME = "SELECT * FROM `" + PREMIUM_TABLE + "` WHERE `Name`=? LIMIT 1"; protected static final String LOAD_BY_UUID = "SELECT * FROM `" + PREMIUM_TABLE @@ -85,11 +90,23 @@ public void createTables() throws SQLException { // choose surrogate PK(ID), because UUID can be null for offline players // if UUID is always Premium UUID we would have to update offline player entries on insert // name cannot be PK, because it can be changed for premium players - //todo: add unique uuid index usage try (Connection con = dataSource.getConnection(); - Statement createStmt = con.createStatement()) { - createStmt.executeUpdate(CREATE_TABLE_STMT); + Statement stmt = con.createStatement()) { + stmt.executeUpdate(getCreateTableStmt()); + + // add Floodgate column + DatabaseMetaData md = con.getMetaData(); + if (isColumnMissing(md, "Floodgate")) { + stmt.executeUpdate(ADD_FLOODGATE_COLUMN_STMT); + } + + } + } + + private boolean isColumnMissing(DatabaseMetaData metaData, String columnName) throws SQLException { + try (ResultSet rs = metaData.getColumns(null, null, PREMIUM_TABLE, columnName)) { + return !rs.next(); } } @@ -101,7 +118,8 @@ public StoredProfile loadProfile(String name) { loadStmt.setString(1, name); try (ResultSet resultSet = loadStmt.executeQuery()) { - return parseResult(resultSet).orElseGet(() -> new StoredProfile(null, name, false, false, "")); + return parseResult(resultSet).orElseGet(() -> new StoredProfile(null, name, false, + FloodgateState.FALSE, "")); } } catch (SQLException sqlEx) { log.error("Failed to query profile: {}", name, sqlEx); @@ -134,9 +152,19 @@ private Optional parseResult(ResultSet resultSet) throws SQLExcep String name = resultSet.getString("Name"); boolean premium = resultSet.getBoolean("Premium"); + int floodgateNum = resultSet.getInt("Floodgate"); + FloodgateState floodgate; + + // if the player wasn't migrated to the new database format + if (resultSet.wasNull()) { + floodgate = FloodgateState.NOT_MIGRATED; + } else { + floodgate = FloodgateState.fromInt(floodgateNum); + } + String lastIp = resultSet.getString("LastIp"); Instant lastLogin = resultSet.getTimestamp("LastLogin").toInstant(); - return Optional.of(new StoredProfile(userId, uuid, name, premium, lastIp, lastLogin)); + return Optional.of(new StoredProfile(userId, uuid, name, premium, floodgate, lastIp, lastLogin)); } return Optional.empty(); @@ -154,9 +182,10 @@ public void save(StoredProfile playerProfile) { saveStmt.setString(1, uuid); saveStmt.setString(2, playerProfile.getName()); saveStmt.setBoolean(3, playerProfile.isPremium()); - saveStmt.setString(4, playerProfile.getLastIp()); + saveStmt.setInt(4, playerProfile.getFloodgate().getValue()); + saveStmt.setString(5, playerProfile.getLastIp()); - saveStmt.setLong(5, playerProfile.getRowId()); + saveStmt.setLong(6, playerProfile.getRowId()); saveStmt.execute(); } } else { @@ -165,7 +194,9 @@ public void save(StoredProfile playerProfile) { saveStmt.setString(2, playerProfile.getName()); saveStmt.setBoolean(3, playerProfile.isPremium()); - saveStmt.setString(4, playerProfile.getLastIp()); + saveStmt.setBoolean(3, playerProfile.isPremium()); + saveStmt.setInt(4, playerProfile.getFloodgate().getValue()); + saveStmt.setString(5, playerProfile.getLastIp()); saveStmt.execute(); try (ResultSet generatedKeys = saveStmt.getGeneratedKeys()) { @@ -183,6 +214,14 @@ public void save(StoredProfile playerProfile) { } } + /** + * SQLite has a slightly different syntax, so this will be overridden by SQLiteStorage + * @return An SQL Statement to create the `premium` table + */ + protected String getCreateTableStmt() { + return CREATE_TABLE_STMT; + } + @Override public void close() { dataSource.close(); diff --git a/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLiteStorage.java b/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLiteStorage.java index b428cbc1e..195cf2bb7 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLiteStorage.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLiteStorage.java @@ -31,15 +31,23 @@ import org.sqlite.SQLiteConfig; import java.nio.file.Path; -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; import java.util.UUID; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class SQLiteStorage extends SQLStorage { + protected static final String CREATE_TABLE_STMT = "CREATE TABLE IF NOT EXISTS `" + PREMIUM_TABLE + "` (" + + "`UserID` INTEGER PRIMARY KEY AUTO_INCREMENT, " + + "`UUID` CHAR(36), " + + "`Name` VARCHAR(16) NOT NULL, " + + "`Premium` BOOLEAN NOT NULL, " + + "`LastIp` VARCHAR(255) NOT NULL, " + + "`LastLogin` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, " + //the premium shouldn't steal the cracked account by changing the name + + "UNIQUE (`Name`) " + + ')'; + private static final String SQLITE_DRIVER = "org.sqlite.SQLiteDataSource"; private final Lock lock = new ReentrantLock(); @@ -103,12 +111,9 @@ public void save(StoredProfile playerProfile) { } @Override - public void createTables() throws SQLException { - try (Connection con = dataSource.getConnection(); - Statement createStmt = con.createStatement()) { - // SQLite has a different syntax for auto increment - createStmt.executeUpdate(CREATE_TABLE_STMT.replace("AUTO_INCREMENT", "AUTOINCREMENT")); - } + protected String getCreateTableStmt() { + // SQLite has a different syntax for auto increment + return CREATE_TABLE_STMT.replace("AUTO_INCREMENT", "AUTOINCREMENT"); } private static String replacePathVariables(Path dataFolder, String input) { diff --git a/core/src/main/java/com/github/games647/fastlogin/core/storage/StoredProfile.java b/core/src/main/java/com/github/games647/fastlogin/core/storage/StoredProfile.java index 0da7775cb..625d383f7 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/storage/StoredProfile.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/storage/StoredProfile.java @@ -26,6 +26,7 @@ package com.github.games647.fastlogin.core.storage; import com.github.games647.craftapi.model.Profile; +import com.github.games647.fastlogin.core.shared.FloodgateState; import java.time.Instant; import java.util.Objects; @@ -39,20 +40,28 @@ public class StoredProfile extends Profile { private final ReentrantLock saveLock = new ReentrantLock(); private boolean premium; + private FloodgateState floodgate; private String lastIp; private Instant lastLogin; - public StoredProfile(long rowId, UUID uuid, String playerName, boolean premium, String lastIp, Instant lastLogin) { + public StoredProfile(long rowId, UUID uuid, String playerName, boolean premium, FloodgateState floodgate, + String lastIp, Instant lastLogin) { super(uuid, playerName); this.rowId = rowId; this.premium = premium; + this.floodgate = floodgate; this.lastIp = lastIp; this.lastLogin = lastLogin; } + public StoredProfile(UUID uuid, String playerName, boolean premium, FloodgateState isFloodgate, String lastIp) { + this(-1, uuid, playerName, premium, isFloodgate, lastIp, Instant.now()); + } + + @Deprecated public StoredProfile(UUID uuid, String playerName, boolean premium, String lastIp) { - this(-1, uuid, playerName, premium, lastIp, Instant.now()); + this(-1, uuid, playerName, premium, FloodgateState.FALSE, lastIp, Instant.now()); } public ReentrantLock getSaveLock() { @@ -96,6 +105,18 @@ public synchronized void setPremium(boolean premium) { this.premium = premium; } + public synchronized FloodgateState getFloodgate() { + return floodgate; + } + + public synchronized boolean isFloodgateMigrated() { + return floodgate != FloodgateState.NOT_MIGRATED; + } + + public synchronized void setFloodgate(FloodgateState floodgate) { + this.floodgate = floodgate; + } + public synchronized String getLastIp() { return lastIp; } @@ -128,7 +149,7 @@ public synchronized boolean equals(Object o) { } return rowId == that.rowId && premium == that.premium - && Objects.equals(lastIp, that.lastIp) && lastLogin.equals(that.lastLogin); + && Objects.equals(lastIp, that.lastIp) && lastLogin.equals(that.lastLogin); } @Override @@ -141,6 +162,7 @@ public synchronized String toString() { return this.getClass().getSimpleName() + '{' + "rowId=" + rowId + ", premium=" + premium + + ", floodgate=" + floodgate + ", lastIp='" + lastIp + '\'' + ", lastLogin=" + lastLogin + "} " + super.toString(); From e566740ddea1b4a67372c576ee12dbad6aa65a44 Mon Sep 17 00:00:00 2001 From: Smart123s <28480228+Smart123s@users.noreply.github.com> Date: Tue, 16 May 2023 14:24:29 +0200 Subject: [PATCH 4/6] Differentiate Floodgate players during login --- .../core/shared/FloodgateManagement.java | 42 +++++++++++++++++-- .../fastlogin/core/shared/FloodgateState.java | 2 +- .../fastlogin/core/shared/JoinManagement.java | 30 ++++++++++--- .../fastlogin/core/storage/SQLStorage.java | 1 - 4 files changed, 65 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateManagement.java b/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateManagement.java index f0c276514..4ca3b6941 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateManagement.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateManagement.java @@ -80,6 +80,38 @@ public void run() { } profile = core.getStorage().loadProfile(username); + + if (profile.isSaved()) { + if (!profile.isFloodgateMigrated()) { + if (isLinked) { + profile.setFloodgate(FloodgateState.LINKED); + core.getPlugin().getLog().info( + "Player {} will be migrated to the v2 database schema as a linked Floodgate user", + username); + } else { + profile.setFloodgate(FloodgateState.TRUE); + core.getPlugin().getLog().info( + "Player {} will be migrated to the v2 database schema as a Floodgate user", username); + } + } else if (profile.getFloodgate() == FloodgateState.TRUE && isLinked) { + core.getPlugin().getLog() + .info("Player {} is already stored by FastLogin as a non-linked Bedrock Edition player", + username); + return; + } else if (profile.getFloodgate() == FloodgateState.FALSE && isLinked) { + profile.setFloodgate(FloodgateState.LINKED); + core.getPlugin().getLog().info( + "Player {} will be changed from a Java player to a linked Floodgate player", + username); + } + } else { + if (isLinked) { + profile.setFloodgate(FloodgateState.LINKED); + } else { + profile.setFloodgate(FloodgateState.TRUE); + } + } + AuthPlugin

authPlugin = core.getAuthPluginHook(); try { @@ -119,13 +151,17 @@ public void run() { } } + // defer auto registration, if it's not enabled in the config if (!isRegistered && !isAutoAuthAllowed(autoRegisterFloodgate)) { return; } - //logging in from bedrock for a second time threw an error with UUID - if (profile == null) { - profile = new StoredProfile(getUUID(player), username, true, getAddress(player).toString()); + // stop the auto login procedure, if the current connection's parameters don't match the one stored in our + // database + // ex. we stored a LINKED account, but the current connection is not linked + if ((profile.getFloodgate() == FloodgateState.LINKED && !isLinked) + || (profile.getFloodgate() == FloodgateState.TRUE && isLinked)) { + return; } //start Bukkit/Bungee specific tasks diff --git a/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateState.java b/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateState.java index 874deb9ba..caa867faf 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateState.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateState.java @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2015-2022 games647 and contributors + * 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 diff --git a/core/src/main/java/com/github/games647/fastlogin/core/shared/JoinManagement.java b/core/src/main/java/com/github/games647/fastlogin/core/shared/JoinManagement.java index 75b9f500b..013dd3ca3 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/shared/JoinManagement.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/shared/JoinManagement.java @@ -49,19 +49,33 @@ public JoinManagement(FastLoginCore core, AuthPlugin

authHook, Bedro public void onLogin(String username, S source) { core.getPlugin().getLog().info("Handling player {}", username); - StoredProfile profile = core.getStorage().loadProfile(username); - if (profile == null) { - return; - } //check if the player is connecting through Bedrock Edition if (bedrockService != null && bedrockService.isBedrockConnection(username)) { - //perform Bedrock specific checks and skip Java checks, if they are not needed + //perform Bedrock specific checks if (bedrockService.performChecks(username, source)) { + //skip Java checks, since they are not needed return; } } + StoredProfile profile = core.getStorage().loadProfile(username); + + //can't be a premium Java player, if it's not saved in the database + if (profile == null) { + return; + } + + if (!profile.isFloodgateMigrated()) { + profile.setFloodgate(FloodgateState.FALSE); + core.getPlugin().getLog().info( + "Player {} will be migrated to the v2 database schema as a JAVA user", username); + } else if (profile.getFloodgate() == FloodgateState.TRUE) { + core.getPlugin().getLog().info("Player {} is already stored by FastLogin as a Bedrock Edition player", + username); + return; + } + callFastLoginPreLoginEvent(username, source, profile); Configuration config = core.getConfig(); @@ -139,6 +153,12 @@ private boolean checkNameChange(S source, String username, Profile profile) { if (core.getConfig().get("nameChangeCheck", false)) { StoredProfile storedProfile = core.getStorage().loadProfile(profile.getId()); if (storedProfile != null) { + if (storedProfile.getFloodgate() == FloodgateState.TRUE) { + core.getPlugin().getLog() + .info("Player {} is already stored by FastLogin as a Bedrock Edition player.", username); + return false; + } + //uuid exists in the database core.getPlugin().getLog().info("GameProfile {} changed it's username", profile); diff --git a/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLStorage.java b/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLStorage.java index f10a07963..ade10a409 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLStorage.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/storage/SQLStorage.java @@ -26,7 +26,6 @@ package com.github.games647.fastlogin.core.storage; import com.github.games647.craftapi.UUIDAdapter; -import com.github.games647.fastlogin.core.StoredProfile; import com.github.games647.fastlogin.core.shared.FloodgateState; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; From 485af5e044cac3ad99a51529376934dec7bddb1f Mon Sep 17 00:00:00 2001 From: games647 Date: Mon, 11 Dec 2023 15:04:03 +0100 Subject: [PATCH 5/6] Document states --- .../fastlogin/core/shared/FloodgateState.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateState.java b/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateState.java index caa867faf..9e5df985a 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateState.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateState.java @@ -26,9 +26,25 @@ package com.github.games647.fastlogin.core.shared; public enum FloodgateState { + + /** + * Purely Java profile + */ FALSE(0), + + /** + * Purely Bedrock profile + */ TRUE(1), + + /** + * Bedrock profile is bidirectional associated with the Java Mojang profile. + */ LINKED(2), + + /** + * Data before floodgate database migration. Floodgate state is unknown. + */ NOT_MIGRATED(3); private int value; From 434a276d30e05e458b4a7873464e9564df37110c Mon Sep 17 00:00:00 2001 From: games647 Date: Mon, 11 Dec 2023 15:05:50 +0100 Subject: [PATCH 6/6] Invert if and document migration flow for better readability --- .../core/shared/FloodgateManagement.java | 24 ++++++++++--------- .../fastlogin/core/shared/JoinManagement.java | 15 ++++++------ 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateManagement.java b/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateManagement.java index 4ca3b6941..9a59f550b 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateManagement.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/shared/FloodgateManagement.java @@ -82,7 +82,19 @@ public void run() { profile = core.getStorage().loadProfile(username); if (profile.isSaved()) { - if (!profile.isFloodgateMigrated()) { + if (profile.isFloodgateMigrated()) { + if (profile.getFloodgate() == FloodgateState.TRUE && isLinked) { + core.getPlugin().getLog() + .info("Player {} is already stored by FastLogin as a non-linked Bedrock Edition player", + username); + return; + } else if (profile.getFloodgate() == FloodgateState.FALSE && isLinked) { + profile.setFloodgate(FloodgateState.LINKED); + core.getPlugin().getLog().info( + "Player {} will be changed from a Java player to a linked Floodgate player", + username); + } + } else { if (isLinked) { profile.setFloodgate(FloodgateState.LINKED); core.getPlugin().getLog().info( @@ -93,16 +105,6 @@ public void run() { core.getPlugin().getLog().info( "Player {} will be migrated to the v2 database schema as a Floodgate user", username); } - } else if (profile.getFloodgate() == FloodgateState.TRUE && isLinked) { - core.getPlugin().getLog() - .info("Player {} is already stored by FastLogin as a non-linked Bedrock Edition player", - username); - return; - } else if (profile.getFloodgate() == FloodgateState.FALSE && isLinked) { - profile.setFloodgate(FloodgateState.LINKED); - core.getPlugin().getLog().info( - "Player {} will be changed from a Java player to a linked Floodgate player", - username); } } else { if (isLinked) { diff --git a/core/src/main/java/com/github/games647/fastlogin/core/shared/JoinManagement.java b/core/src/main/java/com/github/games647/fastlogin/core/shared/JoinManagement.java index 013dd3ca3..c5c41aac7 100644 --- a/core/src/main/java/com/github/games647/fastlogin/core/shared/JoinManagement.java +++ b/core/src/main/java/com/github/games647/fastlogin/core/shared/JoinManagement.java @@ -52,9 +52,8 @@ public void onLogin(String username, S source) { //check if the player is connecting through Bedrock Edition if (bedrockService != null && bedrockService.isBedrockConnection(username)) { - //perform Bedrock specific checks + //perform Bedrock specific checks and skip Java checks if no longer needed if (bedrockService.performChecks(username, source)) { - //skip Java checks, since they are not needed return; } } @@ -66,14 +65,16 @@ public void onLogin(String username, S source) { return; } - if (!profile.isFloodgateMigrated()) { + if (profile.isFloodgateMigrated()) { + if (profile.getFloodgate() == FloodgateState.TRUE) { + // migrated and enabled floodgate player, however the above bedrocks fails, so the current connection + // isn't premium + return; + } + } else { profile.setFloodgate(FloodgateState.FALSE); core.getPlugin().getLog().info( "Player {} will be migrated to the v2 database schema as a JAVA user", username); - } else if (profile.getFloodgate() == FloodgateState.TRUE) { - core.getPlugin().getLog().info("Player {} is already stored by FastLogin as a Bedrock Edition player", - username); - return; } callFastLoginPreLoginEvent(username, source, profile);