Browse Source

Version 2.5

gamerx 6 years ago
parent
commit
cab38c12b9

+ 4 - 4
pom.xml

@@ -2,14 +2,14 @@
     <modelVersion>4.0.0</modelVersion>
     <groupId>com.bukkitbackup</groupId>
     <artifactId>Backup</artifactId>
-    <version>2.0</version>
+    <version>2.5</version>
     <name>Backup</name>
     <description>A Backup plugin for Bukkit's Server mod API.</description>
     <url>https://github.com/gamerx/Backup</url>
     <repositories>
         <repository>
-            <id>maven.tgxn.net</id>
-            <url>http://maven.tgxn.net/bukkit-plugins/</url>
+            <id>repo.bukkit.org</id>
+            <url>http://repo.bukkit.org/content/groups/public/</url>
         </repository>
     </repositories>
     <issueManagement>
@@ -64,7 +64,7 @@
         <dependency>
             <groupId>org.bukkit</groupId>
             <artifactId>bukkit</artifactId>
-            <version>1.2.5-R4.0</version>
+            <version>1.4.7-R1.0</version>
         </dependency>
     </dependencies>
     <properties>

+ 9 - 0
pom.xml.rej

@@ -0,0 +1,9 @@
+diff a/pom.xml b/pom.xml	(rejected hunks)
+@@ -2,6 +2,7 @@
+      <modelVersion>4.0.0</modelVersion>
+      <groupId>com.bukkitbackup</groupId>
+      <artifactId>Backup</artifactId>
+++<<<<<<< HEAD
+ +    <version>2.0</version>
+ +=======
+      <version>2.5</version>

+ 130 - 68
src/main/java/com/bukkitbackup/full/BackupFull.java

@@ -5,71 +5,67 @@ import com.bukkitbackup.full.config.Strings;
 import com.bukkitbackup.full.config.UpdateChecker;
 import com.bukkitbackup.full.events.CommandHandler;
 import com.bukkitbackup.full.events.EventListener;
+import com.bukkitbackup.full.threading.BackupScheduler;
 import com.bukkitbackup.full.threading.BackupTask;
 import com.bukkitbackup.full.threading.PrepareBackup;
