diff --git a/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/EpicFarmingPlugin.java b/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/EpicFarmingPlugin.java index f3c95d8..baec0da 100644 --- a/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/EpicFarmingPlugin.java +++ b/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/EpicFarmingPlugin.java @@ -172,6 +172,8 @@ public class EpicFarmingPlugin extends JavaPlugin implements EpicFarming { } + // Save data initially so that if the person reloads again fast they don't lose all their data. + this.saveToFile(); }, 10); this.references = new References(); @@ -252,35 +254,9 @@ public class EpicFarmingPlugin extends JavaPlugin implements EpicFarming { * Saves registered farms to file. */ private void saveToFile() { - this.storage.closeConnection(); checkStorage(); - /* - * Dump FarmManager to file. - */ - for (Farm farm : farmManager.getFarms().values()) { - if (farm.getLocation() == null - || farm.getLocation().getWorld() == null) continue; - String locstr = Methods.serializeLocation(farm.getLocation()); - storage.prepareSaveItem("farms",new StorageItem("location",locstr), - new StorageItem("level",farm.getLevel().getLevel()), - new StorageItem("placedby",farm.getPlacedBy().toString()), - new StorageItem("contents",((EFarm)farm).dumpInventory())); - } - - /* - * Dump BoostManager to file. - */ - for (BoostData boostData : boostManager.getBoosts()) { - String endTime = String.valueOf(boostData.getEndTime()); - storage.prepareSaveItem("boosts",new StorageItem("endtime",endTime), - new StorageItem("amount",boostData.getMultiplier()), - new StorageItem("player",boostData.getPlayer())); - } - - //Save to file storage.doSave(); - } private void update() { diff --git a/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/farming/ELevel.java b/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/farming/ELevel.java index b0f66e6..57506f6 100644 --- a/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/farming/ELevel.java +++ b/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/farming/ELevel.java @@ -28,7 +28,10 @@ public class ELevel implements Level { EpicFarmingPlugin instance = EpicFarmingPlugin.getInstance(); - description.add(instance.getLocale().getMessage("interface.button.radius", radius)); + description.add(instance + .getLocale() + .getMessage("interface.button.radius", + radius)); description.add(instance.getLocale().getMessage("interface.button.speed", speedMultiplier)); if (autoHarvest) diff --git a/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/storage/Storage.java b/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/storage/Storage.java index 9f8cb73..8d93370 100644 --- a/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/storage/Storage.java +++ b/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/storage/Storage.java @@ -1,9 +1,15 @@ package com.songoda.epicfarming.storage; +import com.songoda.epicfarming.api.farming.Farm; +import com.songoda.epicfarming.boost.BoostData; +import com.songoda.epicfarming.farming.EFarm; +import com.songoda.epicfarming.utils.Methods; import com.songoda.epicfarming.EpicFarmingPlugin; -import com.songoda.epicfarming.api.EpicFarming; import com.songoda.epicfarming.utils.ConfigWrapper; +import com.songoda.epicfarming.utils.Methods; +import org.bukkit.Material; +import java.util.ArrayList; import java.util.List; public abstract class Storage { @@ -25,8 +31,37 @@ public abstract class Storage { public abstract void prepareSaveItem(String group, StorageItem... items); + public void updateData(EpicFarmingPlugin instance) { + /* + * Dump FarmManager to file. + */ + for (Farm farm : instance.getFarmManager().getFarms().values()) { + if (farm.getLocation() == null + || farm.getLocation().getWorld() == null) continue; + String locstr = Methods.serializeLocation(farm.getLocation()); + prepareSaveItem("farms",new StorageItem("location",locstr), + new StorageItem("level",farm.getLevel().getLevel()), + new StorageItem("placedby",farm.getPlacedBy().toString()), + new StorageItem("contents",((EFarm)farm).dumpInventory())); + } + + /* + * Dump BoostManager to file. + */ + for (BoostData boostData : instance.getBoostManager().getBoosts()) { + String endTime = String.valueOf(boostData.getEndTime()); + prepareSaveItem("boosts",new StorageItem("endtime",endTime), + new StorageItem("amount",boostData.getMultiplier()), + new StorageItem("player",boostData.getPlayer())); + } + } + public abstract void doSave(); + public abstract void save(); + + public abstract void makeBackup(); + public abstract void closeConnection(); } diff --git a/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/storage/types/StorageMysql.java b/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/storage/types/StorageMysql.java index 5bd63c1..f4533d4 100644 --- a/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/storage/types/StorageMysql.java +++ b/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/storage/types/StorageMysql.java @@ -1,11 +1,11 @@ package com.songoda.epicfarming.storage.types; - -import com.songoda.epicfarming.EpicFarmingPlugin; import com.songoda.epicfarming.storage.Storage; import com.songoda.epicfarming.storage.StorageItem; import com.songoda.epicfarming.storage.StorageRow; import com.songoda.epicfarming.utils.MySQLDatabase; +import com.songoda.epicfarming.EpicFarmingPlugin; +import com.songoda.epicfarming.utils.MySQLDatabase; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -18,8 +18,9 @@ import java.util.Map; public class StorageMysql extends Storage { + private static Map toSave = new HashMap<>(); + private static Map lastSave = new HashMap<>(); private MySQLDatabase database; - private static List toSave = new ArrayList<>(); public StorageMysql(EpicFarmingPlugin instance) { super(instance); @@ -66,42 +67,106 @@ public class StorageMysql extends Storage { @Override public void prepareSaveItem(String group, StorageItem... items) { - StringBuilder sql = new StringBuilder(String.format("INSERT INTO `" + instance.getConfig().getString("Database.Prefix") + "%s`", group)); - - sql.append(" ("); - - for (StorageItem item : items) { - if (item == null || item.asObject() == null) continue; - sql.append(String.format("`%s`, ", item.getKey())); - } - - sql = new StringBuilder(sql.substring(0, sql.length() - 2)); - - sql.append(") VALUES ("); - - for (StorageItem item : items) { - if (item == null || item.asObject() == null) continue; - sql.append(String.format("'%s', ", item.asObject().toString())); - } - - sql = new StringBuilder(sql.substring(0, sql.length() - 2)); - - sql.append(");"); - - toSave.add(sql.toString()); + toSave.put(group + "]" + items[0].asObject().toString(), items); } @Override public void doSave() { - try { - // Clear database - database.getConnection().createStatement().execute("TRUNCATE `" + instance.getConfig().getString("Database.Prefix") + "farms`"); - database.getConnection().createStatement().execute("TRUNCATE `" + instance.getConfig().getString("Database.Prefix") + "boosts`"); + this.updateData(instance); + if (toSave.isEmpty()) return; + Map nextSave = new HashMap<>(toSave); + if (lastSave.isEmpty()) + lastSave.putAll(toSave); + + this.makeBackup(); + this.save(); + + toSave.clear(); + lastSave.clear(); + lastSave.putAll(nextSave); + } + + @Override + public void save() { + try { Statement stmt = database.getConnection().createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); - for (String line : toSave) { - stmt.addBatch(line); + last: + for (Map.Entry last : lastSave.entrySet()) { + String lastKey = last.getKey().split("]")[0]; + String lastValue = last.getValue()[0].asObject().toString(); + + for (Map.Entry to : toSave.entrySet()) { + String toKey = to.getKey().split("]")[0]; + if (!toKey.equals(lastKey) + || !to.getValue()[0].asObject().equals(lastValue) + || to.getValue().length != last.getValue().length) + continue; + toSave.remove(toKey); + for (int i = 0; i < to.getValue().length - 1; i ++) { + if (!to.getValue()[i].asObject().toString() + .equals(last.getValue()[i].asObject().toString())) { + //Update + StorageItem[] items = to.getValue(); + StringBuilder sql = new StringBuilder(String.format("UPDATE `" + instance.getConfig().getString("Database.Prefix") + "%s`", toKey)); + + sql.append(" SET"); + + for (StorageItem item : items) { + if (item == null || item.asObject() == null) continue; + String key = item.getKey().split("]")[0]; + sql.append(String.format("`%s` = '%s', ", key, item.asObject().toString())); + } + + sql = new StringBuilder(sql.substring(0, sql.length() - 2)); + + sql.append(String.format(" WHERE `%s`='%s'", last.getValue()[0].getKey(), last.getValue()[0].asObject().toString())); + + stmt.addBatch(sql.toString()); + + continue last; + } + } + // Already up to date. + + continue last; + } + //Was not found delete. + StringBuilder sql = new StringBuilder(String.format("DELETE FROM `" + instance.getConfig().getString("Database.Prefix") + "%s`", lastKey)); + sql.append(String.format(" WHERE `%s`='%s'", last.getValue()[0].getKey(), last.getValue()[0].asObject().toString())); + stmt.addBatch(sql.toString()); + + } + + for (Map.Entry to : toSave.entrySet()) { + String toKey = to.getKey().split("]")[0]; + //Add + StorageItem[] items = to.getValue(); + StringBuilder sql = new StringBuilder(String.format("INSERT INTO `" + instance.getConfig().getString("Database.Prefix") + "%s`", toKey)); + + sql.append(" ("); + + for (StorageItem item : items) { + if (item == null || item.asObject() == null) continue; + String key = item.getKey().split("]")[0]; + sql.append(String.format("`%s`, ", key)); + } + + sql = new StringBuilder(sql.substring(0, sql.length() - 2)); + + sql.append(") VALUES ("); + + for (StorageItem item : items) { + if (item == null || item.asObject() == null) continue; + sql.append(String.format("'%s', ", item.asObject().toString())); + } + + sql = new StringBuilder(sql.substring(0, sql.length() - 2)); + + sql.append(");"); + + stmt.addBatch(sql.toString()); } stmt.executeBatch(); @@ -113,6 +178,11 @@ public class StorageMysql extends Storage { } } + @Override + public void makeBackup() { + + } + @Override public void closeConnection() { try { @@ -122,3 +192,4 @@ public class StorageMysql extends Storage { } } } + diff --git a/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/storage/types/StorageYaml.java b/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/storage/types/StorageYaml.java index 9343b2b..ab9665e 100644 --- a/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/storage/types/StorageYaml.java +++ b/EpicFarming-Plugin/src/main/java/com/songoda/epicfarming/storage/types/StorageYaml.java @@ -1,12 +1,11 @@ package com.songoda.epicfarming.storage.types; -import com.songoda.epicfarming.EpicFarmingPlugin; import com.songoda.epicfarming.storage.Storage; import com.songoda.epicfarming.storage.StorageItem; import com.songoda.epicfarming.storage.StorageRow; +import com.songoda.epicfarming.EpicFarmingPlugin; import com.songoda.epicfarming.utils.Debugger; import org.apache.commons.io.FileUtils; -import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.MemorySection; @@ -17,6 +16,7 @@ import java.util.*; public class StorageYaml extends Storage { private static final Map toSave = new HashMap<>(); + private static final Map lastSave = new HashMap<>(); public StorageYaml(EpicFarmingPlugin instance) { super(instance); @@ -65,39 +65,66 @@ public class StorageYaml extends Storage { @Override public void doSave() { - try { - dataFile.getConfig().set("data", null); // Clear file + this.updateData(instance); + if (toSave.isEmpty()) return; + Map nextSave = new HashMap<>(toSave); - File data = new File(instance.getDataFolder() + "/data.yml"); - File dataClone = new File(instance.getDataFolder() + "/data-backup-" + System.currentTimeMillis() + ".yml"); - try { - FileUtils.copyFile(data, dataClone); - } catch (IOException e) { - Debugger.runReport(e); - } - Deque backups = new ArrayDeque<>(); - for (File file : Objects.requireNonNull(instance.getDataFolder().listFiles())) { - if (file.getName().toLowerCase().contains("data-backup")) { - backups.add(file); + if (lastSave.isEmpty()) + lastSave.putAll(toSave); + + this.makeBackup(); + this.save(); + + toSave.clear(); + lastSave.clear(); + lastSave.putAll(nextSave); + } + + @Override + public void save() { + try { + for (Map.Entry entry : lastSave.entrySet()) { + if (toSave.containsKey(entry.getKey())) { + Object newValue = toSave.get(entry.getKey()); + if (!entry.getValue().equals(newValue)) { + dataFile.getConfig().set(entry.getKey(), entry.getValue()); + } + toSave.remove(newValue); + } else { + dataFile.getConfig().set(entry.getKey(), null); } } - if (backups.size() > 5) { - backups.getFirst().delete(); - } - for (Map.Entry entry : toSave.entrySet()) { dataFile.getConfig().set(entry.getKey(), entry.getValue()); } dataFile.saveConfig(); - - toSave.clear(); } catch (NullPointerException e) { Debugger.runReport(e); } } + @Override + public void makeBackup() { + File data = new File(instance.getDataFolder(), "data.yml"); + File dataClone = new File(instance.getDataFolder(), "data-backup-" + System.currentTimeMillis() + ".yml"); + try { + FileUtils.copyFile(data, dataClone); + } catch (IOException e) { + Debugger.runReport(e); + } + Deque backups = new ArrayDeque<>(); + for (File file : Objects.requireNonNull(instance.getDataFolder().listFiles())) { + if (file.getName().toLowerCase().contains("data-backup")) { + backups.add(file); + } + } + if (backups.size() > 3) { + backups.getFirst().delete(); + } + } + @Override public void closeConnection() { dataFile.saveConfig();