From 6365f72133a2b0935ce741fe21906b534ddf2350 Mon Sep 17 00:00:00 2001 From: jascotty2 Date: Wed, 25 Sep 2019 07:08:46 -0500 Subject: [PATCH] fix location data duplication bug --- .../songoda/ultimatekits/UltimateKits.java | 1 + .../command/commands/CommandSet.java | 10 +- .../ultimatekits/database/DataManager.java | 11 ++- .../database/DataMigrationManager.java | 10 +- .../migrations/_1_InitialMigration.java | 14 ++- .../migrations/_2_DuplicateMigration.java | 99 +++++++++++++++++++ .../ultimatekits/kit/KitBlockData.java | 2 - .../songoda/ultimatekits/kit/KitManager.java | 14 +-- 8 files changed, 132 insertions(+), 29 deletions(-) create mode 100644 src/main/java/com/songoda/ultimatekits/database/migrations/_2_DuplicateMigration.java diff --git a/src/main/java/com/songoda/ultimatekits/UltimateKits.java b/src/main/java/com/songoda/ultimatekits/UltimateKits.java index 05eadf9..ceddeb7 100644 --- a/src/main/java/com/songoda/ultimatekits/UltimateKits.java +++ b/src/main/java/com/songoda/ultimatekits/UltimateKits.java @@ -186,6 +186,7 @@ public class UltimateKits extends JavaPlugin { /* * On plugin disable. */ + @Override public void onDisable() { saveToFile(); dataFile.saveConfig(); diff --git a/src/main/java/com/songoda/ultimatekits/command/commands/CommandSet.java b/src/main/java/com/songoda/ultimatekits/command/commands/CommandSet.java index eba55d4..32f9adf 100644 --- a/src/main/java/com/songoda/ultimatekits/command/commands/CommandSet.java +++ b/src/main/java/com/songoda/ultimatekits/command/commands/CommandSet.java @@ -3,6 +3,7 @@ package com.songoda.ultimatekits.command.commands; import com.songoda.ultimatekits.UltimateKits; import com.songoda.ultimatekits.command.AbstractCommand; import com.songoda.ultimatekits.kit.Kit; +import com.songoda.ultimatekits.kit.KitBlockData; import com.songoda.ultimatekits.utils.Methods; import org.bukkit.block.Block; import org.bukkit.command.CommandSender; @@ -24,14 +25,15 @@ public class CommandSet extends AbstractCommand { return ReturnType.FAILURE; } Player player = (Player) sender; - String kit = args[1].toLowerCase(); - if (instance.getKitManager().getKit(kit) == null) { + Kit kit = instance.getKitManager().getKit(args[1].toLowerCase()); + if (kit == null) { instance.getLocale().getMessage("command.kit.kitdoesntexist").sendPrefixedMessage(sender); return ReturnType.FAILURE; } Block b = player.getTargetBlock(null, 200); - instance.getKitManager().addKitToLocation(instance.getKitManager().getKit(kit), b.getLocation()); - instance.getLocale().newMessage("&8Kit &a" + kit + " &8set to: &a" + b.getType().toString() + "&8.") + KitBlockData data = instance.getKitManager().addKitToLocation(kit, b.getLocation()); + UltimateKits.getInstance().getDataManager().createBlockData(data); + instance.getLocale().newMessage("&8Kit &a" + kit.getName() + " &8set to: &a" + b.getType().toString() + "&8.") .sendPrefixedMessage(sender); return ReturnType.SUCCESS; } diff --git a/src/main/java/com/songoda/ultimatekits/database/DataManager.java b/src/main/java/com/songoda/ultimatekits/database/DataManager.java index e2fe0de..dd9b8af 100644 --- a/src/main/java/com/songoda/ultimatekits/database/DataManager.java +++ b/src/main/java/com/songoda/ultimatekits/database/DataManager.java @@ -38,9 +38,8 @@ public class DataManager { "displayItems = ?, particles = ?, itemOverride = ? " + "WHERE world = ? AND x = ? AND y = ? AND z = ?"; try (PreparedStatement statement = connection.prepareStatement(updateData)) { - for (int i = 0; i < blockData.size(); i++) { - KitBlockData data = blockData.get(i); - if (data == null) continue; + for (KitBlockData data : blockData.values()) { + if (data == null || data.getWorld() == null) continue; statement.setString(1, data.getType().toString()); statement.setString(2, data.getKit().getName()); statement.setBoolean(3, data.showHologram()); @@ -51,7 +50,6 @@ public class DataManager { statement.setInt(8, data.getX()); statement.setInt(9, data.getY()); statement.setInt(10, data.getZ()); - statement.executeUpdate(); statement.addBatch(); } @@ -61,6 +59,7 @@ public class DataManager { } public void updateBlockData(KitBlockData blockData) { + if (blockData.getWorld() == null) return; this.async(() -> this.databaseConnector.connect(connection -> { String updateData = "UPDATE " + this.getTablePrefix() + "blockdata SET type = ?, kit = ?, holograms = ?, " + "displayItems = ?, particles = ?, itemOverride = ? " + @@ -82,6 +81,7 @@ public class DataManager { } public void createBlockData(KitBlockData blockData) { + if (blockData.getWorld() == null) return; this.async(() -> this.databaseConnector.connect(connection -> { String createData ="INSERT INTO " + this.getTablePrefix() + "blockdata (" + "type, kit, holograms, displayItems, particles, itemOverride, world, x, y, z)" + @@ -123,13 +123,14 @@ public class DataManager { try (Statement statement = connection.createStatement()) { ResultSet result = statement.executeQuery(selectData); while (result.next()) { + World world = Bukkit.getWorld(result.getString("world")); + if (world == null) continue; KitType type = KitType.valueOf(result.getString("type")); String kit = result.getString("kit"); boolean holograms = result.getBoolean("holograms"); boolean displayItems = result.getBoolean("displayItems"); boolean particles = result.getBoolean("particles"); boolean itemOverride = result.getBoolean("itemOverride"); - World world = Bukkit.getWorld(result.getString("world")); int x = result.getInt("x"); int y = result.getInt("y"); int z = result.getInt("z"); diff --git a/src/main/java/com/songoda/ultimatekits/database/DataMigrationManager.java b/src/main/java/com/songoda/ultimatekits/database/DataMigrationManager.java index aa80b4b..79d9903 100644 --- a/src/main/java/com/songoda/ultimatekits/database/DataMigrationManager.java +++ b/src/main/java/com/songoda/ultimatekits/database/DataMigrationManager.java @@ -1,6 +1,7 @@ package com.songoda.ultimatekits.database; import com.songoda.ultimatekits.database.migrations._1_InitialMigration; +import com.songoda.ultimatekits.database.migrations._2_DuplicateMigration; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -11,16 +12,17 @@ import java.util.stream.Collectors; public class DataMigrationManager { - private List migrations; - private DatabaseConnector databaseConnector; - private DataManager dataManager; + private final List migrations; + private final DatabaseConnector databaseConnector; + private final DataManager dataManager; public DataMigrationManager(DatabaseConnector databaseConnector, DataManager dataManager) { this.databaseConnector = databaseConnector; this.dataManager = dataManager; this.migrations = Arrays.asList( - new _1_InitialMigration() + new _1_InitialMigration(), + new _2_DuplicateMigration(databaseConnector instanceof SQLiteConnector) ); } diff --git a/src/main/java/com/songoda/ultimatekits/database/migrations/_1_InitialMigration.java b/src/main/java/com/songoda/ultimatekits/database/migrations/_1_InitialMigration.java index 2982a8e..8474bc0 100644 --- a/src/main/java/com/songoda/ultimatekits/database/migrations/_1_InitialMigration.java +++ b/src/main/java/com/songoda/ultimatekits/database/migrations/_1_InitialMigration.java @@ -1,8 +1,6 @@ package com.songoda.ultimatekits.database.migrations; -import com.songoda.ultimatekits.UltimateKits; import com.songoda.ultimatekits.database.DataMigration; -import com.songoda.ultimatekits.database.MySQLConnector; import java.sql.Connection; import java.sql.SQLException; @@ -16,8 +14,8 @@ public class _1_InitialMigration extends DataMigration { @Override public void migrate(Connection connection, String tablePrefix) throws SQLException { - String autoIncrement = UltimateKits.getInstance().getDatabaseConnector() instanceof - MySQLConnector ? " AUTO_INCREMENT" : ""; + //String autoIncrement = UltimateKits.getInstance().getDatabaseConnector() instanceof + // MySQLConnector ? " AUTO_INCREMENT" : ""; // Create plugin settings table try (Statement statement = connection.createStatement()) { @@ -28,10 +26,10 @@ public class _1_InitialMigration extends DataMigration { "displayItems BOOLEAN NOT NULL," + "particles BOOLEAN NOT NULL," + "itemOverride BOOLEAN NOT NULL," + - "world TEXT NOT NULL," + - "x INTEGER NOT NULL," + - "y INTEGER NOT NULL," + - "z INTEGER NOT NULL " + + "world TEXT NOT NULL," + // PK + "x INTEGER NOT NULL," + // PK + "y INTEGER NOT NULL," + // PK + "z INTEGER NOT NULL " + // PK ")"); } } diff --git a/src/main/java/com/songoda/ultimatekits/database/migrations/_2_DuplicateMigration.java b/src/main/java/com/songoda/ultimatekits/database/migrations/_2_DuplicateMigration.java new file mode 100644 index 0000000..ac12b6c --- /dev/null +++ b/src/main/java/com/songoda/ultimatekits/database/migrations/_2_DuplicateMigration.java @@ -0,0 +1,99 @@ +package com.songoda.ultimatekits.database.migrations; + +import com.songoda.ultimatekits.database.DataMigration; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.HashMap; + +public class _2_DuplicateMigration extends DataMigration { + + final boolean sqlite; + public _2_DuplicateMigration(boolean sqlite) { + super(2); + this.sqlite = sqlite; + } + + @Override + public void migrate(Connection connection, String tablePrefix) throws SQLException { + // Fix duplicate data caused by old sqlite data duplication bug + if(sqlite) { + HashMap data = new HashMap(); + // grab a copy of the unique data values + try (Statement statement = connection.createStatement()) { + ResultSet allData = statement.executeQuery("SELECT * FROM " + tablePrefix + "blockdata"); + while (allData.next()) { + String world = allData.getString("world"); + int x = allData.getInt("x"); + int y = allData.getInt("y"); + int z = allData.getInt("z"); + String key = world + ";" + x + ";" + y + ";" + z + ";"; + if(!data.containsKey(key)) { + data.put(key, new TempKitData( + allData.getString("type"), + allData.getString("kit"), + allData.getBoolean("holograms"), + allData.getBoolean("displayItems"), + allData.getBoolean("particles"), + allData.getBoolean("itemOverride"), + world, x, y, z + )); + } + } + allData.close(); + } + if(data.isEmpty()) return; + connection.setAutoCommit(false); + // first delete old data + try (Statement statement = connection.createStatement()) { + statement.executeUpdate("DELETE FROM " + tablePrefix + "blockdata"); + } + // then re-add valid unique data + try (PreparedStatement statement = connection.prepareStatement("INSERT INTO " + tablePrefix + "blockdata (" + + "type, kit, holograms, displayItems, particles, itemOverride, world, x, y, z)" + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")) { + for(TempKitData blockData : data.values()) { + statement.setString(1, blockData.type); + statement.setString(2, blockData.kit); + statement.setBoolean(3, blockData.holograms); + statement.setBoolean(4, blockData.displayItems); + statement.setBoolean(5, blockData.particles); + statement.setBoolean(6, blockData.itemOverride); + statement.setString(7, blockData.world); + statement.setInt(8, blockData.x); + statement.setInt(9, blockData.y); + statement.setInt(10, blockData.z); + statement.addBatch(); + } + statement.executeBatch(); + } + connection.commit(); + connection.setAutoCommit(true); + // free up disk space (sqlite command) + try (Statement statement = connection.createStatement()) { + statement.executeUpdate("VACUUM"); + } + } + } + + static class TempKitData { + final String type, kit, world; + final int x, y, z; + final boolean holograms, displayItems, particles, itemOverride; + + public TempKitData(String type, String kit, boolean holograms, boolean displayItems, boolean particles, boolean itemOverride, String world, int x, int y, int z) { + this.type = type; + this.kit = kit; + this.world = world; + this.x = x; + this.y = y; + this.z = z; + this.holograms = holograms; + this.displayItems = displayItems; + this.particles = particles; + this.itemOverride = itemOverride; + } + } +} diff --git a/src/main/java/com/songoda/ultimatekits/kit/KitBlockData.java b/src/main/java/com/songoda/ultimatekits/kit/KitBlockData.java index 456f06a..f15e497 100644 --- a/src/main/java/com/songoda/ultimatekits/kit/KitBlockData.java +++ b/src/main/java/com/songoda/ultimatekits/kit/KitBlockData.java @@ -20,12 +20,10 @@ public class KitBlockData { this.items = items; this.itemOverride = itemOverride; this.type = type; - UltimateKits.getInstance().getDataManager().createBlockData(this); } public KitBlockData(Kit kit, Location location) { this(kit, location, KitType.PREVIEW, false, false, false, false); - UltimateKits.getInstance().getDataManager().createBlockData(this); } public void reset() { diff --git a/src/main/java/com/songoda/ultimatekits/kit/KitManager.java b/src/main/java/com/songoda/ultimatekits/kit/KitManager.java index 3bf2398..c56f06d 100644 --- a/src/main/java/com/songoda/ultimatekits/kit/KitManager.java +++ b/src/main/java/com/songoda/ultimatekits/kit/KitManager.java @@ -1,7 +1,6 @@ package com.songoda.ultimatekits.kit; import com.songoda.ultimatekits.UltimateKits; -import org.bukkit.Bukkit; import org.bukkit.Location; import java.util.*; @@ -9,7 +8,7 @@ import java.util.*; public final class KitManager { private Map kitsAtLocations = new HashMap<>(); - private List registeredKits = new LinkedList<>(); + private final List registeredKits = new LinkedList<>(); public boolean addKit(Kit kit) { if (kit == null) return false; @@ -30,15 +29,18 @@ public final class KitManager { } } - public void addKitToLocation(Kit kit, Location location) { + public KitBlockData addKitToLocation(Kit kit, Location location) { KitBlockData data = new KitBlockData(kit, location); kitsAtLocations.put(roundLocation(location), data); + return data; } - public void addKitToLocation(Kit kit, Location location, KitType type, boolean hologram, boolean particles, boolean items, boolean itemOverride) { - KitBlockData kitBlockData = kitsAtLocations.put(roundLocation(location), new KitBlockData(kit, location, type, hologram, particles, items, itemOverride)); + public KitBlockData addKitToLocation(Kit kit, Location location, KitType type, boolean hologram, boolean particles, boolean items, boolean itemOverride) { + KitBlockData data = new KitBlockData(kit, location, type, hologram, particles, items, itemOverride); + kitsAtLocations.put(roundLocation(location), data); if (UltimateKits.getInstance().getHologram() != null) - UltimateKits.getInstance().getHologram().update(kitBlockData); + UltimateKits.getInstance().getHologram().update(data); + return data; } public Kit removeKitFromLocation(Location location) {