-import com.bukkitbackup.full.threading.SyncSaveAll;
-import com.bukkitbackup.full.threading.tasks.BackupEverything;
-import com.bukkitbackup.full.threading.tasks.BackupPlugins;
-import com.bukkitbackup.full.threading.tasks.BackupWorlds;
 import com.bukkitbackup.full.utils.FileUtils;
 import com.bukkitbackup.full.utils.LogUtils;
 import com.bukkitbackup.full.utils.MetricUtils;
 import java.io.File;
 import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import org.bukkit.Server;
 import org.bukkit.plugin.PluginManager;
 import org.bukkit.plugin.java.JavaPlugin;
 
 /**
- * BackupFull - Plugin Loader Class. This extends Bukkit's JavaPlugin class.
+ * Backup - The simple server backup solution.
  *
- * @author Domenic Horner
+ * @author Domenic Horner (gamerx)
+ * @author gamerx@gamerx.me
  */
 public class BackupFull extends JavaPlugin {
 
-    public File mainDataFolder;
-    private String clientID;
-    private static Strings strings;
-    private static Settings settings;
-    private PrepareBackup prepareBackup;
-    private static SyncSaveAll syncSaveAllUtil;
-    private static UpdateChecker updateChecker;
-    public static BackupEverything backupEverything;
-    public static BackupWorlds backupWorlds;
-    public static BackupPlugins backupPlugins;
+    // Public variables for class comms.
+    private static PrepareBackup prepareBackup;
     public static BackupTask backupTask;
+    
+    // Private variables for this class.
+    private static Settings settings;
+    private static Strings strings;
+    private File thisDataFolder;
+    private String clientUID;
 
     @Override
     public void onLoad() {
 
-        // Initalize main data folder variable.
-        mainDataFolder = this.getDataFolder();
-
-        // Initalize logging utilities.
+        // Set Data Folder, Init log utils.
+        thisDataFolder = this.getDataFolder();
         LogUtils.initLogUtils(this);
+        FileUtils.checkFolderAndCreate(thisDataFolder);
 
-        // check and create main datafile.
-        FileUtils.checkFolderAndCreate(mainDataFolder);
-
-        // Load configuration files.
-        strings = new Strings(new File(mainDataFolder, "strings.yml"));
-        settings = new Settings(new File(mainDataFolder, "config.yml"), strings);
+        // Setup Configuration Files.
+        strings = new Strings(new File(thisDataFolder, "strings.yml"));
+        settings = new Settings(new File(thisDataFolder, "config.yml"), strings);
 
         // Run version checking on configurations.
-        strings.checkStringsVersion(settings.getStringProperty("requiredstrings", ""));
+        //@TODO Refactor Settings & Strings Loading Code.
+        strings.checkStringsVersion(settings.getStringProperty("version", ""));
         settings.checkSettingsVersion(this.getDescription().getVersion());
 
-        // Complete initalization of LogUtils.
-        LogUtils.finishInitLogUtils(settings.getBooleanProperty("displaylog", true));
+        // Complete loading log utils.
+        LogUtils.finishInitLogUtils(settings.getBooleanProperty("displaylog", true), settings.getBooleanProperty("debugenabled", false));
 
-        // Load Metric Utils.
+        // BukkitMetrics Loading. (Not Plugin-Specific)
         try {
-            MetricUtils metricUtils = new MetricUtils(this, new File(mainDataFolder, "metrics.yml"));
+            MetricUtils metricUtils = new MetricUtils(this);
             metricUtils.start();
-            clientID = metricUtils.guid;
+            clientUID = metricUtils.guid;
         } catch (IOException ex) {
             LogUtils.exceptionLog(ex, "Exception loading metrics.");
         }
+
     }
 
     @Override
@@ -79,77 +75,143 @@ public class BackupFull extends JavaPlugin {
         Server pluginServer = getServer();
         PluginManager pluginManager = pluginServer.getPluginManager();
 
-        // Check backup path.
+        // Check backup path, create if required.
         FileUtils.checkFolderAndCreate(new File(settings.getStringProperty("backuppath", "backups")));
 
         // Setup backup tasks.
-        backupEverything = new BackupEverything(settings);
-        backupWorlds = new BackupWorlds(pluginServer, settings, strings);
-        backupPlugins = new BackupPlugins(settings, strings);
         backupTask = new BackupTask(this, settings, strings);
-
+        
         // Create new "PrepareBackup" instance.
         prepareBackup = new PrepareBackup(this, settings, strings);
 
-        // Initalize the update checker code.
-        updateChecker = new UpdateChecker(this.getDescription(), strings, clientID);
-
         // Initalize Command Listener.
-        getCommand("backup").setExecutor(new CommandHandler(prepareBackup, this, settings, strings, updateChecker));
-        getCommand("bu").setExecutor(new CommandHandler(prepareBackup, this, settings, strings, updateChecker));
+        getCommand("backup").setExecutor(new CommandHandler(prepareBackup, this, settings, strings));
+        getCommand("bu").setExecutor(new CommandHandler(prepareBackup, this, settings, strings));
 
         // Initalize Event Listener.
         EventListener eventListener = new EventListener(prepareBackup, this, settings, strings);
         pluginManager.registerEvents(eventListener, this);
 
-        // Configure main backup task schedule.
-        int backupInterval = settings.getIntervalInMinutes("backupinterval");
-        if (backupInterval != -1 && backupInterval != 0) {
-
-            // Convert to server ticks.
-            int backupIntervalInTicks = (backupInterval * 1200);
-
-            // Should the schedule repeat?
-            if (settings.getBooleanProperty("norepeat", false)) {
-                pluginServer.getScheduler().scheduleAsyncDelayedTask(this, prepareBackup, backupIntervalInTicks);
-                LogUtils.sendLog(strings.getString("norepeatenabled", Integer.toString(backupInterval)));
+        // Get the backup interval setting, and clean it.
+        String backupInterval = settings.getStringProperty("backupinterval", "15M").trim().toLowerCase();
+
+        // Initalize default variables.
+        int backupMinutes = 0; // Should contain interval, in minutes.
+        String[] backupSchedArray = null; // Should contain an array of times.
+
+        // Matches one or more numbers. (Interpret them as minutes)
+        if (backupInterval.matches("^[0-9]+$")) {
+
+            // Parse the value to integer.
+            backupMinutes = Integer.parseInt(backupInterval);
+            LogUtils.sendDebug("Entry is set to minutes. (M:0002)");
+
+        } // Matches one or more numbers, followed by a letter.
+        else if (backupInterval.matches("[0-9]+[a-z]")) {
+
+            // Parse for the integer.
+            Pattern timePattern = Pattern.compile("^([0-9]+)[a-z]$");
+            Matcher amountTime = timePattern.matcher(backupInterval);
+
+            // Parse it for the letter.
+            Pattern letterPattern = Pattern.compile("^[0-9]+([a-z])$");
+            Matcher letterTime = letterPattern.matcher(backupInterval);
+
+            // Confirm that we found a match for both items.
+            if (letterTime.matches() && amountTime.matches()) {
+
+                // Assign values to the variables.
+                String letter = letterTime.group(1);
+                int time = Integer.parseInt(amountTime.group(1));
+
+                // Perform matching for time spans, calculate back to minutes.
+                if (letter.equals("m")) { // Minutes
+                    backupMinutes = time;
+                } else if (letter.equals("h")) { // Hours
+                    backupMinutes = time * 60;
+                } else if (letter.equals("d")) { // Days
+                    backupMinutes = time * 60 * 12;
+                } else if (letter.equals("w")) { // Weeks
+                    backupMinutes = time * 60 * 12 * 7;
+                } else { // Assume minutes.
+                    LogUtils.sendLog(strings.getString("unknowntimeident"));
+                    backupMinutes = time;
+                }
             } else {
-                pluginServer.getScheduler().scheduleAsyncRepeatingTask(this, prepareBackup, backupIntervalInTicks, backupIntervalInTicks);
+                LogUtils.sendLog(strings.getString("checkbackupinterval"));
             }
+            LogUtils.sendDebug("Found correctly-formatted time (M:0001)");
+
+        } // Matches "TA[02:00,06:00,10:00,14:00,18:00,22:00]", or similar.
+        else if (backupInterval.matches("^ta\\[(.*)\\]$")) {
+
+            // Parse the string to get the array.
+            Pattern letterPattern = Pattern.compile("^ta\\[(.*)\\]$");
+            Matcher array = letterPattern.matcher(backupInterval);
+
+            // Put the array into a variable.
+            backupSchedArray = array.toString().split(",");
+            LogUtils.sendDebug("Found time array string. (M:0003)");
+
         } else {
-            LogUtils.sendLog(strings.getString("disbaledauto"));
+
+            // Nothing found.
+            LogUtils.sendLog(strings.getString("checkbackupinterval"));
+            backupMinutes = 0;
+            LogUtils.sendDebug("No correct backup interval string found. (M:0004)");
+
         }
 
-        // Configure save-all schedule.
-        int saveAllInterval = settings.getIntervalInMinutes("saveallinterval");
-        if (saveAllInterval != 0 && saveAllInterval != -1) {
+        // If interval is defined.
+        if (backupMinutes != 0) {
 
             // Convert to server ticks.
-            int saveAllIntervalInTicks = (saveAllInterval * 1200);
+            int backupIntervalInTicks = (backupMinutes * 1200);
+
+            // Schedule a repeating backup task.
+            pluginServer.getScheduler().runTaskTimerAsynchronously(this, prepareBackup, backupIntervalInTicks, backupIntervalInTicks);
+
+            LogUtils.sendDebug("Doing recurring backup interval code. (M:0005)");
+
+        } // If the backup should be done at pre-defined times.
+        else if (backupSchedArray != null) {
 
-            LogUtils.sendLog(strings.getString("savealltimeron", Integer.toString(saveAllInterval)));
+            // Create a backup scheduler instance.
+            BackupScheduler backupScheduler = new BackupScheduler(this, prepareBackup, settings, strings, backupSchedArray);
+
+            // Start the scheduler as another thread.
+            pluginServer.getScheduler().runTaskAsynchronously(this, backupScheduler);
+
+            LogUtils.sendDebug("Doing time array backup code. (M:0006)");
+
+        } // Automatic backups must be disabled.
+        else {
+
+            // Alert the user of disabled backup.
+            LogUtils.sendLog(strings.getString("disbaledauto"));
+
+            LogUtils.sendDebug("Disabled automatic backup. (M:0007)");
 
-            // Syncronised save-all.
-            syncSaveAllUtil = new SyncSaveAll(pluginServer, 0);
-            pluginServer.getScheduler().scheduleSyncRepeatingTask(this, syncSaveAllUtil, saveAllIntervalInTicks, saveAllIntervalInTicks);
         }
 
-        // Update & version checking loading.
+        // If the update check is enabled.
         if (settings.getBooleanProperty("enableversioncheck", true)) {
-            pluginServer.getScheduler().scheduleAsyncDelayedTask(this, updateChecker);
+
+            // Start the update checker in another thread.
+            pluginServer.getScheduler().runTaskAsynchronously(this, new UpdateChecker(this.getDescription(), strings, clientUID));
         }
 
         // Notify loading complete.
-        LogUtils.sendLog(this.getDescription().getFullName() + " has completed loading!");
+        LogUtils.sendLog(this.getDescription().getFullName() + " enabled!");
     }
 
     @Override
     public void onDisable() {
 
-        // Stop and scheduled tasks.
+        // Stop any scheduled tasks.
         this.getServer().getScheduler().cancelTasks(this);
 
         // Shutdown complete.
-        LogUtils.sendLog(this.getDescription().getFullName() + " has completely un-loaded!");
+        LogUtils.sendLog(this.getDescription().getFullName() + " diabled!");
     }
 }

+ 57 - 123
src/main/java/com/bukkitbackup/full/config/Settings.java

@@ -8,29 +8,59 @@ import org.bukkit.configuration.file.FileConfiguration;
 import org.bukkit.configuration.file.YamlConfiguration;
 
 /**
- * Class for loading the configuration file.
+ * Backup - The simple server backup solution.
  *
- * @author Domenic Horner
+ * @author Domenic Horner (gamerx)
  */
 public final class Settings {
 
-    private Strings strings;
-    private File configFile;
-    private FileConfiguration settings;
+    private static Strings strings;
+    private static FileConfiguration settings;
     public boolean useMaxSizeBackup = false;
-    public boolean debugMessages;
 
     public Settings(File configFile, Strings strings) {
-
-        this.strings = strings;
-        this.configFile = configFile;
+        
+        // Populate the strings variable.
+        Settings.strings = strings;
 
         try {
 
             // Checks if configuration file exists, creates it if it does not.
             if (!configFile.exists()) {
                 LogUtils.sendLog(strings.getString("newconfigfile"));
-                createDefaultSettings();
+
+                BufferedReader bReader = null;
+                BufferedWriter bWriter = null;
+                String line;
+
+                try {
+
+                    // Open a stream to the configuration file in the jar, because we can only access over the class loader.
+                    bReader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/resources/config.yml")));
+                    bWriter = new BufferedWriter(new FileWriter(configFile));
+
+                    // Writeout the new configuration file.
+                    while ((line = bReader.readLine()) != null) {
+                        bWriter.write(line);
+                        bWriter.newLine();
+                    }
+
+                } catch (Exception e) {
+                    LogUtils.exceptionLog(e, "Error opening stream.");
+                } finally {
+                    try {
+
+                        // Confirm the streams are closed.
+                        if (bReader != null) {
+                            bReader.close();
+                        }
+                        if (bWriter != null) {
+                            bWriter.close();
+                        }
+                    } catch (Exception e) {
+                        LogUtils.exceptionLog(e, "Error closing configuration stream.");
+                    }
+                }
             }
 
             // Initialize the configuration, and populate with settings.
@@ -38,50 +68,10 @@ public final class Settings {
             settings.load(configFile);
 
         } catch (Exception e) {
-            e.printStackTrace(System.out);
             LogUtils.exceptionLog(e, "Failed to load configuration.");
         }
     }
 
-    /**
-     * Load the properties file from the JAR and place it in the backup DIR.
-     */
-    private void createDefaultSettings() {
-
-        BufferedReader bReader = null;
-        BufferedWriter bWriter = null;
-        String line;
-
-        try {
-
-            // Open a stream to the configuration file in the jar, because we can only access over the class loader.
-            bReader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream("/resources/config.yml")));
-            bWriter = new BufferedWriter(new FileWriter(configFile));
-
-            // Writeout the new configuration file.
-            while ((line = bReader.readLine()) != null) {
-                bWriter.write(line);
-                bWriter.newLine();
-            }
-
-        } catch (Exception e) {
-            LogUtils.exceptionLog(e, "Error opening stream.");
-        } finally {
-            try {
-
-                // Confirm the streams are closed.
-                if (bReader != null) {
-                    bReader.close();
-                }
-                if (bWriter != null) {
-                    bWriter.close();
-                }
-            } catch (Exception e) {
-                LogUtils.exceptionLog(e, "Error closing configuration stream.");
-            }
-        }
-    }
-
     public void checkSettingsVersion(String requiredVersion) {
 
         // Get the version information from the file.
@@ -95,23 +85,12 @@ public final class Settings {
         }
     }
 
-    /**
-     * Used to upgrade the configuration file.
-     */
-    public void doConfigurationUpgrade() {
-        LogUtils.sendLog(strings.getString("updatingconf"));
-        if (configFile.exists()) {
-            configFile.delete();
-        }
-        createDefaultSettings();
-        LogUtils.sendLog(strings.getString("updatingconf"));
-    }
-
     /**
      * Gets the value of a integer property.
      *
      * @param property The name of the property.
-     * @return The value of the property, defaults to -1.
+     * @param defaultInt Set the default value of the integer.
+     * @return The value of the property.
      */
     public int getIntProperty(String property, int defaultInt) {
         return settings.getInt(property, defaultInt);
@@ -121,88 +100,41 @@ public final class Settings {
      * Gets the value of a boolean property.
      *
      * @param property The name of the property.
-     * @return The value of the property, defaults to true.
+     * @param defaultBool Set the default value of the boolean.
+     * @return The value of the property.
      */
     public boolean getBooleanProperty(String property, boolean defaultBool) {
         return settings.getBoolean(property, defaultBool);
     }
 
     /**
-     * Gets a value of the string property and make sure it is not null.
+     * Gets a value of the string property.
      *
      * @param property The name of the property.
+     * @param defaultString Set the default value of the string.
      * @return The value of the property.
      */
     public String getStringProperty(String property, String defaultString) {
         return settings.getString(property, defaultString);
     }
 
-    /**
-     * Method that gets the amount of time between backups. - Checks string for
-     * no automatic backup. - Checks for if only number (as minutes). - Checks
-     * for properly formatted string. - If unknown amount of time, sets as
-     * minutes.
-     *
-     * @return Amount of time between backups. (In minutes)
-     */
-    public int getIntervalInMinutes(String forSetting) {
-        String settingInterval = getStringProperty(forSetting, "15M").trim().toLowerCase();
-        // If it is null or set to disable.
-        if (settingInterval.equals("-1") || settingInterval == null) {
-            return 0;
-        }
-        // If it is just a number, return minutes.
-        if (settingInterval.matches("^[0-9]+$")) {
-            return Integer.parseInt(settingInterval);
-        } else if (settingInterval.matches("[0-9]+[a-z]")) {
-            Pattern timePattern = Pattern.compile("^([0-9]+)[a-z]$");
-            Matcher amountTime = timePattern.matcher(settingInterval);
-            Pattern letterPattern = Pattern.compile("^[0-9]+([a-z])$");
-            Matcher letterTime = letterPattern.matcher(settingInterval);
-            if (letterTime.matches() && amountTime.matches()) {
-                String letter = letterTime.group(1);
-                int time = Integer.parseInt(amountTime.group(1));
-                if (letter.equals("m")) {
-                    return time;
-                } else if (letter.equals("h")) {
-                    return time * 60;
-                } else if (letter.equals("d")) {
-                    return time * 1440;
-                } else if (letter.equals("w")) {
-                    return time * 10080;
-                } else {
-                    LogUtils.sendLog(strings.getString("unknowntimeident"));
-                    return time;
-                }
-            } else {
-                LogUtils.sendLog(strings.getString("checkbackupinterval"));
-                return 0;
-            }
-        } else {
-            LogUtils.sendLog(strings.getString("checkbackupinterval"));
-            return 0;
-        }
-    }
-
-    /**
-     * Method that gets the amount of time between backups. - Checks string for
-     * no automatic backup. - Checks for if only number (as minutes). - Checks
-     * for properly formatted string. - If unknown amount of time, sets as
-     * minutes.
-     *
-     * @return Amount of time between backups. (In minutes)
-     */
     public int getBackupLimits() {
         String limitSetting = getStringProperty("maxbackups", "25").trim().toLowerCase();
 
         // If it is null or set to disable.
-        if (limitSetting.equals("-1") || limitSetting == null) {
+        if (limitSetting.equals("-1")) {
             return 0;
         }
+
         // If it is just a number, return minutes.
         if (limitSetting.matches("^[0-9]+$")) {
+            LogUtils.sendDebug("Max Backups: Amount (M:0011)");
+
             return Integer.parseInt(limitSetting);
-        } else if (limitSetting.matches("[0-9]+[a-z]")) {
+        } else if (limitSetting.matches("^[0-9]+[a-z]$")) {
+            LogUtils.sendDebug("Max Backups: Size (M:0010)");
+
+            useMaxSizeBackup = true;
             Pattern timePattern = Pattern.compile("^([0-9]+)[a-z]$");
             Matcher amountTime = timePattern.matcher(limitSetting);
             Pattern letterPattern = Pattern.compile("^[0-9]+([a-z])$");
@@ -210,7 +142,7 @@ public final class Settings {
             if (letterTime.matches() && amountTime.matches()) {
                 String letter = letterTime.group(1);
                 int bytes = Integer.parseInt(amountTime.group(1));
-                useMaxSizeBackup = true;
+
                 if (letter.equals("k")) {
                     return bytes;
                 } else if (letter.equals("k")) {
@@ -228,6 +160,8 @@ public final class Settings {
                 return 0;
             }
         } else {
+            LogUtils.sendDebug("Max Backups: Unknown (M:0012)");
+
             LogUtils.sendLog(strings.getString("checksizelimit"));
             return 0;
         }

+ 5 - 11
src/main/java/com/bukkitbackup/full/config/Strings.java

@@ -6,9 +6,9 @@ import org.bukkit.configuration.file.FileConfiguration;
 import org.bukkit.configuration.file.YamlConfiguration;
 
 /**
- * Class for loading the strings configuration file.
+ * Backup - The simple server backup solution.
  *
- * @author Domenic Horner
+ * @author Domenic Horner (gamerx)
  */
 public class Strings {
 
@@ -115,13 +115,6 @@ public class Strings {
         }
     }
 
-    /**
-     * Method used when doing string file updates.
-     */
-    public void doStringsUpdate() {
-        loadStrings();
-    }
-
     /**
      * Gets a value of the string property.
      *
@@ -166,7 +159,8 @@ public class Strings {
      * Gets a value of the string property, and replaces options.
      *
      * @param property The identifier for the string.
-     * @param option The variable to replace %%ARG%% with.
+     * @param optionOne The variable to replace %%ARG%% with.
+     * @param optionTwo The variable to replace %%ARG1%% with.
      * @return The string from properties, with colors encoded, and text
      * replaced.
      */
@@ -197,7 +191,7 @@ public class Strings {
 
         // Check we got passed a string.
         if (toColor != null) {
-            return toColor.replaceAll("&([0-9a-f])", "\u00A7$1");
+            return toColor.replaceAll("&([0-9a-fklmnor])", "\u00A7$1");
         } else {
             return "";
         }

+ 2 - 3
src/main/java/com/bukkitbackup/full/config/UpdateChecker.java

@@ -7,10 +7,9 @@ import java.net.URL;
 import org.bukkit.plugin.PluginDescriptionFile;
 
 /**
- * Class for checking for the latest version of Backup. It will report to the
- * user depending if it is out of date or not.
+ * Backup - The simple server backup solution.
  *
- * @author Domenic Horner
+ * @author Domenic Horner (gamerx)
  */
 public class UpdateChecker implements Runnable {
 

+ 12 - 9
src/main/java/com/bukkitbackup/full/events/CommandHandler.java

@@ -15,6 +15,11 @@ import org.bukkit.entity.Player;
 import org.bukkit.event.Listener;
 import org.bukkit.plugin.Plugin;
 
+/**
+ * Backup - The simple server backup solution.
+ *
+ * @author Domenic Horner (gamerx)
+ */
 public class CommandHandler implements Listener, CommandExecutor {
 
     private PrepareBackup prepareBackup;
@@ -33,13 +38,12 @@ public class CommandHandler implements Listener, CommandExecutor {
      * @param settings Instance of the settings loader.
      * @param strings Instance of the strings loader.
      */
-    public CommandHandler(PrepareBackup prepareBackup, Plugin plugin, Settings settings, Strings strings, UpdateChecker updateChecker) {
+    public CommandHandler(PrepareBackup prepareBackup, Plugin plugin, Settings settings, Strings strings) {
         this.prepareBackup = prepareBackup;
         this.plugin = plugin;
         this.server = plugin.getServer();
         this.settings = settings;
         this.strings = strings;
-        this.updateChecker = updateChecker;
     }
 
     /**
@@ -105,7 +109,7 @@ public class CommandHandler implements Listener, CommandExecutor {
                     if (checkPerms(sender, "backup.toggle")) {
                         toggleEnabled(sender);
                     }
-                } // Help command - Show help & support info.} // Unknown command.
+                } // Unknown command.
                 else {
                     // Unknown Command Message.
                     messageSender(sender, strings.getString("unknowncommand"));
@@ -142,7 +146,7 @@ public class CommandHandler implements Listener, CommandExecutor {
         prepareBackup.isManualBackup = true;
 
         // Schedule an async task to run for the backup.
-        plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, prepareBackup);
+        plugin.getServer().getScheduler().runTask(plugin, prepareBackup);
     }
 
     /**
@@ -169,8 +173,7 @@ public class CommandHandler implements Listener, CommandExecutor {
         messageSender(sender, strings.getString("gettingversions"));
 
         // Start a new asynchronous task to get version and print them.
-        server.getScheduler().scheduleAsyncDelayedTask(plugin, new Runnable() {
-
+        server.getScheduler().runTaskAsynchronously(plugin, new Runnable() {
             @Override
             public void run() {
 
@@ -319,11 +322,11 @@ public class CommandHandler implements Listener, CommandExecutor {
     }
 
     private void toggleEnabled(CommandSender sender) {
-        if (prepareBackup.backupEnabled) {
-            prepareBackup.backupEnabled = false;
+        if (PrepareBackup.backupEnabled) {
+            PrepareBackup.backupEnabled = false;
             messageSender(sender, strings.getString("backuptoggleoff"));
         } else {
-            prepareBackup.backupEnabled = true;
+            PrepareBackup.backupEnabled = true;
             messageSender(sender, strings.getString("backuptoggleon"));
         }
     }

+ 5 - 2
src/main/java/com/bukkitbackup/full/events/EventListener.java

@@ -14,7 +14,7 @@ import org.bukkit.event.player.PlayerQuitEvent;
 import org.bukkit.plugin.Plugin;
 
 /**
- * Listens for login events, and perform actions based on what happened.
+ * Backup - The simple server backup solution.
  *
  * @author Domenic Horner (gamerx)
  */
@@ -59,12 +59,15 @@ public class EventListener implements Listener {
      * Called when a player leaves the server.
      *
      */
+    // @TODO determine how we should handle this if backups are at specific times.
+    // for now, i set it to 15 mins.
     private void playerPart(PlayerEvent event) {
         int onlinePlayers = plugin.getServer().getOnlinePlayers().length;
         // Check if it was the last player, and we need to stop backups after this last player leaves.
         if (onlinePlayers == 1 && !settings.getBooleanProperty("backupemptyserver", false)) {
             prepareBackup.isLastBackup = true;
-            int intervalInMinutes = settings.getIntervalInMinutes("backupinterval");
+            //int intervalInMinutes = settings.getBackupInterval();
+            int intervalInMinutes = 15;
             if (intervalInMinutes != 0) {
                 int interval = intervalInMinutes * 1200;
                 lastBackupID = plugin.getServer().getScheduler().scheduleAsyncDelayedTask(plugin, prepareBackup, interval);

+ 0 - 107
src/main/java/com/bukkitbackup/full/ftp/FTPUploader.java

@@ -1,107 +0,0 @@
-package com.bukkitbackup.full.ftp;
-
-import com.bukkitbackup.full.config.Settings;
-import com.bukkitbackup.full.config.Strings;
-import com.bukkitbackup.full.utils.FileUtils;
-import com.bukkitbackup.full.utils.LogUtils;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import sun.net.ftp.FtpClient;
-
-/**
- * The class provides the functionality to upload files to an FTP server.
- *
- * @author Domenic Horner
- */
-public class FTPUploader extends FtpClient implements Runnable {
-
-    private Settings settings;
-    private Strings strings;
-    private String fileToUpload;
-    private static FtpClient ftpClient;
-
-    public FTPUploader(Settings settings, Strings strings, String fileToUpload) {
-        this.settings = settings;
-        this.strings = strings;
-        this.fileToUpload = fileToUpload;
-    }
-
-    public void run() {
-
-        // Settings.
-        String connAddress = settings.getStringProperty("ftpserveraddress", "");
-        int connPort = settings.getIntProperty("ftpserverport", 21);
-        String connUser = settings.getStringProperty("ftpusername", "");
-        String connPassword = settings.getStringProperty("ftppassword", "");
-        String connTargetDIR = settings.getStringProperty("ftpdirectory", "backups");
-
-
-        // Perform checking of settings.
-        if (connAddress.equals("") || ((connPort < 0) && (connPort > 65535)) || connUser.equals("")) {
-            LogUtils.sendLog(strings.getString("ftpfailsettings"));
-            return;
-        }
-
-        // Check the file.
-        if (fileToUpload.isEmpty()) {
-            LogUtils.sendLog(strings.getString("ftpfailnofile"));
-            return;
-        }
-
-        // Initalize the buffer for the upload.
-        byte[] buffer = new byte[FileUtils.BUFFER_SIZE];
-
-        try {
-
-            // Start the connection.
-            LogUtils.sendLog(strings.getString("ftpconnecting", connAddress + ":" + connPort));
-            ftpClient = new FtpClient();
-            ftpClient.connect(conAddress);
-            LogUtils.sendLog(strings.getString("ftpestablished", connAddress));
-
-            // Atempt authentication.
-            ftpClient.login(connUser, connPassword);
-            LogUtils.sendLog(strings.getString("ftphellomsg", ftpClient.welcomeMsg));
-
-            // Switch to binary mode.
-            ftpClient.binary();
-
-            // Change directory if required.
-            if (!connTargetDIR.equals("")) {
-                ftpClient.cd(connTargetDIR);
-                LogUtils.sendLog(strings.getString("ftpchangedinto", connTargetDIR));
-            }
-
-            // Attempt the file upload.
-            LogUtils.sendLog(strings.getString("ftpuploading"));
-            FileInputStream in = new FileInputStream(fileToUpload.toString());
-            OutputStream out = ftpClient.put(fileToUpload.substring(fileToUpload.lastIndexOf("\\") + 1));
-            while (true) {
-                int bytes = in.read(buffer);
-                if (bytes < 0) {
-                    break;
-                }
-                out.write(buffer, 0, bytes);
-            }
-
-            // Notify complete, and close streams.
-            LogUtils.sendLog(strings.getString("ftpuploadcomplete"));
-            out.close();
-            in.close();
-
-        } catch (Exception ex) {
-            LogUtils.exceptionLog(ex);
-        }
-
-        if (ftpClient != null) {
-            try {
-                // Close the ftp Client.
-                ftpClient.closeServer();
-            } catch (IOException ex) {
-                LogUtils.exceptionLog(ex);
-            }
-            ftpClient = null;
-        }
-    }
-}

+ 66 - 0
src/main/java/com/bukkitbackup/full/threading/BackupScheduler.java

@@ -0,0 +1,66 @@
+package com.bukkitbackup.full.threading;
+
+import com.bukkitbackup.full.config.Settings;
+import com.bukkitbackup.full.config.Strings;
+import com.bukkitbackup.full.utils.LogUtils;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import org.bukkit.Server;
+import org.bukkit.plugin.Plugin;
+
+/**
+ * Backup - The simple server backup solution.
+ *
+ * @author Domenic Horner (gamerx)
+ */
+public class BackupScheduler implements Runnable {
+
+    private final Plugin plugin;
+    private final PrepareBackup prepareBackup;
+    private final Settings settings;
+    private final Strings strings;
+    private final Server pluginServer;
+    private final String[] timesArray;
+
+    public BackupScheduler(Plugin plugin, PrepareBackup prepareBackup, Settings settings, Strings strings, String[] timesArray) {
+        this.plugin = plugin;
+        this.prepareBackup = prepareBackup;
+        this.pluginServer = plugin.getServer();
+        this.settings = settings;
+        this.strings = strings;
+        this.timesArray = timesArray;
+    }
+
+    public void run() {
+        
+        // Loop to check if we need to backup.
+        while(true) {
+            
+            LogUtils.sendDebug("Checking if we should backup. (M:0008)");
+            
+            // Get current time, and format it to our requirements.
+            Calendar calendarInstance = Calendar.getInstance();
+            String timeNow = new SimpleDateFormat("HH:mm").format(calendarInstance.getTime());
+            
+            LogUtils.sendDebug("Time is: "+ timeNow + " (M:0009)");
+            
+            // Loop the array of times we want to backup at.
+            for (int j = 0; j < timesArray.length; j++) {
+                
+                // If we want to backup this minute, schedule a backupTask.
+                if(timesArray[j].equals(timeNow)) {
+                    pluginServer.getScheduler().scheduleAsyncDelayedTask(plugin, prepareBackup);
+                }
+            }
+            
+            // This sleeps the thread for 30 seconds in order to do another check.
+            try {
+                Thread.sleep(30000);
+            } catch (InterruptedException ex) {
+                LogUtils.exceptionLog(ex);
+            }
+            
+        }
+        
+    }
+}

+ 116 - 106
src/main/java/com/bukkitbackup/full/threading/BackupTask.java

@@ -1,9 +1,7 @@
 package com.bukkitbackup.full.threading;
 
-import com.bukkitbackup.full.BackupFull;
 import com.bukkitbackup.full.config.Settings;
 import com.bukkitbackup.full.config.Strings;
-import com.bukkitbackup.full.ftp.FTPUploader;
 import com.bukkitbackup.full.threading.tasks.BackupEverything;
 import com.bukkitbackup.full.threading.tasks.BackupPlugins;
 import com.bukkitbackup.full.threading.tasks.BackupWorlds;
@@ -17,34 +15,35 @@ import java.util.Arrays;
 import java.util.Calendar;
 import java.util.List;
 import org.bukkit.Server;
+import org.bukkit.World;
 import org.bukkit.entity.Player;
 import org.bukkit.plugin.Plugin;
 
 /**
- * This is the main backup thread. It handles backing everything up.
+ * Backup - The simple server backup solution.
  *
- * @author Domenic Horner
+ * @author Domenic Horner (gamerx)
  */
 public class BackupTask implements Runnable {
 
-    private Plugin plugin;
-    private Server pluginServer;
-    private Settings settings;
-    private Strings strings;
-    private boolean backupEverything;
-    private boolean splitBackup;
-    private boolean shouldZIP;
-    private boolean useTemp;
-    private String dateFormat;
+    private final Plugin plugin;
+    private final Server pluginServer;
+    private final Settings settings;
+    private final Strings strings;
+    private final boolean backupEverything;
+    private final boolean splitBackup;
+    private final boolean shouldZIP;
+    private final boolean useTemp;
+    private final String dateFormat;
     private final String worldContainer;
-    private String backupPath;
-    private String tempDestination;
+    private final String backupPath;
+    private final String tempDestination;
     private String thisBackupName;
+    
     // Threads.
-    private BackupWorlds worldBackupTask;
+    private final BackupWorlds worldBackupTask;
     private final BackupPlugins pluginBackupTask;
     private final BackupEverything everythingBackupTask;
-    private SyncSaveAll syncSaveAllUtil;
 
     public BackupTask(Plugin plugin, Settings settings, Strings strings) {
 
@@ -66,10 +65,10 @@ public class BackupTask implements Runnable {
         dateFormat = settings.getStringProperty("dateformat", "%1$tY-%1$tm-%1$td-%1$tH-%1$tM-%1$tS");
 
         // Import backup tasks.
-        everythingBackupTask = BackupFull.backupEverything;
-        worldBackupTask = BackupFull.backupWorlds;
-        pluginBackupTask = BackupFull.backupPlugins;
-
+        everythingBackupTask = new BackupEverything(settings);
+        worldBackupTask = new BackupWorlds(pluginServer, settings, strings);
+        pluginBackupTask =  new BackupPlugins(settings, strings);
+        
         // Generate the worldStore.
         if (useTemp) {
             String tempFolder = settings.getStringProperty("tempfoldername", "");
@@ -86,7 +85,7 @@ public class BackupTask implements Runnable {
 
     @Override
     public void run() {
-        
+
         // Get this instances folder name, set variables.
         thisBackupName = getBackupName();
 
@@ -170,11 +169,17 @@ public class BackupTask implements Runnable {
 
         File backupDir = new File(backupPath);
 
+        LogUtils.sendDebug("Delete old backups. (M:0013)");
 
         if (splitBackup) { // Look inside the folders.
+
+            LogUtils.sendDebug("Delete old backups. - Split Backup (M:0014)");
+
             // Check if we have a different container for worlds.
             if (!worldContainer.equals(".")) { // Custom.
 
+                LogUtils.sendDebug("Delete old backups. - Custom world container. (M:0015)");
+
                 backupDir = new File(backupPath.concat(FILE_SEPARATOR).concat(worldContainer));
 
                 File[] worldFoldersToClean = backupDir.listFiles();
@@ -195,8 +200,14 @@ public class BackupTask implements Runnable {
                     }
                 }
             } else {
+
+                LogUtils.sendDebug("Delete old backups. - Split backup. - No custom container. (M:0016)");
+
                 File[] foldersToClean = backupDir.listFiles();
                 for (int l = 0; l < foldersToClean.length; l++) {
+
+
+
                     // Make sure we are cleaning a directory.
                     if (foldersToClean[l].isDirectory()) {
                         cleanFolder(foldersToClean[l]);
@@ -206,53 +217,100 @@ public class BackupTask implements Runnable {
 
 
         } else { // Clean entire directory.
+
+            LogUtils.sendDebug("Delete old backups.- Plain and simple (M:0017)");
+
             cleanFolder(backupDir);
         }
     }
 
     private void cleanFolder(File folderToClean) throws IOException {
+
+        LogUtils.sendDebug("Attempting to clean: " + folderToClean.toString() + " (M:0014)");
+
         try {
 
             // Get total backup limit.
             int backupLimit = settings.getBackupLimits();
+            if (backupLimit != 0) {
 
-            // List all the files inside this folder.
-            File[] filesList = FileUtils.listFilesInDir(folderToClean);
+                // List all the files inside this folder.
+                File[] filesList = FileUtils.listItemsInDir(folderToClean);
 
-            // Check we listed the directory.
-            if (filesList == null) {
-                LogUtils.sendLog(strings.getString("failedlistdir"));
-                return;
-            }
+                LogUtils.sendDebug("Files: (M:0018)");
+                LogUtils.sendDebug(filesList.toString());
+
+                // Check we listed the directory.
+                if (filesList == null) {
+                    LogUtils.sendLog(strings.getString("failedlistdir"));
+                    return;
+                }
 
-            // Using size to limit backups.
-            if (settings.useMaxSizeBackup) {
+                // Using size to limit backups.
+                if (settings.useMaxSizeBackup) {
 
-                // Get total folder size.
-                int totalFolderSize = FileUtils.getTotalFolderSize(folderToClean);
+                    // Get total folder size.
+                    int totalFolderSize = FileUtils.getTotalFolderSize(folderToClean);
 
-                // If the amount of files exceeds the max backups to keep.
-                if (totalFolderSize > backupLimit) {
+                    // If the amount of files exceeds the max backups to keep.
+                    if (totalFolderSize > backupLimit) {
 
-                    // Create a list for deleted backups.
-                    ArrayList<File> deletedList = new ArrayList<File>(filesList.length);
+                        // Create a list for deleted backups.
+                        ArrayList<File> deletedList = new ArrayList<File>(filesList.length);
 
-                    // Inti variables.
-                    int maxModifiedIndex;
-                    long maxModified;
+                        // Inti variables.
+                        int maxModifiedIndex;
+                        long maxModified;
 
-                    // While the total folder size is bigger than the limit.
-                    while (FileUtils.getTotalFolderSize(folderToClean) > backupLimit) {
+                        // While the total folder size is bigger than the limit.
+                        while (FileUtils.getTotalFolderSize(folderToClean) > backupLimit) {
+
+                            // Create updated list.
+                            filesList = FileUtils.listFilesInDir(folderToClean);
+
+                            // List of all the backups.
+                            ArrayList<File> backupList = new ArrayList<File>(filesList.length);
+                            backupList.addAll(Arrays.asList(filesList));
+
+                            // Loop backup list.
+                            for (int i = 0; backupList.size() > 1; i++) {
+                                maxModifiedIndex = 0;
+                                maxModified = backupList.get(0).lastModified();
+                                for (int j = 1; j < backupList.size(); ++j) {
+                                    File currentFile = backupList.get(j);
+                                    if (currentFile.lastModified() > maxModified) {
+                                        maxModified = currentFile.lastModified();
+                                        maxModifiedIndex = j;
+                                    }
+                                }
+                                backupList.remove(maxModifiedIndex);
+                            }
+
+                            FileUtils.deleteDirectory(backupList.get(0));
+                            deletedList.add(backupList.get(0));
+                        }
+
+
+                        // Inform the user what backups are being deleted.
+                        LogUtils.sendLog(strings.getString("removeoldsize"));
+                        LogUtils.sendLog(Arrays.toString(deletedList.toArray()));
+                    }
 
-                        // Create updated list.
-                        filesList = FileUtils.listFilesInDir(folderToClean);
 
-                        // List of all the backups.
+
+
+                } else { // Using amount of backups.
+
+                    // If the amount of files exceeds the max backups to keep.
+                    if (filesList.length > backupLimit) {
                         ArrayList<File> backupList = new ArrayList<File>(filesList.length);
                         backupList.addAll(Arrays.asList(filesList));
 
-                        // Loop backup list,
-                        for (int i = 0; backupList.size() > 1; i++) {
+                        int maxModifiedIndex;
+                        long maxModified;
+
+                        //Remove the newst backups from the list.
+                        for (int i = 0; i < backupLimit; ++i) {
                             maxModifiedIndex = 0;
                             maxModified = backupList.get(0).lastModified();
                             for (int j = 1; j < backupList.size(); ++j) {
@@ -264,55 +322,19 @@ public class BackupTask implements Runnable {
                             }
                             backupList.remove(maxModifiedIndex);
                         }
-                        FileUtils.deleteDir(backupList.get(0));
-                        deletedList.add(backupList.get(0));
-                    }
-
-
-                    // Inform the user what backups are being deleted.
-                    LogUtils.sendLog(strings.getString("removeoldsize"));
-                    LogUtils.sendLog(Arrays.toString(deletedList.toArray()));
-                }
 
+                        // Inform the user what backups are being deleted.
+                        LogUtils.sendLog(strings.getString("removeoldage"));
+                        LogUtils.sendLog(Arrays.toString(backupList.toArray()));
 
-
-
-            } else { // Using amount of backups.
-
-                // If the amount of files exceeds the max backups to keep.
-                if (filesList.length > backupLimit) {
-                    ArrayList<File> backupList = new ArrayList<File>(filesList.length);
-                    backupList.addAll(Arrays.asList(filesList));
-
-                    int maxModifiedIndex;
-                    long maxModified;
-
-                    //Remove the newst backups from the list.
-                    for (int i = 0; i < backupLimit; ++i) {
-                        maxModifiedIndex = 0;
-                        maxModified = backupList.get(0).lastModified();
-                        for (int j = 1; j < backupList.size(); ++j) {
-                            File currentFile = backupList.get(j);
-                            if (currentFile.lastModified() > maxModified) {
-                                maxModified = currentFile.lastModified();
-                                maxModifiedIndex = j;
-                            }
+                        // Finally delete the backups.
+                        for (File backupToDelete : backupList) {
+                            FileUtils.deleteDir(backupToDelete);
                         }
-                        backupList.remove(maxModifiedIndex);
                     }
 
-                    // Inform the user what backups are being deleted.
-                    LogUtils.sendLog(strings.getString("removeoldage"));
-                    LogUtils.sendLog(Arrays.toString(backupList.toArray()));
-
-                    // Finally delete the backups.
-                    for (File backupToDelete : backupList) {
-                        FileUtils.deleteDir(backupToDelete);
-                    }
                 }
-
             }
-
         } catch (SecurityException se) {
             LogUtils.exceptionLog(se, "Failed to clean old backups: Security Exception.");
         }
@@ -323,12 +345,7 @@ public class BackupTask implements Runnable {
      * scheduler to prevent thread problems.
      */
     private void finishBackup() {
-
-        // Do the FTP upload if required.
-        if (shouldZIP && !splitBackup) {
-            doFTPUpload(backupPath.concat(FILE_SEPARATOR).concat(thisBackupName) + ".zip");
-        }
-
+        
         // Create new Runnable instance.
         Runnable run = new Runnable() {
 
@@ -337,8 +354,9 @@ public class BackupTask implements Runnable {
 
                 // Should we enable auto-save again?
                 if (settings.getBooleanProperty("enableautosave", true)) {
-                    syncSaveAllUtil = new SyncSaveAll(pluginServer, 2);
-                    pluginServer.getScheduler().scheduleSyncDelayedTask(plugin, syncSaveAllUtil);
+                    for (World world : pluginServer.getWorlds()) {
+                        world.setAutoSave(true);
+                    }
                 }
 
                 // Delete the temp directory.
@@ -413,16 +431,8 @@ public class BackupTask implements Runnable {
             }
         };
         pluginServer.getScheduler().scheduleSyncDelayedTask(plugin, run);
-        
-        PrepareBackup.backupInProgress = false;
-        
-    }
 
-    private void doFTPUpload(String ZIPFile) {
+        PrepareBackup.backupInProgress = false;
 
-        // This runs in another thread to ensure it does nto affect server performance.
-        if (settings.getBooleanProperty("ftpuploadenable", false)) {
-            pluginServer.getScheduler().scheduleAsyncDelayedTask(plugin, new FTPUploader(settings, strings, ZIPFile));
-        }
     }
 }

+ 22 - 22
src/main/java/com/bukkitbackup/full/threading/PrepareBackup.java

@@ -7,27 +7,26 @@ import com.bukkitbackup.full.utils.LogUtils;
 import java.util.Arrays;
 import java.util.List;
 import org.bukkit.Server;
+import org.bukkit.World;
 import org.bukkit.entity.Player;
 import org.bukkit.plugin.Plugin;
 
 /**
- * This class determines if we should start a backup, and what settings to use for the backup.
- * Once it has determined to start a backup, it pushes one out to a new thread.
- * 
- * @author Domenic Horner
+ * Backup - The simple server backup solution.
+ *
+ * @author Domenic Horner (gamerx)
  */
 public class PrepareBackup implements Runnable {
 
-    private Plugin plugin;
+    private final Plugin plugin;
     private final Server pluginServer;
     private final Settings settings;
-    private Strings strings;
-    
+    private final Strings strings;
     public static boolean backupInProgress = false;
     public static boolean backupEnabled = true;
     public boolean isLastBackup = false;
     public boolean isManualBackup;
-    
+
     public PrepareBackup(Plugin plugin, Settings settings, Strings strings) {
         this.plugin = plugin;
         this.pluginServer = plugin.getServer();
@@ -72,7 +71,7 @@ public class PrepareBackup implements Runnable {
                         prepareBackup();
                         isLastBackup = false;
                     } else {
-                        LogUtils.sendLog(strings.getString("abortedbackup", Integer.toString(settings.getIntervalInMinutes("backupinterval"))));
+                        LogUtils.sendLog(strings.getString("abortedbackup"));
                     }
                 } else {
 
@@ -103,37 +102,38 @@ public class PrepareBackup implements Runnable {
         } else {
             LogUtils.sendLog(strings.getString("backupoff"));
         }
-
-        // Check we should do a save-all.
-        if (settings.getBooleanProperty("alwayssaveall", false)) {
-            pluginServer.getScheduler().scheduleSyncDelayedTask(plugin, new SyncSaveAll(pluginServer, 0));
-            LogUtils.sendLog(strings.getString("alwayssaveall"));
-        }
     }
 
     /**
      * Prepared for, and starts, a doBackup.
      */
     protected void prepareBackup() {
-        
+
         // Tell the world!
         backupInProgress = true;
-        
+
         // Notify doBackup has started.
         notifyStarted();
 
-        // Perform final world save before backup, then turn off auto-saving.
-        pluginServer.getScheduler().scheduleSyncDelayedTask(plugin, new SyncSaveAll(pluginServer, 1));
-
-        // Save all players.
+        // Save all players to worlds.
         pluginServer.savePlayers();
 
+        // Turn off auto-saving of worlds.
+        for (World world : pluginServer.getWorlds()) {
+            world.setAutoSave(false);
+        }
+
+        // Perform final world save before backup.
+        for (World world : pluginServer.getWorlds()) {
+            world.save();
+        }
+
         // Scedule the doBackup.
         pluginServer.getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
 
             @Override
             public void run() {
-                pluginServer.getScheduler().scheduleAsyncDelayedTask(plugin, BackupFull.backupTask);
+                pluginServer.getScheduler().runTaskAsynchronously(plugin, BackupFull.backupTask);
             }
         });
         isManualBackup = false;

+ 2 - 2
src/main/java/com/bukkitbackup/full/threading/SyncSaveAll.java

@@ -9,8 +9,8 @@ public class SyncSaveAll implements Runnable {
     private int mode;
 
     /**
-     * This class is used for synchronizing the save-all task. It is started as
-     * a new thread.
+     * This class is used for synchronizing the save-all task.
+     * It is started as a new thread.
      *
      * @param server The server object for this plugin.
      * @param mode The type of save-all we are performing.

+ 7 - 7
src/main/java/com/bukkitbackup/full/threading/tasks/BackupEverything.java

@@ -1,15 +1,15 @@
 package com.bukkitbackup.full.threading.tasks;
 
 import com.bukkitbackup.full.config.Settings;
-import com.bukkitbackup.full.config.Strings;
 import com.bukkitbackup.full.utils.FileUtils;
 import static com.bukkitbackup.full.utils.FileUtils.FILE_SEPARATOR;
 import java.io.File;
 import java.io.FileFilter;
 
 /**
+ * Backup - The simple server backup solution.
  *
- * @author Domenic Horner
+ * @author Domenic Horner (gamerx)
  */
 public class BackupEverything {
 
@@ -17,7 +17,7 @@ public class BackupEverything {
     private final boolean shouldZIP;
     private final boolean useTemp;
     private final String tempDestination;
-    private FileFilter fileFilter;
+    private final FileFilter fileFilter;
 
     public BackupEverything(final Settings settings) {
 
@@ -62,11 +62,11 @@ public class BackupEverything {
 
     // The actual backup should be done here, as it is run in another thread.
     public void doEverything(String backupName) throws Exception {
+            // Copy the directory.
+            FileUtils.copyDirectory(new File(".".concat(FILE_SEPARATOR)), new File(tempDestination.concat(backupName)), fileFilter, true);
 
-        // Copy the directory.
-        FileUtils.copyDirectory(new File(".".concat(FILE_SEPARATOR)), new File(tempDestination), fileFilter, true);
+            // Perform the zipping action.
+            FileUtils.doCopyAndZIP(tempDestination.concat(backupName), backupPath.concat(FILE_SEPARATOR).concat(backupName), shouldZIP, useTemp);
 
-        // Perform the zipping action.
-        FileUtils.doCopyAndZIP(tempDestination, backupPath.concat(FILE_SEPARATOR).concat(backupName), shouldZIP, useTemp);
     }
 }

+ 2 - 3
src/main/java/com/bukkitbackup/full/threading/tasks/BackupPlugins.java

@@ -12,10 +12,9 @@ import java.util.Arrays;
 import java.util.List;
 
 /**
- * [Backup] BackupPlugins.java (Plugin Backup) Backup plugins when the function
- * doPlugins() is called.
+ * Backup - The simple server backup solution.
  *
- * @author Domenic Horner
+ * @author Domenic Horner (gamerx)
  */
 public class BackupPlugins {
 

+ 38 - 5
src/main/java/com/bukkitbackup/full/threading/tasks/BackupWorlds.java

@@ -5,7 +5,10 @@ import com.bukkitbackup.full.config.Strings;
 import com.bukkitbackup.full.utils.FileUtils;
 import static com.bukkitbackup.full.utils.FileUtils.FILE_SEPARATOR;
 import com.bukkitbackup.full.utils.LogUtils;
+import java.io.BufferedWriter;
 import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
 import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
@@ -13,10 +16,9 @@ import org.bukkit.Server;
 import org.bukkit.World;
 
 /**
- * [Backup] BackupWorlds.java (World Backup) Backup worlds when the function
- * doWorlds() is called.
+ * Backup - The simple server backup solution.
  *
- * @author Domenic Horner
+ * @author Domenic Horner (gamerx)
  */
 public class BackupWorlds {
 
@@ -29,8 +31,8 @@ public class BackupWorlds {
     private final boolean shouldZIP;
     private final boolean splitBackup;
     private final String tempDestination;
-    private String thisTempDestination;
     private final List<String> ignoredWorlds;
+    private final boolean backupSeeds;
 
     /**
      * This should be the place where all the settings and paths for the backup
@@ -57,6 +59,7 @@ public class BackupWorlds {
         shouldZIP = settings.getBooleanProperty("zipbackup", true);
         splitBackup = settings.getBooleanProperty("splitbackup", false);
         useTemp = settings.getBooleanProperty("usetemp", true);
+        backupSeeds = settings.getBooleanProperty("backupworldseed", true);
 
         // Generate the worldStore.
         if (useTemp) {
@@ -83,8 +86,12 @@ public class BackupWorlds {
 
         // Loops each world that needs to backed up, and do the required copies.
         while (!worldsToBackup.isEmpty()) {
+            
             String currentWorldName = worldsToBackup.removeFirst();
 
+            // Get the current worlds seed.
+            String worldSeed = String.valueOf(pluginServer.getWorld(currentWorldName).getSeed());
+
             // Check for split backup.
             if (splitBackup) {
 
@@ -114,6 +121,19 @@ public class BackupWorlds {
                 // Check this backup folder exists.
                 FileUtils.checkFolderAndCreate(new File(thisWorldBackupFolder));
 
+                // World seed backup.
+                if (backupSeeds) {
+                    try {
+                        BufferedWriter out = new BufferedWriter(new FileWriter(thisWorldBackupFolder.concat(FILE_SEPARATOR).concat("worldSeed.txt")));
+                        out.write("Level seed for '" + currentWorldName + "':");
+                        out.newLine();
+                        out.write(worldSeed);
+                        out.close();
+                    } catch (IOException ex) {
+                        LogUtils.exceptionLog(ex, "Error saving level seed.");
+                    }
+                }
+
                 // Copy the current world into it's backup folder.
                 FileUtils.copyDirectory(worldContainer.concat(FILE_SEPARATOR).concat(currentWorldName), thisWorldBackupFolder.concat(FILE_SEPARATOR).concat(currentWorldName));
 
@@ -135,6 +155,19 @@ public class BackupWorlds {
                 // Create this folder.
                 FileUtils.checkFolderAndCreate(new File(copyDestination));
 
+                // Bacup level seeds.
+                if (backupSeeds) {
+                    try {
+                        BufferedWriter out = new BufferedWriter(new FileWriter(copyDestination.concat(FILE_SEPARATOR).concat("worldSeed.txt")));
+                        out.write("Level seed for '" + currentWorldName + "':");
+                        out.newLine();
+                        out.write(worldSeed);
+                        out.close();
+                    } catch (IOException ex) {
+                        LogUtils.exceptionLog(ex, "Error saving level seed.");
+                    }
+                }
+
                 // Copy the current world into it's backup folder.
                 FileUtils.copyDirectory(worldContainer.concat(FILE_SEPARATOR).concat(currentWorldName), copyDestination);
 
@@ -173,4 +206,4 @@ public class BackupWorlds {
         }
         return toBackup;
     }
-}
+}

+ 25 - 24
src/main/java/com/bukkitbackup/full/utils/FileUtils.java

@@ -55,12 +55,6 @@ import java.util.zip.ZipOutputStream;
  */
 public class FileUtils {
 
-    /**
-     * Instances should NOT be constructed in standard programming.
-     */
-    public FileUtils() {
-        super();
-    }
     public static int BUFFER_SIZE = 10240;
     /**
      * The number of bytes in a kilobyte.
@@ -87,7 +81,7 @@ public class FileUtils {
     private static final char WINDOWS_SEPARATOR = '\\';
 
     /**
-     * Copies a whole directory to a new location preserving the file dates. <p>
+     * Copies a whole directory to a new location preserving the file dates.
      * This method copies the specified directory and all its child directories
      * and files to the specified destination. The destination is the new
      * location and name of the directory. <p> The destination directory is
@@ -110,7 +104,6 @@ public class FileUtils {
      * @since Commons IO 1.1
      */
     public static void copyDirectory(String srcDir, String destDir) throws IOException {
-
         copyDirectory(new File(srcDir), new File(destDir), true);
     }
 
@@ -140,8 +133,7 @@ public class FileUtils {
      * @throws IOException if an IO error occurs during copying
      * @since Commons IO 1.1
      */
-    private static void copyDirectory(File srcDir, File destDir,
-            boolean preserveFileDate) throws IOException {
+    private static void copyDirectory(File srcDir, File destDir, boolean preserveFileDate) throws IOException {
         copyDirectory(srcDir, destDir, null, preserveFileDate);
     }
 
@@ -240,8 +232,7 @@ public class FileUtils {
      * @throws IOException if an error occurs
      * @since Commons IO 1.1
      */
-    private static void doCopyDirectory(File srcDir, File destDir, FileFilter filter,
-            boolean preserveFileDate, List<String> exclusionList) throws IOException {
+    private static void doCopyDirectory(File srcDir, File destDir, FileFilter filter, boolean preserveFileDate, List<String> exclusionList) throws IOException {
         // recurse
         File[] files = filter == null ? srcDir.listFiles() : srcDir.listFiles(filter);
         if (files == null) // null if security restricted
@@ -362,14 +353,15 @@ public class FileUtils {
      * @throws IOException in case deletion is unsuccessful
      */
     public static void deleteDirectory(File directory) throws IOException {
+
+        // Check provided file exists.
         if (!directory.exists()) {
             return;
         }
+        
+        cleanDirectory(directory);
 
-        if (!isSymlink(directory)) {
-            cleanDirectory(directory);
-        }
-
+        // Attempt deletion.
         if (!directory.delete()) {
             String message = "Unable to delete directory " + directory + ".";
             throw new IOException(message);
@@ -377,28 +369,32 @@ public class FileUtils {
     }
 
     /**
-     * Cleans a directory without deleting it.
+     * Recursively empties a directory without deleting it.
      *
-     * @param directory directory to clean
+     * @param directory directory to recursively empty
      * @throws IOException in case cleaning is unsuccessful
      */
     private static void cleanDirectory(File directory) throws IOException {
+
+        // Check it exists.
         if (!directory.exists()) {
             String message = directory + " does not exist";
             throw new IllegalArgumentException(message);
         }
 
+        // Check it is a directory.
         if (!directory.isDirectory()) {
             String message = directory + " is not a directory";
             throw new IllegalArgumentException(message);
         }
 
+        // Retrieve contents.
         File[] files = directory.listFiles();
-        if (files == null) // null if security restricted
-        {
-            throw new IOException("Failed to list contents of " + directory);
+        if (files == null) {
+            throw new SecurityException("Failed to list contents of " + directory);
         }
 
+        // Attempt file deletion.
         IOException exception = null;
         for (File file : files) {
             try {
@@ -408,7 +404,8 @@ public class FileUtils {
             }
         }
 
-        if (null != exception) {
+        // Do we need to throw an exception?
+        if (exception != null) {
             throw exception;
         }
     }
@@ -494,7 +491,6 @@ public class FileUtils {
         if (!zipName.endsWith(".zip")) {
             zipName += ".zip";
         }
-		
         // create a ZipOutputStream to zip the data to
         ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipName));
         zipDir(directory, zos, "");
@@ -643,6 +639,11 @@ public class FileUtils {
         });
         return filesList;
     }
+    
+    
+    public static File[] listItemsInDir(File directory) {
+        return directory.listFiles();
+    }
 
     public static int getTotalFolderSize(File folder) {
         int bytes = 0;
@@ -656,4 +657,4 @@ public class FileUtils {
         }
         return bytes;
     }
-}
+}

+ 37 - 22
src/main/java/com/bukkitbackup/full/utils/LogUtils.java

@@ -7,9 +7,9 @@ import java.util.logging.Logger;
 import org.bukkit.plugin.Plugin;
 
 /**
- * Class used for all logging.
- * 
- * @author Domenic Horner
+ * Backup - The simple server backup solution.
+ *
+ * @author Domenic Horner (gamerx)
  */
 public class LogUtils {
 
@@ -17,12 +17,13 @@ public class LogUtils {
     private static Logger logger;
     private static boolean logToConsole = true;
     private static String lastMesage;
-    
+    public static boolean debugMode = false;
+
     /**
      * Setup the logger class with required settings.
-     * 
-     * @param plugin he plugin's object. 
-    */
+     *
+     * @param plugin he plugin's object.
+     */
     public static void initLogUtils(Plugin plugin) {
         LogUtils.plugin = plugin;
         LogUtils.logger = Logger.getLogger(plugin.getServer().getLogger().getName() + "." + plugin.getServer().getName());
@@ -30,54 +31,57 @@ public class LogUtils {
     }
 
     /**
-     * Finish initalizing the LogUtils class.
-     * 
+     * Finish setting up the LogUtils class.
+     *
      * @param logToConsole Whether or not to output to the console.
      */
-    public static void finishInitLogUtils(boolean logToConsole) {
-        
+    public static void finishInitLogUtils(boolean logToConsole, boolean debugMode) {
+
         // If we should send output to the console.
         LogUtils.logToConsole = logToConsole;
+
+        // Is debugging enabled?
+        LogUtils.debugMode = debugMode;
     }
 
     /**
      * This will send a message to the console using the logger.
-     * 
+     *
      * @param message The message to be send.
      */
     public static void sendLog(String message) {
-        
+
         // Check if this is a split-message.
         if (message.contains(";;")) {
-            
+
             // Split the message list.
             List<String> messageList = Arrays.asList(message.split(";;"));
-            
+
             // Loop each message in the array.
             for (int i = 0; i < messageList.size(); i++) {
-                
+
                 String thisMessage = messageList.get(i);
-                
+
                 // Check it should be sent to the console.
                 if (logToConsole && !lastMesage.equals(message)) {
                     logger.log(Level.INFO, "[".concat(plugin.getDescription().getName()).concat("] ").concat(thisMessage));
                 }
             }
         } else {
-            
+
             // Check it should be sent to the console.
             if (logToConsole && !lastMesage.equals(message)) {
                 logger.log(Level.INFO, "[".concat(plugin.getDescription().getName()).concat("] ").concat(message));
             }
         }
-        
+
         // Set the last message so they don't duplicate.
         lastMesage = message;
     }
-    
+
     /**
      * This posts a tidy stack trace to the console, along with a message.
-     * 
+     *
      * @param ste The Stack Trace object.
      * @param message Message to accompany this exception.
      */
@@ -86,9 +90,20 @@ public class LogUtils {
         exceptionLog(ste);
     }
 
+    /**
+     * This is where debug messages should be sent.
+     *
+     * @param message Debug message.
+     */
+    public static void sendDebug(String message) {
+        if (debugMode) {
+            sendLog(message);
+        }
+    }
+
     /**
      * This posts a tidy stack trace to the console.
-     * 
+     *
      * @param ste The Stack Trace object.
      */
     public static void exceptionLog(Throwable ste) {

+ 61 - 5
src/main/java/com/bukkitbackup/full/utils/MetricUtils.java

@@ -1,3 +1,6 @@
+/*
+ * Copyright 2011 Tyler Blair. All rights reserved.
+ */
 package com.bukkitbackup.full.utils;
 
 import java.io.*;
@@ -6,33 +9,65 @@ import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLEncoder;
 import java.util.UUID;
+import java.util.logging.Level;
 import org.bukkit.Bukkit;
 import org.bukkit.configuration.InvalidConfigurationException;
 import org.bukkit.configuration.file.YamlConfiguration;
 import org.bukkit.plugin.Plugin;
 import org.bukkit.plugin.PluginDescriptionFile;
 
-public class MetricUtils {
+public final class MetricUtils {
 
+    /**
+     * The current revision number
+     */
     private final static int REVISION = 5;
+    /**
+     * The base url of the metrics domain
+     */
     private static final String BASE_URL = "http://mcstats.org";
+    /**
+     * The url used to report a server's status
+     */
     private static final String REPORT_URL = "/report/%s";
+    /**
+     * Interval of time to ping (in minutes)
+     */
     private final static int PING_INTERVAL = 10;
+    /**
+     * The plugin this metrics submits for
+     */
     private final Plugin plugin;
+    /**
+     * The plugin configuration file
+     */
     private final YamlConfiguration configuration;
+    /**
+     * The plugin configuration file
+     */
     private final File configurationFile;
+    /**
+     * Unique server id
+     */
     public final String guid;
+    /**
+     * Lock for synchronization
+     */
     private final Object optOutLock = new Object();
+    /**
+     * Id of the scheduled task
+     */
     private volatile int taskId = -1;
 
-    public MetricUtils(Plugin plugin, File mainDataFolder) throws IOException {
+    public MetricUtils(Plugin plugin) throws IOException {
         if (plugin == null) {
             throw new IllegalArgumentException("Plugin cannot be null");
         }
+
         this.plugin = plugin;
 
         // load the config
-        configurationFile = mainDataFolder;
+        configurationFile = getConfigFile();
         configuration = YamlConfiguration.loadConfiguration(configurationFile);
 
         // add some defaults
@@ -94,6 +129,7 @@ public class MetricUtils {
                         // Each post thereafter will be a ping
                         firstPost = false;
                     } catch (IOException e) {
+                        Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
                     }
                 }
             }, 0, PING_INTERVAL * 1200);
@@ -111,10 +147,12 @@ public class MetricUtils {
         synchronized (optOutLock) {
             try {
                 // Reload the metrics file
-                configuration.load(configurationFile);
+                configuration.load(getConfigFile());
             } catch (IOException ex) {
+                Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
                 return true;
             } catch (InvalidConfigurationException ex) {
+                Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
                 return true;
             }
             return configuration.getBoolean("opt-out", false);
@@ -166,6 +204,24 @@ public class MetricUtils {
         }
     }
 
+    /**
+     * Gets the File object of the config file that should be used to store data
+     * such as the GUID and opt-out status
+     *
+     * @return the File object for the config file
+     */
+    public File getConfigFile() {
+        // I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use
+        // is to abuse the plugin object we already have
+        // plugin.getDataFolder() => base/plugins/PluginA/
+        // pluginsFolder => base/plugins/
+        // The base is not necessarily relative to the startup directory.
+        File pluginsFolder = plugin.getDataFolder().getParentFile();
+
+        // return => base/plugins/PluginMetrics/config.yml
+        return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml");
+    }
+
     /**
      * Generic method that posts a plugin to the metrics website
      */
@@ -264,4 +320,4 @@ public class MetricUtils {
     private static String encode(String text) throws UnsupportedEncodingException {
         return URLEncoder.encode(text, "UTF-8");
     }
-}
+}

+ 25 - 91
src/main/resources/config.yml

@@ -5,52 +5,28 @@
 
 #======== Backup Settings ==========#
 
-## How often show the backup run? (Default: "15M" / 15 Minutes)
-# (Note: -1 or 0 will disable automatic backups.)
-# Format: [Time][M-Minutes, H-Hours, D-Days, W-Weeks]
+## When and how often should the backup be run? (Default: "15M" / Every 15 Minutes)
+# (Note: -1 or 0 will disable automatic backups)
+# Format: (for interval-based) [Time][M-Minutes, H-Hours, D-Days, W-Weeks]
+# Format: (for time-based)  TA[02:00,06:00,10:00,14:00,18:00,22:00]
+# The example backs up at: 2AM, 6AM, 10AM, 2PM, 6PM, 10PM.
 backupinterval: 15M
 
-## Enable scheduled save-all? (Default: "0" / Off)
-# (Note: -1 or 0 disables this feature.)
-# Format: [Time][M-Minutes, H-Hours, D-Days, W-Weeks]
-saveallinterval: 0
-
 ## How many backups are retained? (Default: 25)
 # If this limit is hit, the oldest backup(s) will be removed.
-# (Note: -1 or 0 disables this feature.)
+# (Note: -1 or 0 disables this feature)
 # This can also be a max size, Format: [Size][K-KiloBytes, M-MegaBytes, G-GigaByes]
 maxbackups: 25
 
-## Should backups be performed on an empty server? (Default: false)
-# When the last player leaves the server, a final backup will be made. The automatic backup cycle will resume when a player re-joins.
-backupemptyserver: false
-
-## Should the backup stop the schedule after the first backup? (Default: false)
-# If enabled, one backup will be performed at the time specified under backupinterval.
-norepeat: false
-
-## Option to always perform a /save-all on backup schedule. (Default: false)
-# If false, /save-all's are only performed when a backup is required.
-alwayssaveall: false
-
-## If permissions system is un-available, should everyone be able to access all commands, or just ops? (Default: true)
-# If set to false, all players will be able to perform all commands, unless you use a permissions system.
-onlyops: true
-
-## Should the bypass node be ignored? (Default: false)
-# If this is true, even if all players have the "backup.bypass" permissions node, the backup will still continue.
-ignorebypass: false
-
-## Enables the auto-save function after the backup. (Defualt: true)
-# Note: If you set this to false, this plugin will backup your worlds but not save the data from the memory to your hard disc. If the server crashes between
-# backups, all work is lost. Disable if you use another plugin to save the world to disk (EG: autosave).
-enableautosave: true
+## Should backups only be performed with users online? (Default: true)
+# When the last player leaves the server, a final backup will be made.
+# The automatic backup cycle will resume when a player re-joins.
+onlyifonline: true
 
 ## Should we backup the entire folder? (Default: false)
 # Use with caution, as this will be a long, large backup, it automatically ignores the backup folder, so it can still be in the server folder.
 # Using this will ignore "backupworlds", "backupplugins", "skipworlds", "skipplugins", and "splitbackup"
-backupeverything: false
-
+fullbackup: false
 
 #======== File & Location Settings ==========#
 
@@ -58,13 +34,11 @@ backupeverything: false
 # Note: Path can be relative, or absolute. ('D:\Backups', '/var/backups', 'altbackups', and '~/backups' are all valid)
 backuppath: backups
 
-## Do we use the temp folder when doing backup? (Default: true)
-usetemp: true
-
-## Name for the temp folder. (Default: none)
-# This stores tempoary files while backup is in progress.
-# Note: Path can be relative, or absolute. ('D:\temp', '/tmp', 'temp', and '~/backups/temp' are all valid)
-# If this is not set, it defaults to a temp folder under the backups folder.
+## Tempoary folder settings. (Default: false/none)
+# These settings are for storing tempoary files while backup is in progress.
+# Note: Path can be relative or absolute. ('D:\temp', '/tmp', 'temp', and '~/backups/temp' are all valid)
+# If the folder name is not set, it defaults to a temp folder under the backups folder.
+usetempfolder: false
 tempfoldername:
 
 ## Whether to ZIP Backups or not. (Default: true)
@@ -75,48 +49,12 @@ zipbackup: true
 ## Should all the worlds be split into their own foders? (Default: false)
 splitbackup: false
 
+## @TODO Remove setting.
 ## Customize the date format for each backup. (Default: '%1$tY-%1$tm-%1$td-%1$tH-%1$tM-%1$tS' [YYYY-MM-DD-HH-MM-SS])
 # This has to be a Java String.format string, see
 # http://download.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html#syntax
 dateformat: '%1$tY-%1$tm-%1$td-%1$tH-%1$tM-%1$tS'
 
-#======== FTP Server Settings ==========#
-
-###########################################################
-##             !!!  Warning on FTP  !!!                  ##
-## This implementation relies on Sun's implemenentation  ##
-##  of the FTP protocol, and depending on the version    ##
-##  of Java you have installed, it may or may not work.  ##
-##     You need sun.net.ftp.FtpClient in your JRE.       ##
-##    Please tell me if this works/doesn't for you.      ##
-###########################################################
-
-
-## Should we enable FTP uploads? (Default: false)
-# If enabled, following options must be set.
-# zipbackup must be true for this to take effect.
-ftpuploadenable: false
-
-## The FTP server address to connect to. (Default: none)
-# Can be an IP address or a hostname.
-ftpserveraddress:
-
-## What port should we connect to on the server? (Default: 22)
-# The FTP default port is 21, if you're unsure, don't change this.
-ftpserverport: 21
-
-## The username to login to the FTP server with. (Default: none)
-ftpusername:
-
-## The password to login to the FTP server with. (Default: none)
-ftppassword:
-
-## The directory on the FTP server you would like backups stored in.  (Default: backups)
-# Please leave blank for the root directory.
-# This folder MUST exist on the FTP server, and will NOT be created!
-ftpdirectory: backups
-
-
 #======== Content Settings ==========#
 
 ## What to backup. (Default: true, true)
@@ -136,23 +74,19 @@ pluginlistmode: true
 # Seperate by a semicolon. eg. Plugin1;Plugin2;Plugin3. This takes effect inside plugins/
 pluginlist:
 
-#======== Notification & Logging Settings ==========#
-
-## Should we display messages in server/console log? (Default: true)
-# If false messages will only be logged to file.
-displaylog: true
+#======== Advanced Settings ==========#
 
-## Should we send messages in-game on backup complete. (Default: true)
-# False will only notify players with the "backup.notify" permission.
-notifyallplayers: true
+## Should we enable debugging in the console? (Defualt: false)
+# This will also create a debug.log file in the data directory.
+debugmode: false
 
 ## Enable online version checking? (Default: true)
-# Requires internet connectivity.
-enableversioncheck: true
+# This enabled checking for new plugin versions, it will download them automatically if it finds one.
+# Obviously, this requires internet connectivity.
+checkversion: true
 
 ###############################################
 ##   Internal Settings (Read: DO NOT EDIT)   ##
 ###############################################
 
-requiredstrings: str-200
-version: 2.0
+version: 2.5

+ 4 - 4
src/main/resources/plugin.yml

@@ -1,5 +1,5 @@
 name: Backup
-version: 2.0
+version: 2.5
 description: A full and simple backup plugin.
 authors: [Meldanor, gamerx, lycano]
 website: http://www.bukkitbackup.com/
@@ -7,10 +7,10 @@ dev-url: http://dev.bukkit.org/server-mods/backup/
 main: com.bukkitbackup.full.BackupFull
 commands:
   backup:
-    description: Starts a backup of the server.
+    description: Manually starts a backup of the server.
     usage: "Usage: /backup [args]"
   bu:
-    description: Starts a backup of the server.
+    description: Manually starts a backup of the server.
     usage: "Usage: /bu [args]"
 permissions:
   backup.*:
@@ -40,4 +40,4 @@ permissions:
   backup.bypass:
     description: Players with this permission are not counted as online players.
     default: false
-    
+    

+ 4 - 17
src/main/resources/strings.yml

@@ -16,15 +16,14 @@ gettingversions      : '[Backup] Please wait, Retrieving version information...'
 
 #========= Startup Strings ==========#
 
-configupdate         : Your config file is outdated, please regenerate it.
-stringsupdate        : Your strings file is out of date, please regenerate it.
+configupdate         : Your config file is outdated.
+stringsupdate        : Your strings file is outdated.
 failedtogetpropsver  : Failed to obtain version information from config file.
 zipdisabled          : You have disabled backup compression.
 defaultperms         : No permissions plugin detected, defaulting to OP.
 hookedperms          : Found and hooked a permissions plugin.
 newconfigfile        : No config file exists, creating default.
 disbaledauto         : You have disabled scheduled backups!
-norepeatenabled      : Backup will be performed once in %%ARG%% minute(s).
 savealltimeron       : Save-All will be performed every %%ARG%% minute(s).
 
 #========= Notification Strings ==========#
@@ -33,7 +32,7 @@ disabledworlds       : 'Backup is disabled for the following world(s):'
 disabledplugins      : 'Backup is disabled for the following plugin(s):'
 enabledplugins       : 'Backup is enabled for the following plugin(s):'
 allpluginsdisabled   : Plugin backup is on, but no plugins are selected.
-abortedbackup        : Aborted backup as no players online. Next attempt in %%ARG%% minutes.
+abortedbackup        : Aborted backup as no players online. Will re-attempt at next schedule.
 skipworlds           : Skipworlds is enabled.
 skipplugins          : Skipping plugin backup, for all plugins.
 removeoldage         : 'Removing the following backup(s) due to age:'
@@ -67,21 +66,9 @@ checksizelimit       : Error getting maximum allowed backups.
 errorversioncheck    : Failed to retrieve latest version information.
 failedlistdir        : Failed to list backup directory.
 
-#========= FTP Strings ==========#
-
-ftpfailsettings      : 'FTP: Fail - Connection settings incorrect.'
-ftpfailnofile        : 'FTP: Fail - No file to upload.'
-ftpconnecting        : 'FTP: Connecting: %%ARG%%'
-ftpestablished       : 'FTP: Connection Estblished: %%ARG%%'
-ftphellomsg          : 'FTP: Hello Message: %%ARG%%'
-ftpchangedinto       : 'FTP: Changed into: %%ARG%%'
-ftpuploading         : 'FTP: Attempting to upload file...'
-ftpuploadcomplete    : 'FTP: Upload Complete.'
-
 ###############################################
 ##   Internal Settings (Read: DO NOT EDIT)   ##
 ###############################################
 
 stringnotfound       : 'String not found - '
-packagedwith         : 2.0
-version              : str-200
+version              : 2.5