Fixed the first Duplication Glitch with this Plugin and released 1.1.
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
<groupId>com.user404_</groupId>
|
<groupId>com.user404_</groupId>
|
||||||
<artifactId>BalSync</artifactId>
|
<artifactId>BalSync</artifactId>
|
||||||
<version>1.0</version>
|
<version>1.1</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>BalSync</name>
|
<name>BalSync</name>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public class BalanceManager {
|
|||||||
private BukkitTask dbPollingTask;
|
private BukkitTask dbPollingTask;
|
||||||
private final Map<UUID, Double> lastKnownBalances = new HashMap<>();
|
private final Map<UUID, Double> lastKnownBalances = new HashMap<>();
|
||||||
private final Map<UUID, Double> lastKnownDbBalances = new HashMap<>();
|
private final Map<UUID, Double> lastKnownDbBalances = new HashMap<>();
|
||||||
|
|
||||||
public void saveAllBalances() {
|
public void saveAllBalances() {
|
||||||
plugin.getPluginLogger().info("Saving all player balances to database...");
|
plugin.getPluginLogger().info("Saving all player balances to database...");
|
||||||
|
|
||||||
@@ -43,6 +44,7 @@ public class BalanceManager {
|
|||||||
plugin.getPluginLogger().info("Saved " + saved + " player balances to database.");
|
plugin.getPluginLogger().info("Saved " + saved + " player balances to database.");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public BalanceManager(BalSyncPlugin plugin, Economy economy, DatabaseManager databaseManager) {
|
public BalanceManager(BalSyncPlugin plugin, Economy economy, DatabaseManager databaseManager) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
this.economy = economy;
|
this.economy = economy;
|
||||||
@@ -227,18 +229,32 @@ public class BalanceManager {
|
|||||||
|
|
||||||
Double lastBalance = lastKnownBalances.get(uuid);
|
Double lastBalance = lastKnownBalances.get(uuid);
|
||||||
if (lastBalance != null && Math.abs(currentBalance - lastBalance) > 0.001) {
|
if (lastBalance != null && Math.abs(currentBalance - lastBalance) > 0.001) {
|
||||||
// Balance has changed - save to database
|
// Balance has changed on this server. Instead of overwriting the DB with
|
||||||
|
// a stale server value, compute the delta and apply that to the DB.
|
||||||
|
double delta = currentBalance - lastBalance;
|
||||||
try {
|
try {
|
||||||
databaseManager.saveBalance(uuid, offlinePlayer.getName(), currentBalance);
|
databaseManager.addBalanceDelta(uuid, offlinePlayer.getName(), delta);
|
||||||
|
|
||||||
|
// Refresh DB snapshot for tracking
|
||||||
|
double newDbBalance = databaseManager.getBalance(uuid);
|
||||||
|
|
||||||
lastKnownBalances.put(uuid, currentBalance);
|
lastKnownBalances.put(uuid, currentBalance);
|
||||||
|
lastKnownDbBalances.put(uuid, newDbBalance);
|
||||||
|
|
||||||
plugin.getLogger().info("Detected offline change for " +
|
plugin.getLogger().info("Detected offline change for " +
|
||||||
offlinePlayer.getName() + ": " + currentBalance);
|
offlinePlayer.getName() + ": serverDelta=" + delta + ", newDB=" + newDbBalance);
|
||||||
|
|
||||||
|
// Optional: send configured offline-change message to console/log
|
||||||
|
String msg = plugin.getTranslationManager().getMessage("offline-change-detected");
|
||||||
|
if (msg != null && !msg.isEmpty()) {
|
||||||
|
plugin.getLogger().info(plugin.getTranslationManager().formatMessage("prefix") + msg);
|
||||||
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
plugin.getLogger().log(Level.WARNING,
|
plugin.getPluginLogger().log(Level.WARNING,
|
||||||
"Failed to save offline change for " + offlinePlayer.getName(), e);
|
"Failed to save offline change for " + offlinePlayer.getName(), e);
|
||||||
}
|
}
|
||||||
} else if (lastBalance == null) {
|
} else if (lastBalance == null) {
|
||||||
// First time seeing this player, store initial balance
|
// First time seeing this player on this server, store initial balance
|
||||||
lastKnownBalances.put(uuid, currentBalance);
|
lastKnownBalances.put(uuid, currentBalance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -264,6 +280,23 @@ public class BalanceManager {
|
|||||||
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
|
||||||
try {
|
try {
|
||||||
double balance = economy.getBalance(player);
|
double balance = economy.getBalance(player);
|
||||||
|
UUID uuid = player.getUniqueId();
|
||||||
|
|
||||||
|
Double lastBalance = lastKnownBalances.get(uuid);
|
||||||
|
if (lastBalance != null) {
|
||||||
|
// There is a last-known server-side snapshot => compute delta and apply it
|
||||||
|
double delta = balance - lastBalance;
|
||||||
|
if (Math.abs(delta) > 0.001) {
|
||||||
|
databaseManager.addBalanceDelta(uuid, player.getName(), delta);
|
||||||
|
|
||||||
|
double newDb = databaseManager.getBalance(uuid);
|
||||||
|
lastKnownBalances.put(uuid, balance);
|
||||||
|
lastKnownDbBalances.put(uuid, newDb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: overwrite DB with current balance
|
||||||
databaseManager.saveBalance(player.getUniqueId(), player.getName(), balance);
|
databaseManager.saveBalance(player.getUniqueId(), player.getName(), balance);
|
||||||
lastKnownBalances.put(player.getUniqueId(), balance);
|
lastKnownBalances.put(player.getUniqueId(), balance);
|
||||||
lastKnownDbBalances.put(player.getUniqueId(), balance);
|
lastKnownDbBalances.put(player.getUniqueId(), balance);
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ public class DatabaseManager {
|
|||||||
"`id` INT AUTO_INCREMENT PRIMARY KEY, " +
|
"`id` INT AUTO_INCREMENT PRIMARY KEY, " +
|
||||||
"`player_uuid` CHAR(36) UNIQUE NOT NULL, " +
|
"`player_uuid` CHAR(36) UNIQUE NOT NULL, " +
|
||||||
"`player_name` VARCHAR(16), " +
|
"`player_name` VARCHAR(16), " +
|
||||||
"`balance` DECIMAL(15, 2) NOT NULL DEFAULT %.2f, " + // DECIMAL für bessere Präzision
|
"`balance` DECIMAL(15, 2) NOT NULL DEFAULT %.2f, " +
|
||||||
"`last_updated` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
"`last_updated` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
||||||
"INDEX `idx_uuid` (`player_uuid`)" +
|
"INDEX `idx_uuid` (`player_uuid`)" +
|
||||||
") CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE=InnoDB",
|
") CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE=InnoDB",
|
||||||
@@ -111,7 +111,7 @@ public class DatabaseManager {
|
|||||||
"`id` INT AUTO_INCREMENT PRIMARY KEY, " +
|
"`id` INT AUTO_INCREMENT PRIMARY KEY, " +
|
||||||
"`player_uuid` CHAR(36) UNIQUE NOT NULL, " +
|
"`player_uuid` CHAR(36) UNIQUE NOT NULL, " +
|
||||||
"`player_name` VARCHAR(16), " +
|
"`player_name` VARCHAR(16), " +
|
||||||
"`balance` DECIMAL(15, 2) NOT NULL, " + // Kein DEFAULT hier
|
"`balance` DECIMAL(15, 2) NOT NULL, " +
|
||||||
"`last_updated` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
"`last_updated` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
|
||||||
"INDEX `idx_uuid` (`player_uuid`)" +
|
"INDEX `idx_uuid` (`player_uuid`)" +
|
||||||
") CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE=InnoDB",
|
") CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE=InnoDB",
|
||||||
@@ -158,6 +158,36 @@ public class DatabaseManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Atomically add a delta to the stored balance. This avoids overwriting the DB with stale
|
||||||
|
* values when multiple servers write concurrently. If no row exists, insert one with
|
||||||
|
* (startingBalance + delta).
|
||||||
|
*/
|
||||||
|
public void addBalanceDelta(UUID playerUUID, String playerName, double delta) throws SQLException {
|
||||||
|
String updateSql = String.format("UPDATE %s SET balance = balance + ? WHERE player_uuid = ?", tableName);
|
||||||
|
|
||||||
|
try (Connection conn = dataSource.getConnection()) {
|
||||||
|
// Try atomic update first
|
||||||
|
try (PreparedStatement update = conn.prepareStatement(updateSql)) {
|
||||||
|
update.setDouble(1, delta);
|
||||||
|
update.setString(2, playerUUID.toString());
|
||||||
|
int affected = update.executeUpdate();
|
||||||
|
|
||||||
|
if (affected == 0) {
|
||||||
|
// No row existed — insert with startingBalance + delta
|
||||||
|
double starting = plugin.getConfigManager().getStartingBalance();
|
||||||
|
String insertSql = String.format("INSERT INTO %s (player_uuid, player_name, balance) VALUES (?, ?, ?)", tableName);
|
||||||
|
try (PreparedStatement insert = conn.prepareStatement(insertSql)) {
|
||||||
|
insert.setString(1, playerUUID.toString());
|
||||||
|
insert.setString(2, playerName);
|
||||||
|
insert.setDouble(3, starting + delta);
|
||||||
|
insert.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Connection getConnection() throws SQLException {
|
public Connection getConnection() throws SQLException {
|
||||||
return dataSource.getConnection();
|
return dataSource.getConnection();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: BalSync
|
name: BalSync
|
||||||
version: 1.0
|
version: 1.1
|
||||||
main: com.user404_.balsync.BalSyncPlugin
|
main: com.user404_.balsync.BalSyncPlugin
|
||||||
api-version: '1.20'
|
api-version: '1.20'
|
||||||
description: Synchronizes player balances with MySQL database
|
description: Synchronizes player balances with MySQL database
|
||||||
|
|||||||
Reference in New Issue
Block a user