Fixed the first Duplication Glitch with this Plugin and released 1.1.

This commit is contained in:
2025-12-04 17:23:55 +01:00
parent 355b3cdc8f
commit 6b0c22b71f
4 changed files with 72 additions and 9 deletions

View File

@@ -6,7 +6,7 @@
<groupId>com.user404_</groupId>
<artifactId>BalSync</artifactId>
<version>1.0</version>
<version>1.1</version>
<packaging>jar</packaging>
<name>BalSync</name>

View File

@@ -21,6 +21,7 @@ public class BalanceManager {
private BukkitTask dbPollingTask;
private final Map<UUID, Double> lastKnownBalances = new HashMap<>();
private final Map<UUID, Double> lastKnownDbBalances = new HashMap<>();
public void saveAllBalances() {
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.");
});
}
public BalanceManager(BalSyncPlugin plugin, Economy economy, DatabaseManager databaseManager) {
this.plugin = plugin;
this.economy = economy;
@@ -227,18 +229,32 @@ public class BalanceManager {
Double lastBalance = lastKnownBalances.get(uuid);
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 {
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);
lastKnownDbBalances.put(uuid, newDbBalance);
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) {
plugin.getLogger().log(Level.WARNING,
plugin.getPluginLogger().log(Level.WARNING,
"Failed to save offline change for " + offlinePlayer.getName(), e);
}
} 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);
}
}
@@ -264,6 +280,23 @@ public class BalanceManager {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
try {
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);
lastKnownBalances.put(player.getUniqueId(), balance);
lastKnownDbBalances.put(player.getUniqueId(), balance);

View File

@@ -64,7 +64,7 @@ public class DatabaseManager {
"`id` INT AUTO_INCREMENT PRIMARY KEY, " +
"`player_uuid` CHAR(36) UNIQUE NOT NULL, " +
"`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, " +
"INDEX `idx_uuid` (`player_uuid`)" +
") CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE=InnoDB",
@@ -111,7 +111,7 @@ public class DatabaseManager {
"`id` INT AUTO_INCREMENT PRIMARY KEY, " +
"`player_uuid` CHAR(36) UNIQUE NOT NULL, " +
"`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, " +
"INDEX `idx_uuid` (`player_uuid`)" +
") 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 {
return dataSource.getConnection();
}

View File

@@ -1,5 +1,5 @@
name: BalSync
version: 1.0
version: 1.1
main: com.user404_.balsync.BalSyncPlugin
api-version: '1.20'
description: Synchronizes player balances with MySQL database