diff --git a/src/main/java/us/tastybento/bskyblock/BSkyBlock.java b/src/main/java/us/tastybento/bskyblock/BSkyBlock.java index b0ea1348a..c300070ae 100755 --- a/src/main/java/us/tastybento/bskyblock/BSkyBlock.java +++ b/src/main/java/us/tastybento/bskyblock/BSkyBlock.java @@ -7,8 +7,6 @@ import us.tastybento.bskyblock.api.placeholders.PlaceholderHandler; import us.tastybento.bskyblock.commands.AdminCommand; import us.tastybento.bskyblock.commands.IslandCommand; import us.tastybento.bskyblock.database.BSBDatabase; -import us.tastybento.bskyblock.database.managers.PlayersManager; -import us.tastybento.bskyblock.database.managers.island.IslandsManager; import us.tastybento.bskyblock.generators.IslandWorld; import us.tastybento.bskyblock.listeners.JoinLeaveListener; import us.tastybento.bskyblock.listeners.NetherPortals; @@ -16,7 +14,9 @@ import us.tastybento.bskyblock.listeners.PanelListenerManager; import us.tastybento.bskyblock.managers.AddonsManager; import us.tastybento.bskyblock.managers.CommandsManager; import us.tastybento.bskyblock.managers.FlagsManager; +import us.tastybento.bskyblock.managers.IslandsManager; import us.tastybento.bskyblock.managers.LocalesManager; +import us.tastybento.bskyblock.managers.PlayersManager; import us.tastybento.bskyblock.managers.RanksManager; /** @@ -26,7 +26,7 @@ import us.tastybento.bskyblock.managers.RanksManager; */ public class BSkyBlock extends JavaPlugin { - private static BSkyBlock plugin; + private static BSkyBlock instance; // Databases private PlayersManager playersManager; @@ -74,7 +74,7 @@ public class BSkyBlock extends JavaPlugin { ranksManager = new RanksManager(this); // Load metrics - metrics = new Metrics(plugin); + metrics = new Metrics(instance); registerCustomCharts(); // Set up commands @@ -87,29 +87,29 @@ public class BSkyBlock extends JavaPlugin { // at this point. Therefore, the 1 tick scheduler is required. getServer().getScheduler().runTask(this, () -> { // Create the world if it does not exist - islandWorldManager = new IslandWorld(plugin); + islandWorldManager = new IslandWorld(instance); - getServer().getScheduler().runTask(plugin, () -> { + getServer().getScheduler().runTask(instance, () -> { // Load Flags - flagsManager = new FlagsManager(plugin); + flagsManager = new FlagsManager(instance); // Load islands from database islandsManager.load(); - localesManager = new LocalesManager(plugin); - PlaceholderHandler.register(plugin); + localesManager = new LocalesManager(instance); + PlaceholderHandler.register(instance); // Register Listeners registerListeners(); // Load addons - addonsManager = new AddonsManager(plugin); + addonsManager = new AddonsManager(instance); addonsManager.enableAddons(); // Save islands & players data asynchronously every X minutes getSettings().setDatabaseBackupPeriod(10 * 60 * 20); - plugin.getServer().getScheduler().runTaskTimer(plugin, () -> { + instance.getServer().getScheduler().runTaskTimer(instance, () -> { playersManager.save(true); islandsManager.save(true); }, getSettings().getDatabaseBackupPeriod(), getSettings().getDatabaseBackupPeriod()); @@ -193,11 +193,11 @@ public class BSkyBlock extends JavaPlugin { } private static void setInstance(BSkyBlock plugin) { - BSkyBlock.plugin = plugin; + BSkyBlock.instance = plugin; } public static BSkyBlock getInstance() { - return plugin; + return instance; } /** diff --git a/src/main/java/us/tastybento/bskyblock/api/addons/Addon.java b/src/main/java/us/tastybento/bskyblock/api/addons/Addon.java index a3c0144bc..1c1d594bc 100644 --- a/src/main/java/us/tastybento/bskyblock/api/addons/Addon.java +++ b/src/main/java/us/tastybento/bskyblock/api/addons/Addon.java @@ -15,8 +15,8 @@ import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.event.Listener; import us.tastybento.bskyblock.BSkyBlock; -import us.tastybento.bskyblock.database.managers.PlayersManager; -import us.tastybento.bskyblock.database.managers.island.IslandsManager; +import us.tastybento.bskyblock.managers.IslandsManager; +import us.tastybento.bskyblock.managers.PlayersManager; /** * Add-on class for BSkyBlock. Extend this to create an add-on. The operation diff --git a/src/main/java/us/tastybento/bskyblock/api/commands/CompositeCommand.java b/src/main/java/us/tastybento/bskyblock/api/commands/CompositeCommand.java index 37dbc66cf..de079d311 100644 --- a/src/main/java/us/tastybento/bskyblock/api/commands/CompositeCommand.java +++ b/src/main/java/us/tastybento/bskyblock/api/commands/CompositeCommand.java @@ -19,8 +19,8 @@ import org.bukkit.entity.Player; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.Settings; import us.tastybento.bskyblock.api.events.command.CommandEvent; -import us.tastybento.bskyblock.database.managers.PlayersManager; -import us.tastybento.bskyblock.database.managers.island.IslandsManager; +import us.tastybento.bskyblock.managers.IslandsManager; +import us.tastybento.bskyblock.managers.PlayersManager; import us.tastybento.bskyblock.util.Util; /** diff --git a/src/main/java/us/tastybento/bskyblock/api/configuration/BSBConfig.java b/src/main/java/us/tastybento/bskyblock/api/configuration/BSBConfig.java index 6363b1b1f..90de7aa8d 100644 --- a/src/main/java/us/tastybento/bskyblock/api/configuration/BSBConfig.java +++ b/src/main/java/us/tastybento/bskyblock/api/configuration/BSBConfig.java @@ -9,8 +9,8 @@ import java.util.logging.Logger; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.api.addons.Addon; +import us.tastybento.bskyblock.database.AbstractDatabaseHandler; import us.tastybento.bskyblock.database.flatfile.FlatFileDatabase; -import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler; /** * Handy config class to store and load Java POJOs as YAML configs @@ -90,4 +90,4 @@ public class BSBConfig { } -} +} \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/api/configuration/ISettings.java b/src/main/java/us/tastybento/bskyblock/api/configuration/ISettings.java index 6f32e081f..16e1d61a0 100644 --- a/src/main/java/us/tastybento/bskyblock/api/configuration/ISettings.java +++ b/src/main/java/us/tastybento/bskyblock/api/configuration/ISettings.java @@ -4,9 +4,10 @@ import java.beans.IntrospectionException; import java.lang.reflect.InvocationTargetException; import java.sql.SQLException; +import us.tastybento.bskyblock.database.AbstractDatabaseHandler; import us.tastybento.bskyblock.database.BSBDatabase; +import us.tastybento.bskyblock.database.flatfile.ConfigHandler; import us.tastybento.bskyblock.database.flatfile.FlatFileDatabase; -import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler; /** * Simple interface for tagging all classes containing ConfigEntries. @@ -21,7 +22,7 @@ public interface ISettings { @SuppressWarnings("unchecked") default void saveSettings() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IntrospectionException, SQLException { // Get the handler - AbstractDatabaseHandler settingsHandler = (AbstractDatabaseHandler) new FlatFileDatabase().getHandler(getInstance().getClass()); + ConfigHandler settingsHandler = (ConfigHandler) new FlatFileDatabase().getConfig(getInstance().getClass()); // Load every field in the config class settingsHandler.saveSettings(getInstance()); } @@ -44,7 +45,7 @@ public interface ISettings { dbConfig = dbhandler.loadObject(getUniqueId()); } // Get the handler - AbstractDatabaseHandler configHandler = (AbstractDatabaseHandler) new FlatFileDatabase().getHandler(getInstance().getClass()); + ConfigHandler configHandler = (ConfigHandler ) new FlatFileDatabase().getConfig(getInstance().getClass()); // Load every field in the config class return configHandler.loadSettings(getUniqueId(), dbConfig); } diff --git a/src/main/java/us/tastybento/bskyblock/api/flags/Flag.java b/src/main/java/us/tastybento/bskyblock/api/flags/Flag.java index e480693a9..3cd0d03a8 100644 --- a/src/main/java/us/tastybento/bskyblock/api/flags/Flag.java +++ b/src/main/java/us/tastybento/bskyblock/api/flags/Flag.java @@ -9,7 +9,6 @@ import org.bukkit.inventory.ItemStack; import us.tastybento.bskyblock.api.commands.User; import us.tastybento.bskyblock.api.panels.PanelItem; import us.tastybento.bskyblock.api.panels.builders.PanelItemBuilder; -import us.tastybento.bskyblock.managers.RanksManager; public class Flag implements Comparable { diff --git a/src/main/java/us/tastybento/bskyblock/api/panels/builders/PanelItemBuilder.java b/src/main/java/us/tastybento/bskyblock/api/panels/builders/PanelItemBuilder.java index 8ee5e505c..a088eeac4 100644 --- a/src/main/java/us/tastybento/bskyblock/api/panels/builders/PanelItemBuilder.java +++ b/src/main/java/us/tastybento/bskyblock/api/panels/builders/PanelItemBuilder.java @@ -1,6 +1,9 @@ package us.tastybento.bskyblock.api.panels.builders; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; import org.bukkit.Bukkit; import org.bukkit.Material; diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/IslandCreateCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/IslandCreateCommand.java index facda7acd..0851be20e 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/IslandCreateCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/IslandCreateCommand.java @@ -11,7 +11,7 @@ import us.tastybento.bskyblock.api.commands.CompositeCommand; import us.tastybento.bskyblock.api.commands.User; import us.tastybento.bskyblock.api.events.island.IslandEvent.Reason; import us.tastybento.bskyblock.commands.IslandCommand; -import us.tastybento.bskyblock.database.managers.island.NewIsland; +import us.tastybento.bskyblock.managers.island.NewIsland; /** * /island create - Create an island. diff --git a/src/main/java/us/tastybento/bskyblock/commands/island/IslandResetCommand.java b/src/main/java/us/tastybento/bskyblock/commands/island/IslandResetCommand.java index 194eb8790..4bc68cf44 100644 --- a/src/main/java/us/tastybento/bskyblock/commands/island/IslandResetCommand.java +++ b/src/main/java/us/tastybento/bskyblock/commands/island/IslandResetCommand.java @@ -10,8 +10,8 @@ import us.tastybento.bskyblock.Constants; import us.tastybento.bskyblock.api.commands.CompositeCommand; import us.tastybento.bskyblock.api.commands.User; import us.tastybento.bskyblock.api.events.island.IslandEvent.Reason; -import us.tastybento.bskyblock.database.managers.island.NewIsland; import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.managers.island.NewIsland; public class IslandResetCommand extends CompositeCommand { diff --git a/src/main/java/us/tastybento/bskyblock/database/managers/AbstractDatabaseHandler.java b/src/main/java/us/tastybento/bskyblock/database/AbstractDatabaseHandler.java similarity index 78% rename from src/main/java/us/tastybento/bskyblock/database/managers/AbstractDatabaseHandler.java rename to src/main/java/us/tastybento/bskyblock/database/AbstractDatabaseHandler.java index b49b9f507..8388defc8 100644 --- a/src/main/java/us/tastybento/bskyblock/database/managers/AbstractDatabaseHandler.java +++ b/src/main/java/us/tastybento/bskyblock/database/AbstractDatabaseHandler.java @@ -1,4 +1,4 @@ -package us.tastybento.bskyblock.database.managers; +package us.tastybento.bskyblock.database; import java.beans.IntrospectionException; import java.lang.reflect.InvocationTargetException; @@ -7,8 +7,6 @@ import java.util.List; import org.bukkit.plugin.Plugin; -import us.tastybento.bskyblock.database.DatabaseConnecter; - /** * An abstract class that handles insert/select-operations into/from a database * @@ -83,18 +81,4 @@ public abstract class AbstractDatabaseHandler { */ public abstract boolean objectExists(String key); - /** - * Saves a file as settings - * @param instance - */ - public abstract void saveSettings(T instance) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException; - - /** - * Loads a file as settings - * @param uniqueId - unique ID - * @param dbConfig - the database mirror of this object. It will be checked against what is loaded to see if any significant changes have been made - * @return Settings object - */ - public abstract T loadSettings(String uniqueId, T dbConfig) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IntrospectionException; - } diff --git a/src/main/java/us/tastybento/bskyblock/database/BSBDatabase.java b/src/main/java/us/tastybento/bskyblock/database/BSBDatabase.java index 7f400f068..a70416367 100755 --- a/src/main/java/us/tastybento/bskyblock/database/BSBDatabase.java +++ b/src/main/java/us/tastybento/bskyblock/database/BSBDatabase.java @@ -2,9 +2,7 @@ package us.tastybento.bskyblock.database; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.database.flatfile.FlatFileDatabase; -import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler; import us.tastybento.bskyblock.database.mysql.MySQLDatabase; -import us.tastybento.bskyblock.database.mysqljson.MySQLDatabaseJ; public abstract class BSBDatabase { @@ -24,9 +22,7 @@ public abstract class BSBDatabase { public enum DatabaseType{ FLATFILE(new FlatFileDatabase()), - MYSQL(new MySQLDatabase()), - //JSON(); - MYSQLJ(new MySQLDatabaseJ()); + MYSQL(new MySQLDatabase()); BSBDatabase database; diff --git a/src/main/java/us/tastybento/bskyblock/database/flatfile/ConfigHandler.java b/src/main/java/us/tastybento/bskyblock/database/flatfile/ConfigHandler.java new file mode 100644 index 000000000..45dfd67a6 --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/database/flatfile/ConfigHandler.java @@ -0,0 +1,39 @@ +package us.tastybento.bskyblock.database.flatfile; + +import java.beans.IntrospectionException; +import java.lang.reflect.InvocationTargetException; + +import org.bukkit.plugin.Plugin; + +import us.tastybento.bskyblock.database.DatabaseConnecter; + +/** + * Class handles config settings saving and loading + * + * @author tastybento + * + * @param Handles config files for Class + */ + +public class ConfigHandler extends FlatFileDatabaseHandler { + + public ConfigHandler(Plugin plugin, Class type, DatabaseConnecter databaseConnecter) { + super(plugin, type, databaseConnecter); + } + + public void saveSettings(T instance) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException { + configFlag = true; + saveObject(instance); + } + + public T loadSettings(String uniqueId, T dbConfig) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IntrospectionException { + if (dbConfig == null) { + return loadObject(uniqueId); + } + + // TODO: compare the loaded with the database copy + + return loadObject(uniqueId); + } + +} diff --git a/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabase.java b/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabase.java index fb656963b..d4b2f7aed 100755 --- a/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabase.java +++ b/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabase.java @@ -1,8 +1,8 @@ package us.tastybento.bskyblock.database.flatfile; import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.database.AbstractDatabaseHandler; import us.tastybento.bskyblock.database.BSBDatabase; -import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler; public class FlatFileDatabase extends BSBDatabase{ @@ -10,5 +10,14 @@ public class FlatFileDatabase extends BSBDatabase{ public AbstractDatabaseHandler getHandler(Class type) { return new FlatFileDatabaseHandler<>(BSkyBlock.getInstance(), type, new FlatFileDatabaseConnecter(BSkyBlock.getInstance(), null)); } + + /** + * Get the config + * @param type - config object type + * @return - the config handler + */ + public AbstractDatabaseHandler getConfig(Class type) { + return new ConfigHandler<>(BSkyBlock.getInstance(), type, new FlatFileDatabaseConnecter(BSkyBlock.getInstance(), null)); + } } diff --git a/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabaseHandler.java b/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabaseHandler.java index 1b0e81b3c..7b66f86e2 100644 --- a/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabaseHandler.java +++ b/src/main/java/us/tastybento/bskyblock/database/flatfile/FlatFileDatabaseHandler.java @@ -31,8 +31,8 @@ import us.tastybento.bskyblock.Constants.GameType; import us.tastybento.bskyblock.api.configuration.ConfigComment; import us.tastybento.bskyblock.api.configuration.ConfigEntry; import us.tastybento.bskyblock.api.configuration.StoreAt; +import us.tastybento.bskyblock.database.AbstractDatabaseHandler; import us.tastybento.bskyblock.database.DatabaseConnecter; -import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler; import us.tastybento.bskyblock.database.objects.adapters.Adapter; import us.tastybento.bskyblock.database.objects.adapters.AdapterInterface; import us.tastybento.bskyblock.util.Util; @@ -50,7 +50,7 @@ public class FlatFileDatabaseHandler extends AbstractDatabaseHandler { private static final String DATABASE_FOLDER_NAME = "database"; private static final boolean DEBUG = false; - private boolean configFlag; + protected boolean configFlag; public FlatFileDatabaseHandler(Plugin plugin, Class type, DatabaseConnecter databaseConnecter) { super(plugin, type, databaseConnecter); @@ -264,15 +264,6 @@ public class FlatFileDatabaseHandler extends AbstractDatabaseHandler { return instance; } - /* (non-Javadoc) - * @see us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler#saveConfig(java.lang.Object) - */ - @Override - public void saveSettings(T instance) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException { - configFlag = true; - saveObject(instance); - } - /** * Inserts T into the corresponding database-table * @@ -525,18 +516,4 @@ public class FlatFileDatabaseHandler extends AbstractDatabaseHandler { } } - /* (non-Javadoc) - * @see us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler#loadSettings(java.lang.String, java.lang.Object) - */ - @Override - public T loadSettings(String uniqueId, T dbConfig) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IntrospectionException { - if (dbConfig == null) { - return loadObject(uniqueId); - } - - // TODO: compare the loaded with the database copy - - return loadObject(uniqueId); - } - } diff --git a/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabase.java b/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabase.java index 1654456c3..8a602ec4f 100755 --- a/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabase.java +++ b/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabase.java @@ -1,9 +1,9 @@ package us.tastybento.bskyblock.database.mysql; import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.database.AbstractDatabaseHandler; import us.tastybento.bskyblock.database.BSBDatabase; import us.tastybento.bskyblock.database.DatabaseConnectionSettingsImpl; -import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler; public class MySQLDatabase extends BSBDatabase{ diff --git a/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandler.java b/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandler.java index b26a23f9b..f0d8a7963 100644 --- a/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandler.java +++ b/src/main/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandler.java @@ -1,42 +1,30 @@ package us.tastybento.bskyblock.database.mysql; -import java.beans.IntrospectionException; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.math.BigDecimal; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.UUID; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.plugin.Plugin; +import org.bukkit.potion.PotionEffectType; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.api.flags.Flag; +import us.tastybento.bskyblock.database.AbstractDatabaseHandler; import us.tastybento.bskyblock.database.DatabaseConnecter; -import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler; -import us.tastybento.bskyblock.database.objects.adapters.Adapter; -import us.tastybento.bskyblock.database.objects.adapters.AdapterInterface; -import us.tastybento.bskyblock.util.Util; +import us.tastybento.bskyblock.database.mysql.adapters.FlagAdapter; +import us.tastybento.bskyblock.database.mysql.adapters.LocationAdapter; +import us.tastybento.bskyblock.database.mysql.adapters.PotionEffectTypeAdapter; +import us.tastybento.bskyblock.database.mysql.adapters.WorldAdapter; +import us.tastybento.bskyblock.database.objects.DataObject; /** * @@ -52,47 +40,8 @@ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { * Connection to the database */ private Connection connection = null; - /** - * This hashmap maps Java types to MySQL SQL types because they are not the same - */ - private static final HashMap MYSQL_MAPPING = new HashMap<>(); - private static final String STRING_MAP = "VARCHAR(254)"; - - static { - MYSQL_MAPPING.put(boolean.class.getTypeName(), "BOOL"); - MYSQL_MAPPING.put(byte.class.getTypeName(), "TINYINT"); - MYSQL_MAPPING.put(short.class.getTypeName(), "SMALLINT"); - MYSQL_MAPPING.put(int.class.getTypeName(), "INTEGER"); - MYSQL_MAPPING.put(long.class.getTypeName(), "BIGINT"); - MYSQL_MAPPING.put(double.class.getTypeName(), "DOUBLE PRECISION"); - MYSQL_MAPPING.put(Boolean.class.getTypeName(), "BOOL"); - MYSQL_MAPPING.put(Byte.class.getTypeName(), "TINYINT"); - MYSQL_MAPPING.put(Short.class.getTypeName(), "SMALLINT"); - MYSQL_MAPPING.put(Integer.class.getTypeName(), "INTEGER"); - MYSQL_MAPPING.put(Long.class.getTypeName(), "BIGINT"); - MYSQL_MAPPING.put(Double.class.getTypeName(), "DOUBLE PRECISION"); - MYSQL_MAPPING.put(BigDecimal.class.getTypeName(), "DECIMAL(13,0)"); - MYSQL_MAPPING.put(String.class.getTypeName(), STRING_MAP); - MYSQL_MAPPING.put(Date.class.getTypeName(), "DATE"); - MYSQL_MAPPING.put(Time.class.getTypeName(), "TIME"); - MYSQL_MAPPING.put(Timestamp.class.getTypeName(), "TIMESTAMP"); - MYSQL_MAPPING.put(UUID.class.getTypeName(), "VARCHAR(36)"); - - // Bukkit Mappings - MYSQL_MAPPING.put(Location.class.getTypeName(), STRING_MAP); - MYSQL_MAPPING.put(World.class.getTypeName(), STRING_MAP); - - // Collections are stored as additional tables. The boolean indicates whether there - // is any data in it or not (maybe) - MYSQL_MAPPING.put(Set.class.getTypeName(), "BOOL"); - MYSQL_MAPPING.put(Map.class.getTypeName(), "BOOL"); - MYSQL_MAPPING.put(HashMap.class.getTypeName(), "BOOL"); - MYSQL_MAPPING.put(ArrayList.class.getTypeName(), "BOOL"); - - // Enums - MYSQL_MAPPING.put(Enum.class.getTypeName(), STRING_MAP); - - } + + private BSkyBlock plugin; /** * Handles the connection to the database and creation of the initial database schema (tables) for @@ -101,13 +50,14 @@ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { * @param type - the type of class to be stored in the database. Must inherit DataObject * @param databaseConnecter - authentication details for the database */ - public MySQLDatabaseHandler(Plugin plugin, Class type, DatabaseConnecter databaseConnecter) { + public MySQLDatabaseHandler(BSkyBlock plugin, Class type, DatabaseConnecter databaseConnecter) { super(plugin, type, databaseConnecter); + this.plugin = plugin; connection = databaseConnecter.createConnection(); // Check if the table exists in the database and if not, create it createSchema(); } - + /** * Creates the table in the database if it doesn't exist already */ @@ -115,70 +65,7 @@ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { StringBuilder sql = new StringBuilder(); sql.append("CREATE TABLE IF NOT EXISTS `"); sql.append(dataObject.getCanonicalName()); - sql.append("` ("); - // Run through the fields of the class using introspection - for (Field field : dataObject.getDeclaredFields()) { - try { - // Get the description of the field - PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), dataObject); - // Get default SQL mappings - // Get the write method for this field. This method will take an argument of the type of this field. - Method writeMethod = propertyDescriptor.getWriteMethod(); - // The SQL column name is the name of the field - String columnName = field.getName(); - // Get the mapping for this field from the hashmap - String typeName = propertyDescriptor.getPropertyType().getTypeName(); - if (propertyDescriptor.getPropertyType().isEnum()) { - typeName = "Enum"; - } - String mapping = MYSQL_MAPPING.get(typeName); - // If it exists, then create the SQL - if (mapping != null) { - // Note that the column name must be enclosed in `'s because it may include reserved words. - sql.append("`"); - sql.append(columnName); - sql.append("` "); - sql.append(mapping); - sql.append(","); - // Create set and map tables if the type is a collection - if (propertyDescriptor.getPropertyType().equals(Set.class) || - propertyDescriptor.getPropertyType().equals(Map.class) || - propertyDescriptor.getPropertyType().equals(HashMap.class) || - propertyDescriptor.getPropertyType().equals(ArrayList.class)) { - // The ID in this table relates to the parent table and is unique - StringBuilder setSql = new StringBuilder(); - setSql.append("CREATE TABLE IF NOT EXISTS `"); - setSql.append(dataObject.getCanonicalName()); - setSql.append("."); - setSql.append(field.getName()); - setSql.append("` (uniqueId VARCHAR(36) NOT NULL, "); - // Get columns separated by commas - setSql.append(getCollectionColumnString(writeMethod,false,true)); - // Close the SQL string - setSql.append(")"); - // Execute the statement - try (PreparedStatement collections = connection.prepareStatement(setSql.toString())) { - collections.executeUpdate(); - } catch (SQLException e) { - plugin.getLogger().severe(() -> "Getter or setter missing in data object. Cannot create schema! " + e.getMessage()); - } - } - } else { - // The Java type is not in the hashmap, so we'll just guess that it can be stored in a string - // This should NOT be used in general because every type should be in the hashmap - sql.append(field.getName()); - sql.append(" "); - sql.append(STRING_MAP); - sql.append(","); - plugin.getLogger().severe("Unknown type! Hoping it'll fit in a string!"); - plugin.getLogger().severe(propertyDescriptor.getPropertyType().getTypeName()); - } - } catch (IntrospectionException e) { - plugin.getLogger().severe(() -> "Getter or setter missing in data object. Cannot create schema! " + e.getMessage()); - } - } - // For the main table for the class, the unique ID is the primary key - sql.append(" PRIMARY KEY (uniqueId))"); + sql.append("` (json JSON, uniqueId VARCHAR(255) GENERATED ALWAYS AS (json->\"$.uniqueId\"), UNIQUE INDEX i (uniqueId) )"); // Prepare and execute the database statements try (PreparedStatement pstmt = connection.prepareStatement(sql.toString())) { pstmt.executeUpdate(); @@ -186,597 +73,111 @@ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { plugin.getLogger().severe(() -> "Problem trying to create schema for data object " + dataObject.getCanonicalName() + " " + e.getMessage()); } } - - /** - * - * Creates a comma-separated-String with the names of the variables in this - * class - * Not used in Flat File database. - * @param usePlaceHolders - * true, if PreparedStatement-placeholders ('?') should be used - * instead of the names of the variables - * @return a comma-separated-String with the names of the variables - */ - public String getColumns(boolean usePlaceHolders) { - StringBuilder sb = new StringBuilder(); - - boolean first = true; - /* Iterate the column-names */ - for (Field f : dataObject.getDeclaredFields()) { - if (first) { - first = false; - } else { - sb.append(", "); - } - - if (usePlaceHolders) { - sb.append("?"); - } else { - sb.append("`" + f.getName() + "`"); - } - } - - return sb.toString(); + + // Gets the GSON builder + private Gson getGSON() { + // excludeFieldsWithoutExposeAnnotation - this means that every field to be stored should use @Expose + // enableComplexMapKeySerialization - forces GSON to use TypeAdapters even for Map keys + GsonBuilder builder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().enableComplexMapKeySerialization(); + // Register adapters + builder.registerTypeAdapter(Location.class, new LocationAdapter(plugin)) ; + builder.registerTypeAdapter(World.class, new WorldAdapter(plugin)); + builder.registerTypeAdapter(Flag.class, new FlagAdapter(plugin)); + builder.registerTypeAdapter(PotionEffectType.class, new PotionEffectTypeAdapter()); + // Keep null in the database + builder.serializeNulls(); + // Allow characters like < or > without escaping them + builder.disableHtmlEscaping(); + return builder.create(); } - /** - * Returns a string of columns separated by commas that represent the parameter types of this method - * this is used to get into parameters like HashMap at runtime and find out Location - * and Boolean. - * @param writeMethod - * @param usePlaceHolders - * true, if PreparedStatement-placeholders ('?') should be used - * instead of the names of the variables - * @param createSchema if true contains the columns types - * @return Returns a string of columns separated by commas. - */ - private String getCollectionColumnString(Method writeMethod, boolean usePlaceHolders, boolean createSchema) { - StringBuilder sb = new StringBuilder(); - List cols = getCollentionColumnList(writeMethod, createSchema); - boolean first = true; - for (String col : cols) { - // Add commas - if (first) { - first = false; - } else { - sb.append(", "); - } - // this is used if the string is going to be used to insert something so the value will replace the ? - if (usePlaceHolders) { - sb.append("?"); - } else { - sb.append(col); - } - } - return sb.toString(); - } - - /** - * Returns a list of columns that represent the parameter types of this method - * @param method - * @param createSchema if true contains the columns types - * @return Returns a list of columns separated by commas. - */ - private List getCollentionColumnList(Method method, boolean createSchema) { - List columns = new ArrayList<>(); - for (Entry en : getCollectionColumnMap(method).entrySet()) { - StringBuilder col = new StringBuilder(); - col.append(en.getKey()); - if (createSchema) { - col.append(" "); - col.append(en.getValue()); - } - columns.add(col.toString()); - } - - return columns; - } - - /** - * Returns a map of column names and their types - * @param method - * @return - */ - private Map getCollectionColumnMap(Method method) { - Map columns = new LinkedHashMap<>(); - // Get the return type - // This uses a trick to extract what the arguments are of the writeMethod of the field. - // In this way, we can deduce what type needs to be written at runtime. - Type[] genericParameterTypes = method.getGenericParameterTypes(); - // There could be more than one argument, so step through them - for (Type genericParameterType : genericParameterTypes) { - // If the argument is a parameter, then do something - this should always be true if the parameter is a collection - if (genericParameterType instanceof ParameterizedType) { - // Get the actual type arguments of the parameter - Type[] parameters = ((ParameterizedType)genericParameterType).getActualTypeArguments(); - //parameters[0] contains java.lang.String for method like "method(List value)" - // Run through them one by one and create a SQL string - int index = 0; - for (Type type : parameters) { - // This is a request for column names. - String setMapping = MYSQL_MAPPING.get(type.getTypeName()); - // This column name format is typeName_# where # is a number incremented from 0 - columns.put("`" + type.getTypeName() + "_" + index + "`", setMapping != null ? setMapping : STRING_MAP); - // Increment the index so each column has a unique name - index++; - } - } - } - return columns; - } - - String createSelectQuery() { - - StringBuilder sb = new StringBuilder(); - - sb.append("SELECT "); - sb.append(getColumns(false)); - sb.append(" FROM "); - sb.append("`"); - sb.append(dataObject.getCanonicalName()); - sb.append("`"); - - return sb.toString(); - } - - String createInsertQuery() { - - StringBuilder sb = new StringBuilder(); - // Replace into is used so that any data in the table will be replaced with updated data - sb.append("REPLACE INTO "); - sb.append("`"); - // The table name is the canonical name, so that add-ons can be sure of a unique table in the database - sb.append(dataObject.getCanonicalName()); - sb.append("`"); - sb.append("("); - sb.append(getColumns(false)); - sb.append(")"); - sb.append(" VALUES ("); - sb.append(getColumns(true)); - sb.append(")"); - - return sb.toString(); - } - - String createDeleteQuery() { - return "DELETE FROM [table_name] WHERE uniqueId = ?"; - } - - /** - * Inserts a into the corresponding database-table - * - * @param instance that should be inserted into the corresponding database-table. Must extend DataObject. - */ - /* (non-Javadoc) - * @see us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler#insertObject(java.lang.Object) - */ @Override - public void saveObject(T instance) throws SQLException, - SecurityException, IllegalArgumentException, - InstantiationException, IllegalAccessException, - IntrospectionException, InvocationTargetException, NoSuchMethodException { - - try (PreparedStatement preparedStatement = connection.prepareStatement(createInsertQuery())) { - // Get the uniqueId. As each class extends DataObject, it must have this method in it. - PropertyDescriptor propertyDescriptor = new PropertyDescriptor("uniqueId", dataObject); - Method getUniqueId = propertyDescriptor.getReadMethod(); - final String uniqueId = (String) getUniqueId.invoke(instance); - if (uniqueId.isEmpty()) { - throw new SQLException("uniqueId is blank"); - } - // Create the insertion - int i = 0; - // Run through the fields in the class using introspection - for (Field field : dataObject.getDeclaredFields()) { - // Get the field's property descriptor - propertyDescriptor = new PropertyDescriptor(field.getName(), dataObject); - // Get the read method for this field - Method method = propertyDescriptor.getReadMethod(); - //sql += "`" + field.getName() + "` " + mapping + ","; - // Invoke the read method to obtain the value from the class - this is the value we need to store in the database - Object value = method.invoke(instance); - // Adapter Notation - Adapter adapterNotation = field.getAnnotation(Adapter.class); - if (adapterNotation != null && AdapterInterface.class.isAssignableFrom(adapterNotation.value())) { - // A conversion adapter has been defined - value = ((AdapterInterface)adapterNotation.value().newInstance()).deserialize(value); - } - // Create set and map table inserts if this is a Collection - if (propertyDescriptor.getPropertyType().equals(Set.class) || - propertyDescriptor.getPropertyType().equals(Map.class) || - propertyDescriptor.getPropertyType().equals(HashMap.class) || - propertyDescriptor.getPropertyType().equals(ArrayList.class)) { - // Collection - // The table is cleared for this uniqueId every time the data is stored - StringBuilder clearTableSql = new StringBuilder(); - clearTableSql.append("DELETE FROM `"); - clearTableSql.append(dataObject.getCanonicalName()); - clearTableSql.append("."); - clearTableSql.append(field.getName()); - clearTableSql.append("` WHERE uniqueId = ?"); - try (PreparedStatement collStatement = connection.prepareStatement(clearTableSql.toString())) { - collStatement.setString(1, uniqueId); - collStatement.execute(); - } - // Insert into the table - StringBuilder setSql = new StringBuilder(); - setSql.append("INSERT INTO `"); - setSql.append(dataObject.getCanonicalName()); - setSql.append("."); - setSql.append(field.getName()); - setSql.append("` (uniqueId, "); - // Get the columns we are going to insert, just the names of them - setSql.append(getCollectionColumnString(propertyDescriptor.getWriteMethod(), false, false)); - setSql.append(") "); - // Get all the ?'s for the columns - setSql.append("VALUES (?,"); - setSql.append(getCollectionColumnString(propertyDescriptor.getWriteMethod(), true, false)); - setSql.append(")"); - // Prepare the statement - try (PreparedStatement collStatement = connection.prepareStatement(setSql.toString())) { - // Set the uniqueId - collStatement.setString(1, uniqueId); - // Do single dimension types (set and list) - if (propertyDescriptor.getPropertyType().equals(Set.class) || - propertyDescriptor.getPropertyType().equals(ArrayList.class)) { - //plugin.getLogger().info("DEBUG: set class for "); - // Loop through the set or list - // Note that we have no idea what type this is - Collection collection = (Collection)value; - Iterator it = collection.iterator(); - while (it.hasNext()) { - Object setValue = it.next(); - //if (setValue instanceof UUID) { - // Serialize everything - setValue = serialize(setValue, setValue.getClass()); - //} - // Set the value from ? to whatever it is - collStatement.setObject(2, setValue); - // Execute the SQL in the database - collStatement.execute(); - } - } else if (propertyDescriptor.getPropertyType().equals(Map.class) || - propertyDescriptor.getPropertyType().equals(HashMap.class)) { - // Loop through the map - Map collection = (Map)value; - Iterator it = collection.entrySet().iterator(); - while (it.hasNext()) { - Entry en = (Entry) it.next(); - // Get the key and serialize it - Object key = serialize(en.getKey(), en.getKey().getClass()); - // Get the value and serialize it - Object mapValue = serialize(en.getValue(), en.getValue().getClass()); - // Write the objects into prepared statement - collStatement.setObject(2, key); - collStatement.setObject(3, mapValue); - // Write to database - collStatement.execute(); - } - } - // Set value for the main insert. For collections, this is just a dummy value because the real values are in the - // additional table. - value = true; - } - } else { - // If the value is not a collection, it just needs to be serialized to go into the database. - value = serialize(value, propertyDescriptor.getPropertyType()); - } - // Set the value in the main prepared statement and increment the location - // Note that with prepared statements, they count from 1, not 0, so the ++ goes on the front of i. - preparedStatement.setObject(++i, value); - } - // Add the statements to a batch - preparedStatement.addBatch(); - // Execute - preparedStatement.executeBatch(); - } - } - - /** - * Serializes values if required to go into a database. - * TODO: This method will need expanding to include additional Java types - * @param value - * @param clazz - the known class of value - * @return the object to write to the database - */ - private Object serialize(Object value, Class clazz) { - //plugin.getLogger().info("DEBUG: serialize - class is " + clazz.getTypeName()); - if (value == null) { - // If the value is null to start, return null as a string - return "null"; - } - // Types that need to be serialized - // TODO - add others, like Date, Timestamp, etc. - if (clazz.equals(UUID.class)) { - value = value.toString(); - } - else - // Bukkit Types - if (clazz.equals(Location.class)) { - // Serialize - value = Util.getStringLocation(((Location)value)); - } else - if (clazz.equals(World.class)) { - // Serialize - get the name - value = ((World)value).getName(); - } else - if (clazz.getSuperclass() != null && clazz.getSuperclass().equals(Enum.class)) { - //Custom enums are a child of the Enum class. Just get the names of each one. - value = ((Enum)value).name(); - } - if (value == null) { - // The value could become null from the above checks - return "null"; - } - return value; - } - - /** - * Creates a list of s filled with values from the corresponding - * database-table - * - * @return List of s filled with values from the corresponding - * database-table - * - */ - @Override - public List loadObjects() throws SQLException, - SecurityException, IllegalArgumentException, - InstantiationException, IllegalAccessException, - IntrospectionException, InvocationTargetException, ClassNotFoundException { - - try (Statement statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery(createSelectQuery())) { - return createObjects(resultSet); - } - } - - - /* (non-Javadoc) - * @see us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler#selectObject(java.lang.String) - */ - @Override - public T loadObject(String uniqueId) throws InstantiationException, - IllegalAccessException, IllegalArgumentException, - InvocationTargetException, IntrospectionException, SQLException, SecurityException, ClassNotFoundException { - - // Build the select query - StringBuilder query = new StringBuilder(); - query.append("SELECT "); - query.append(getColumns(false)); - query.append(" FROM `"); - query.append(dataObject.getCanonicalName()); - query.append("` WHERE uniqueId = ? LIMIT 1"); - - try (PreparedStatement preparedStatement = connection.prepareStatement(query.toString())) { - preparedStatement.setString(1, uniqueId); - try (ResultSet resultSet = preparedStatement.executeQuery()) { - // If there is a result, we only want/need the first one - List result = createObjects(resultSet); - if (!result.isEmpty()) { - return result.get(0); - } - } - } - return null; - } - - - /** - * - * Creates a list of s filled with values from the provided ResultSet - * - * @param resultSet - * ResultSet that contains the result of the - * database-select-query - * - * @return List of s filled with values from the provided ResultSet - * - */ - @SuppressWarnings("unchecked") - private List createObjects(ResultSet resultSet) - throws SecurityException, IllegalArgumentException, - SQLException, InstantiationException, - IllegalAccessException, IntrospectionException, - InvocationTargetException, ClassNotFoundException { - + public List loadObjects() { List list = new ArrayList<>(); - // The database can return multiple results in one go, e.g., all the islands in the database - // Run through them one by one - while (resultSet.next()) { - // Create a new instance of this type - T instance = dataObject.newInstance(); - // Get the unique ID from the results - String uniqueId = resultSet.getString("uniqueId"); - if (uniqueId == null) { - throw new SQLException("No unique ID in the results!"); - } - // Use introspection to run through all the fields in this type class - for (Field field : dataObject.getDeclaredFields()) { - /* We assume the table-column-names exactly match the variable-names of T */ - Object value = resultSet.getObject(field.getName()); - // Get the property descriptor of this type - PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), dataObject); - // Get the write method for this field, because we are going to use it to write the value - // once we get the value from the database - Method method = propertyDescriptor.getWriteMethod(); - // If the type is a Collection, then we need to deal with set and map tables - if (Collection.class.isAssignableFrom(propertyDescriptor.getPropertyType()) - || Map.class.isAssignableFrom(propertyDescriptor.getPropertyType())) { - // Collection - // value is just of type boolean right now - StringBuilder setSql = new StringBuilder(); - setSql.append("SELECT "); - // Get the columns, just the names of them, no ?'s or types - setSql.append(getCollectionColumnString(method, false, false)); - setSql.append(" "); - setSql.append("FROM `"); - setSql.append(dataObject.getCanonicalName()); - setSql.append("."); - setSql.append(field.getName()); - setSql.append("` "); - // We will need to fill in the ? later with the unique id of the class from the database - setSql.append("WHERE uniqueId = ?"); - // Prepare the statement - try (PreparedStatement collStatement = connection.prepareStatement(setSql.toString())) { - // Set the unique ID - collStatement.setObject(1, uniqueId); - try (ResultSet collectionResultSet = collStatement.executeQuery()) { - - //plugin.getLogger().info("DEBUG: collectionResultSet = " + collectionResultSet.toString()); - // Do single dimension types (set and list) - if (Set.class.isAssignableFrom(propertyDescriptor.getPropertyType())) { - // Loop through the collection resultset - // Note that we have no idea what type this is - List collectionTypes = Util.getCollectionParameterTypes(method); - // collectionTypes should be only 1 long - Type setType = collectionTypes.get(0); - value = new HashSet<>(); - while (collectionResultSet.next()) { - ((Set) value).add(deserialize(collectionResultSet.getObject(1),Class.forName(setType.getTypeName()))); - } - } else if (List.class.isAssignableFrom(propertyDescriptor.getPropertyType())) { - // Loop through the collection resultset - // Note that we have no idea what type this is - List collectionTypes = Util.getCollectionParameterTypes(method); - // collectionTypes should be only 1 long - Type setType = collectionTypes.get(0); - value = new ArrayList<>(); - //plugin.getLogger().info("DEBUG: collection type argument = " + collectionTypes); - while (collectionResultSet.next()) { - // Add to the list - ((List) value).add(deserialize(collectionResultSet.getObject(1),Class.forName(setType.getTypeName()))); - } - } else if (Map.class.isAssignableFrom(propertyDescriptor.getPropertyType()) || - HashMap.class.isAssignableFrom(propertyDescriptor.getPropertyType())) { - // Loop through the collection resultset - // Note that we have no idea what type this is - List collectionTypes = Util.getCollectionParameterTypes(method); - // collectionTypes should be 2 long - Type keyType = collectionTypes.get(0); - Type valueType = collectionTypes.get(1); - value = new HashMap<>(); - while (collectionResultSet.next()) { - // Work through the columns - // Key - Object key = deserialize(collectionResultSet.getObject(1),Class.forName(keyType.getTypeName())); - Object mapValue = deserialize(collectionResultSet.getObject(2),Class.forName(valueType.getTypeName())); - ((Map) value).put(key,mapValue); - } - } else { - // Set value for the main insert. For collections, this is just a dummy value because the real values are in the - // additional table. - value = true; - } - } - } - } else { - value = deserialize(value, propertyDescriptor.getPropertyType()); + StringBuilder sb = new StringBuilder(); + sb.append("SELECT `json` FROM `"); + sb.append(dataObject.getCanonicalName()); + sb.append("`"); + try (Statement preparedStatement = connection.createStatement()) { + try (ResultSet resultSet = preparedStatement.executeQuery(sb.toString())) { + // Load all the results + Gson gson = getGSON(); + while (resultSet.next()) { + list.add(gson.fromJson(resultSet.getString("json"), dataObject)); } - // Adapter - // Check if there is an annotation on the field - Adapter adapterNotation = field.getAnnotation(Adapter.class); - if (adapterNotation != null && AdapterInterface.class.isAssignableFrom(adapterNotation.value())) { - // A conversion adapter has been defined - value = ((AdapterInterface)adapterNotation.value().newInstance()).serialize(value); - } - // Write the value to the class - method.invoke(instance, value); } - // Write the result into the list we are going to return - list.add(instance); + } catch (SQLException e) { + plugin.getLogger().severe(() -> "Could not load objects " + e.getMessage()); } return list; } - /** - * Deserialize any values according to their class - * TODO: expand to include additional types - * @param value - * @param clazz - * @return the deserialized value - */ - @SuppressWarnings({ "unchecked", "rawtypes" }) - private Object deserialize(Object value, Class clazz) { - if (value instanceof String && value.equals("null")) { - // If the value is null as a string, return null - return null; - } - // Types that need to be deserialized - if (clazz.equals(UUID.class)) { - value = UUID.fromString((String)value); - } - // Bukkit Types - if (clazz.equals(Location.class)) { - // Get Location from String - may be null... - value = Util.getLocationString(((String)value)); - } - if (clazz.equals(World.class)) { - // Get world by name - may be null... - value = plugin.getServer().getWorld((String)value); - } - // Enums - if (Enum.class.isAssignableFrom(clazz)) { - //Custom enums are a child of the Enum class. - // Find out the value - try { - Class enumClass = (Class)clazz; - value = Enum.valueOf(enumClass, (String)value); - } catch (Exception e) { - plugin.getLogger().severe("Could not deserialize enum! " + e.getMessage()); - } - } - return value; - } - - /* (non-Javadoc) - * @see us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler#deleteObject(java.lang.Object) - */ @Override - public void deleteObject(T instance) - throws IllegalAccessException, IllegalArgumentException, - InvocationTargetException, IntrospectionException, SQLException, NoSuchMethodException, SecurityException { - // Delete this object from all tables - // Try to connect to the database - // Get the uniqueId. As each class extends DataObject, it must have this method in it. - Method getUniqueId = dataObject.getMethod("getUniqueId"); - String uniqueId = (String) getUniqueId.invoke(instance); - //plugin.getLogger().info("DEBUG: Unique Id = " + uniqueId); - if (uniqueId.isEmpty()) { - throw new SQLException("uniqueId is blank"); - } - // Delete from the main table - // First substitution is the table name - // deleteQuery is created in super from the createInsertQuery() method - try (PreparedStatement preparedStatement = connection.prepareStatement(createDeleteQuery().replace("[table_name]", "`" + dataObject.getCanonicalName() + "`"))) { - // Second is the unique ID + public T loadObject(String uniqueId) { + StringBuilder sb = new StringBuilder(); + sb.append("SELECT `json` FROM `"); + sb.append(dataObject.getCanonicalName()); + sb.append("` WHERE uniqueId = ? LIMIT 1"); + try (PreparedStatement preparedStatement = connection.prepareStatement(sb.toString())) { preparedStatement.setString(1, uniqueId); - preparedStatement.addBatch(); - preparedStatement.executeBatch(); - } - - // Delete from any sub tables created from the object - // Run through the fields in the class using introspection - for (Field field : dataObject.getDeclaredFields()) { - // Get the field's property descriptor - PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), dataObject); - // Delete Collection tables - if (propertyDescriptor.getPropertyType().equals(Set.class) || - propertyDescriptor.getPropertyType().equals(Map.class) || - propertyDescriptor.getPropertyType().equals(HashMap.class) || - propertyDescriptor.getPropertyType().equals(ArrayList.class)) { - // First substitution is the table name - try (PreparedStatement preparedStatement2 = connection.prepareStatement(createDeleteQuery().replace("[table_name]", "`" + dataObject.getCanonicalName() + "." + field.getName() + "`"))) { - // Second is the unique ID - preparedStatement2.setString(1, uniqueId); - preparedStatement2.addBatch(); - // Execute - preparedStatement2.executeBatch(); + try (ResultSet resultSet = preparedStatement.executeQuery()) { + while (resultSet.next()) { + // If there is a result, we only want/need the first one + Gson gson = getGSON(); + return gson.fromJson(resultSet.getString("json"), dataObject); } } + } catch (SQLException e) { + plugin.getLogger().severe(() -> "Could not load object " + uniqueId + " " + e.getMessage()); } - } + return null; + } + @Override + public void saveObject(T instance) { + if (!(instance instanceof DataObject)) { + plugin.getLogger().severe(() -> "This class is not a DataObject: " + instance.getClass().getName()); + return; + } + StringBuilder sb = new StringBuilder(); + // Replace into is used so that any data in the table will be replaced with updated data + sb.append("INSERT INTO "); + sb.append("`"); + // The table name is the canonical name, so that add-ons can be sure of a unique table in the database + sb.append(dataObject.getCanonicalName()); + sb.append("` (json) VALUES (?) ON DUPLICATE KEY UPDATE json = ?"); + try (PreparedStatement preparedStatement = connection.prepareStatement(sb.toString())) { + Gson gson = getGSON(); + String toStore = gson.toJson(instance); + preparedStatement.setString(1, toStore); + preparedStatement.setString(2, toStore); + preparedStatement.execute(); + } catch (SQLException e) { + plugin.getLogger().severe(() -> "Could not save object " + instance.getClass().getName() + " " + e.getMessage()); + // Leave in for now until we know there are no particular issues + e.printStackTrace(); + } + } + + @Override + public void deleteObject(T instance) { + if (!(instance instanceof DataObject)) { + plugin.getLogger().severe(() -> "This class is not a DataObject: " + instance.getClass().getName()); + return; + } + StringBuilder sb = new StringBuilder(); + sb.append("DELETE FROM `"); + sb.append(dataObject.getCanonicalName()); + sb.append("` WHERE uniqueId = ?"); + try (PreparedStatement preparedStatement = connection.prepareStatement(sb.toString())) { + Method getUniqueId = dataObject.getMethod("getUniqueId"); + String uniqueId = (String) getUniqueId.invoke(instance); + preparedStatement.setString(1, uniqueId); + preparedStatement.execute(); + } catch (Exception e) { + plugin.getLogger().severe(() -> "Could not delete object " + instance.getClass().getName() + " " + e.getMessage()); + } + } /* (non-Javadoc) * @see us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler#objectExists(java.lang.String) @@ -785,7 +186,7 @@ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { public boolean objectExists(String key) { // Create the query to see if this key exists StringBuilder query = new StringBuilder(); - query.append("SELECT IF ( EXISTS( SELECT * FROM `"); + query.append("SELECT IF ( EXISTS( SELECT * FROM `"); query.append(dataObject.getCanonicalName()); query.append("` WHERE `uniqueId` = ?), 1, 0)"); @@ -802,18 +203,4 @@ public class MySQLDatabaseHandler extends AbstractDatabaseHandler { return false; } - @Override - public void saveSettings(T instance) - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException { - // This method should not be used because configs are not stored in MySQL - - } - - @Override - public T loadSettings(String uniqueId, T dbConfig) throws InstantiationException, IllegalAccessException, - IllegalArgumentException, InvocationTargetException, ClassNotFoundException, IntrospectionException { - // This method should not be used because configs are not stored in MySQL - return null; - } - } diff --git a/src/main/java/us/tastybento/bskyblock/database/mysql/adapters/FlagAdapter.java b/src/main/java/us/tastybento/bskyblock/database/mysql/adapters/FlagAdapter.java new file mode 100644 index 000000000..4e2f0889b --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/database/mysql/adapters/FlagAdapter.java @@ -0,0 +1,39 @@ +package us.tastybento.bskyblock.database.mysql.adapters; + +import java.io.IOException; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.api.flags.Flag; + +public class FlagAdapter extends TypeAdapter { + + private BSkyBlock plugin; + + public FlagAdapter(BSkyBlock plugin) { + this.plugin = plugin; + } + + @Override + public void write(JsonWriter out, Flag value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + out.value(value.getID()); + + } + + @Override + public Flag read(JsonReader reader) throws IOException { + if (reader.peek() == JsonToken.NULL) { + reader.nextNull(); + return null; + } + return plugin.getFlagsManager().getFlagByID(reader.nextString()); + } +} \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/database/mysql/adapters/LocationAdapter.java b/src/main/java/us/tastybento/bskyblock/database/mysql/adapters/LocationAdapter.java new file mode 100644 index 000000000..cab2dbdd8 --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/database/mysql/adapters/LocationAdapter.java @@ -0,0 +1,54 @@ +package us.tastybento.bskyblock.database.mysql.adapters; + +import java.io.IOException; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.plugin.Plugin; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; + +public class LocationAdapter extends TypeAdapter { + + private Plugin plugin; + + public LocationAdapter(Plugin plugin) { + this.plugin = plugin; + } + + @Override + public void write(JsonWriter out, Location location) throws IOException { + if (location == null) { + out.nullValue(); + return; + } + out.beginArray(); + out.value(location.getWorld().getName()); + out.value(location.getX()); + out.value(location.getY()); + out.value(location.getZ()); + out.value(location.getYaw()); + out.value(location.getPitch()); + out.endArray(); + } + + @Override + public Location read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + in.beginArray(); + World world = plugin.getServer().getWorld(in.nextString()); + double x = in.nextDouble(); + double y = in.nextDouble(); + double z = in.nextDouble(); + float yaw = (float)in.nextDouble(); + float pitch = (float)in.nextDouble(); + in.endArray(); + return new Location(world, x, y, z, yaw, pitch); + } +} \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/database/mysql/adapters/WorldAdapter.java b/src/main/java/us/tastybento/bskyblock/database/mysql/adapters/WorldAdapter.java new file mode 100644 index 000000000..f9ee60c16 --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/database/mysql/adapters/WorldAdapter.java @@ -0,0 +1,39 @@ +package us.tastybento.bskyblock.database.mysql.adapters; + +import java.io.IOException; + +import org.bukkit.World; +import org.bukkit.plugin.Plugin; + +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonToken; +import com.google.gson.stream.JsonWriter; + +public class WorldAdapter extends TypeAdapter { + + private Plugin plugin; + + public WorldAdapter(Plugin plugin) { + this.plugin = plugin; + } + + @Override + public void write(JsonWriter out, World value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + out.value(value.getName()); + + } + + @Override + public World read(JsonReader reader) throws IOException { + if (reader.peek() == JsonToken.NULL) { + reader.nextNull(); + return null; + } + return plugin.getServer().getWorld(reader.nextString()); + } +} \ No newline at end of file diff --git a/src/main/java/us/tastybento/bskyblock/database/mysqljson/LocationAdapter.java b/src/main/java/us/tastybento/bskyblock/database/mysqljson/LocationAdapter.java deleted file mode 100644 index 1d226d910..000000000 --- a/src/main/java/us/tastybento/bskyblock/database/mysqljson/LocationAdapter.java +++ /dev/null @@ -1,88 +0,0 @@ -package us.tastybento.bskyblock.database.mysqljson; - -import java.lang.reflect.Type; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; - -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.JsonPrimitive; -import com.google.gson.JsonSerializationContext; -import com.google.gson.JsonSerializer; - -public class LocationAdapter implements JsonDeserializer, JsonSerializer { - - public static final LocationAdapter INSTANCE = new LocationAdapter(); - - @Override - public Location deserialize( JsonElement json, Type type, JsonDeserializationContext jsonDeserializationContext ) throws JsonParseException { - - if ( !json.isJsonObject() ) { - throw new JsonParseException( "not a JSON object" ); - } - - final JsonObject obj = (JsonObject) json; - final JsonElement world = obj.get( "world" ); - final JsonElement x = obj.get( "x" ); - final JsonElement y = obj.get( "y" ); - final JsonElement z = obj.get( "z" ); - final JsonElement yaw = obj.get( "yaw" ); - final JsonElement pitch = obj.get( "pitch" ); - - if ( world == null || x == null || y == null || z == null || yaw == null || pitch == null ) { - throw new JsonParseException( "Malformed location json string!" ); - } - - if ( !world.isJsonPrimitive() || !((JsonPrimitive) world).isString() ) { - throw new JsonParseException( "world is not a string" ); - } - - if ( !x.isJsonPrimitive() || !((JsonPrimitive) x).isNumber() ) { - throw new JsonParseException( "x is not a number" ); - } - - if ( !y.isJsonPrimitive() || !((JsonPrimitive) y).isNumber() ) { - throw new JsonParseException( "y is not a number" ); - } - - if ( !z.isJsonPrimitive() || !((JsonPrimitive) z).isNumber() ) { - throw new JsonParseException( "z is not a number" ); - } - - if ( !yaw.isJsonPrimitive() || !((JsonPrimitive) yaw).isNumber() ) { - throw new JsonParseException( "yaw is not a number" ); - } - - if ( !pitch.isJsonPrimitive() || !((JsonPrimitive) pitch).isNumber() ) { - throw new JsonParseException( "pitch is not a number" ); - } - - World worldInstance = Bukkit.getWorld( world.getAsString() ); - if (worldInstance == null) { - throw new IllegalArgumentException("Unknown/not loaded world"); - } - - return new Location( worldInstance, x.getAsDouble(), y.getAsDouble(), z.getAsDouble(), yaw.getAsFloat(), pitch.getAsFloat() ); - - } - - @Override - public JsonElement serialize( Location location, Type type, JsonSerializationContext jsonSerializationContext ) { - - final JsonObject obj = new JsonObject(); - obj.addProperty( "world", location.getWorld().getName() ); - obj.addProperty( "x", location.getX() ); - obj.addProperty( "y", location.getY() ); - obj.addProperty( "z", location.getZ() ); - obj.addProperty( "yaw", location.getYaw() ); - obj.addProperty( "pitch", location.getPitch() ); - return obj; - - } - -} diff --git a/src/main/java/us/tastybento/bskyblock/database/mysqljson/MySQLDatabaseConnecterJ.java b/src/main/java/us/tastybento/bskyblock/database/mysqljson/MySQLDatabaseConnecterJ.java deleted file mode 100644 index 5977b30bd..000000000 --- a/src/main/java/us/tastybento/bskyblock/database/mysqljson/MySQLDatabaseConnecterJ.java +++ /dev/null @@ -1,75 +0,0 @@ -package us.tastybento.bskyblock.database.mysqljson; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.Map; - -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.YamlConfiguration; - -import us.tastybento.bskyblock.database.DatabaseConnecter; -import us.tastybento.bskyblock.database.DatabaseConnectionSettingsImpl; - -public class MySQLDatabaseConnecterJ implements DatabaseConnecter { - - private String connectionUrl; - private DatabaseConnectionSettingsImpl dbSettings; - private Connection connection = null; - - /** - * Class for MySQL database connections using the settings provided - * @param dbSettings - */ - public MySQLDatabaseConnecterJ(DatabaseConnectionSettingsImpl dbSettings) { - this.dbSettings = dbSettings; - try { - Class.forName("com.mysql.jdbc.Driver").newInstance(); - } catch (Exception e) { - Bukkit.getLogger().severe("Could not instantiate JDBC driver! " + e.getMessage()); - } - // jdbc:mysql://localhost:3306/Peoples?autoReconnect=true&useSSL=false - connectionUrl = "jdbc:mysql://" + dbSettings.getHost() + "/" + dbSettings.getDatabaseName() + "?autoReconnect=true&useSSL=false&allowMultiQueries=true"; - } - - @Override - public Connection createConnection() { - try { - connection = DriverManager.getConnection(connectionUrl, dbSettings.getUsername(), dbSettings.getPassword()); - } catch (SQLException e) { - Bukkit.getLogger().severe("Could not connect to the database! " + e.getMessage()); - } - return connection; - } - - @Override - public String getConnectionUrl() { - return connectionUrl; - } - - @Override - public String getUniqueId(String tableName) { - // Not used - return ""; - } - - @Override - public YamlConfiguration loadYamlFile(String string, String key) { - // Not used - return null; - } - - @Override - public boolean uniqueIdExists(String tableName, String key) { - // Not used - return false; - } - - @Override - public void saveYamlFile(YamlConfiguration yamlConfig, String tableName, String fileName, - Map commentMap) { - // Not used - - } - -} diff --git a/src/main/java/us/tastybento/bskyblock/database/mysqljson/MySQLDatabaseHandlerJ.java b/src/main/java/us/tastybento/bskyblock/database/mysqljson/MySQLDatabaseHandlerJ.java deleted file mode 100644 index f9d5156c0..000000000 --- a/src/main/java/us/tastybento/bskyblock/database/mysqljson/MySQLDatabaseHandlerJ.java +++ /dev/null @@ -1,191 +0,0 @@ -package us.tastybento.bskyblock.database.mysqljson; - -import java.beans.IntrospectionException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.List; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.plugin.Plugin; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - -import us.tastybento.bskyblock.database.DatabaseConnecter; -import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler; - -/** - * - * Class that inserts a into the corresponding database-table. - * - * @author tastybento - * - * @param - */ -public class MySQLDatabaseHandlerJ extends AbstractDatabaseHandler { - - /** - * Connection to the database - */ - private Connection connection = null; - - /** - * Handles the connection to the database and creation of the initial database schema (tables) for - * the class that will be stored. - * @param plugin - BSkyBlock plugin object - * @param type - the type of class to be stored in the database. Must inherit DataObject - * @param databaseConnecter - authentication details for the database - */ - public MySQLDatabaseHandlerJ(Plugin plugin, Class type, DatabaseConnecter databaseConnecter) { - super(plugin, type, databaseConnecter); - connection = databaseConnecter.createConnection(); - // Check if the table exists in the database and if not, create it - createSchema(); - } - - /** - * Creates the table in the database if it doesn't exist already - */ - private void createSchema() { - StringBuilder sql = new StringBuilder(); - sql.append("CREATE TABLE IF NOT EXISTS `"); - sql.append(dataObject.getCanonicalName()); - sql.append("` (json JSON, uniqueId VARCHAR(255) GENERATED ALWAYS AS (json->\"$.uniqueId\"), INDEX i (uniqueId) );"); - // Prepare and execute the database statements - try (PreparedStatement pstmt = connection.prepareStatement(sql.toString())) { - pstmt.executeUpdate(); - } catch (SQLException e) { - plugin.getLogger().severe(() -> "Problem trying to create schema for data object " + dataObject.getCanonicalName() + " " + e.getMessage()); - } - } - - @Override - public List loadObjects() { - List list = new ArrayList<>(); - StringBuilder sb = new StringBuilder(); - sb.append("SELECT `json` FROM `"); - sb.append(dataObject.getCanonicalName()); - sb.append("`"); - try (Statement preparedStatement = connection.createStatement()) { - try (ResultSet resultSet = preparedStatement.executeQuery(sb.toString())) { - // Load all the results - GsonBuilder builder = new GsonBuilder(); - builder.registerTypeAdapter(Location.class, new LocationAdapter()) ; - Gson gson = builder.create(); - while (resultSet.next()) { - list.add(gson.fromJson(resultSet.getString("json"), dataObject)); - } - } - } catch (SQLException e) { - plugin.getLogger().severe(() -> "Could not load objects " + e.getMessage()); - } - return list; - } - - - @Override - public T loadObject(String uniqueId) { - StringBuilder sb = new StringBuilder(); - sb.append("SELECT `json` FROM `"); - sb.append(dataObject.getCanonicalName()); - sb.append("` WHERE uniqueId = ? LIMIT 1"); - try (PreparedStatement preparedStatement = connection.prepareStatement(sb.toString())) { - preparedStatement.setString(1, uniqueId); - try (ResultSet resultSet = preparedStatement.executeQuery()) { - while (resultSet.next()) { - // If there is a result, we only want/need the first one - GsonBuilder builder = new GsonBuilder(); - builder.registerTypeAdapter(Location.class, new LocationAdapter()) ; - Gson gson = builder.create(); - return gson.fromJson(resultSet.getString("json"), dataObject); - } - } - } catch (SQLException e) { - plugin.getLogger().severe(() -> "Could not load object " + uniqueId + " " + e.getMessage()); - } - return null; - } - - @Override - public void saveObject(T instance) { - Bukkit.getLogger().severe(() -> "Saving object " + instance.getClass().getName()); - StringBuilder sb = new StringBuilder(); - // Replace into is used so that any data in the table will be replaced with updated data - sb.append("REPLACE INTO "); - sb.append("`"); - // The table name is the canonical name, so that add-ons can be sure of a unique table in the database - sb.append(dataObject.getCanonicalName()); - sb.append("` (json) VALUES (?)"); - try (PreparedStatement preparedStatement = connection.prepareStatement(sb.toString())) { - GsonBuilder builder = new GsonBuilder(); - builder.registerTypeAdapter(Location.class, new LocationAdapter()) ; - Gson gson = builder.create(); - preparedStatement.setString(1, gson.toJson(instance)); - } catch (SQLException e) { - plugin.getLogger().severe(() -> "Could not save object " + instance.getClass().getName() + " " + e.getMessage()); - } - } - - @Override - public void deleteObject(T instance) { - StringBuilder sb = new StringBuilder(); - sb.append("DELETE FROM `"); - sb.append(dataObject.getCanonicalName()); - sb.append("` WHERE uniqueId = ?"); - try (PreparedStatement preparedStatement = connection.prepareStatement(sb.toString())) { - Method getUniqueId = dataObject.getMethod("getUniqueId"); - String uniqueId = (String) getUniqueId.invoke(instance); - preparedStatement.setString(1, uniqueId); - preparedStatement.executeQuery(); - } catch (Exception e) { - plugin.getLogger().severe(() -> "Could not delete object " + instance.getClass().getName() + " " + e.getMessage()); - } - } - - /* (non-Javadoc) - * @see us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler#objectExists(java.lang.String) - */ - @Override - public boolean objectExists(String key) { - // Create the query to see if this key exists - StringBuilder query = new StringBuilder(); - query.append("SELECT IF ( EXISTS( SELECT * FROM `"); - query.append(dataObject.getCanonicalName()); - query.append("` WHERE `uniqueId` = ?), 1, 0)"); - - try (PreparedStatement preparedStatement = connection.prepareStatement(query.toString())) { - preparedStatement.setString(1, key); - try (ResultSet resultSet = preparedStatement.executeQuery()) { - if (resultSet.next()) { - return resultSet.getBoolean(1); - } - } - } catch (SQLException e) { - plugin.getLogger().severe("Could not check if key exists in database! " + key + " " + e.getMessage()); - } - return false; - } - - @Override - public void saveSettings(T instance) - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, IntrospectionException { - // This method should not be used because configs are not stored in MySQL - - } - - @Override - public T loadSettings(String uniqueId, T dbConfig) { - // This method should not be used because configs are not stored in MySQL - return null; - } - - - -} diff --git a/src/main/java/us/tastybento/bskyblock/database/mysqljson/MySQLDatabaseJ.java b/src/main/java/us/tastybento/bskyblock/database/mysqljson/MySQLDatabaseJ.java deleted file mode 100755 index 8fa9a17a4..000000000 --- a/src/main/java/us/tastybento/bskyblock/database/mysqljson/MySQLDatabaseJ.java +++ /dev/null @@ -1,22 +0,0 @@ -package us.tastybento.bskyblock.database.mysqljson; - -import us.tastybento.bskyblock.BSkyBlock; -import us.tastybento.bskyblock.database.BSBDatabase; -import us.tastybento.bskyblock.database.DatabaseConnectionSettingsImpl; -import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler; - -public class MySQLDatabaseJ extends BSBDatabase{ - - @Override - public AbstractDatabaseHandler getHandler(Class type) { - BSkyBlock plugin = BSkyBlock.getInstance(); - return new MySQLDatabaseHandlerJ<>(plugin, type, new MySQLDatabaseConnecterJ(new DatabaseConnectionSettingsImpl( - plugin.getSettings().getDbHost(), - plugin.getSettings().getDbPort(), - plugin.getSettings().getDbName(), - plugin.getSettings().getDbUsername(), - plugin.getSettings().getDbPassword() - ))); - } - -} diff --git a/src/main/java/us/tastybento/bskyblock/database/objects/Island.java b/src/main/java/us/tastybento/bskyblock/database/objects/Island.java index 2f1320f61..79a9518e5 100755 --- a/src/main/java/us/tastybento/bskyblock/database/objects/Island.java +++ b/src/main/java/us/tastybento/bskyblock/database/objects/Island.java @@ -7,24 +7,18 @@ import java.util.Map.Entry; import java.util.Set; import java.util.UUID; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.OfflinePlayer; import org.bukkit.World; import org.bukkit.block.BlockState; import org.bukkit.entity.Entity; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet.Builder; +import com.google.gson.annotations.Expose; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.api.commands.User; -import us.tastybento.bskyblock.api.events.IslandBaseEvent; -import us.tastybento.bskyblock.api.events.island.IslandEvent; -import us.tastybento.bskyblock.api.events.island.IslandEvent.IslandLockEvent; -import us.tastybento.bskyblock.api.events.island.IslandEvent.IslandUnlockEvent; -import us.tastybento.bskyblock.api.events.island.IslandEvent.Reason; import us.tastybento.bskyblock.api.flags.Flag; import us.tastybento.bskyblock.database.objects.adapters.Adapter; import us.tastybento.bskyblock.database.objects.adapters.FlagSerializer; @@ -42,57 +36,71 @@ import us.tastybento.bskyblock.util.Util; */ public class Island implements DataObject { - private String uniqueId = ""; + @Expose + private String uniqueId = UUID.randomUUID().toString(); //// Island //// // The center of the island itself + @Expose private Location center; // Island range + @Expose private int range; // Coordinates of the island area + @Expose private int minX; - + @Expose private int minZ; // Coordinates of minimum protected area + @Expose private int minProtectedX; - + @Expose private int minProtectedZ; // Protection size + @Expose private int protectionRange; - // World the island is in + // World the island started in. This may be different from the island location + @Expose private World world; // Display name - private String name; + @Expose + private String name = ""; // Time parameters + @Expose private long createdDate; - + @Expose private long updatedDate; //// Team //// + @Expose private UUID owner; + @Expose private Map members = new HashMap<>(); //// State //// + @Expose private boolean locked = false; - + @Expose private boolean spawn = false; - + @Expose private boolean purgeProtected = false; //// Protection flags //// @Adapter(FlagSerializer.class) + @Expose private Map flags = new HashMap<>(); + @Expose private int levelHandicap; - + @Expose private Location spawnPoint; public Island() {} @@ -126,7 +134,6 @@ public class Island implements DataObject { * @return true if successfully added */ public boolean addToBanList(UUID targetUUID) { - // TODO fire ban event if (targetUUID != null) { members.put(targetUUID, RanksManager.BANNED_RANK); } @@ -206,7 +213,7 @@ public class Island implements DataObject { */ public ImmutableSet getMemberSet(){ Builder result = new ImmutableSet.Builder<>(); - + for (Entry member: members.entrySet()) { if (member.getValue() >= RanksManager.MEMBER_RANK) { result.add(member.getKey()); @@ -247,15 +254,7 @@ public class Island implements DataObject { * @return the island display name or the owner's name if none is set */ public String getName() { - if (name != null) { - return name; - } - if (owner != null) { - OfflinePlayer player = Bukkit.getServer().getOfflinePlayer(owner); - name = player.getName(); - return player.getName(); - } - return ""; + return name; } /** @@ -292,7 +291,6 @@ public class Island implements DataObject { * @return rank integer */ public int getRank(User user) { - //Bukkit.getLogger().info("DEBUG: user UUID = " + user.getUniqueId()); return members.getOrDefault(user.getUniqueId(), RanksManager.VISITOR_RANK); } @@ -353,10 +351,6 @@ public class Island implements DataObject { @Override public String getUniqueId() { - // Island's have UUID's that are randomly assigned if they do not exist - if (uniqueId.isEmpty()) { - uniqueId = UUID.randomUUID().toString(); - } return uniqueId; } @@ -402,8 +396,7 @@ public class Island implements DataObject { * @return true if in the island space */ public boolean inIslandSpace(int x, int z) { - //Bukkit.getLogger().info("DEBUG: center - " + center); - return x >= minX && x < minX + range*2 && z >= minZ && z < minZ + range*2; + return x >= minX && x < minX + range*2 && z >= minZ && z < minZ + range*2; } public boolean inIslandSpace(Location location) { @@ -439,7 +432,6 @@ public class Island implements DataObject { * @return true if allowed, false if not */ public boolean isAllowed(User user, Flag flag) { - //Bukkit.getLogger().info("DEBUG: " + flag.getID() + " user score = " + getRank(user) + " flag req = "+ this.getFlagReq(flag)); return getRank(user) >= getFlag(flag); } @@ -487,7 +479,6 @@ public class Island implements DataObject { * @return true if successful, otherwise false. */ public boolean removeFromBanList(UUID targetUUID) { - // TODO fire unban event members.remove(targetUUID); return true; } @@ -543,24 +534,11 @@ public class Island implements DataObject { } /** - * Locks/Unlocks the island. May be cancelled by - * {@link IslandLockEvent} or {@link IslandUnlockEvent}. + * Locks/Unlocks the island. * @param locked - the lock state to set */ public void setLocked(boolean locked){ - if(locked){ - // Lock the island - IslandBaseEvent event = IslandEvent.builder().island(this).reason(Reason.LOCK).build(); - if(!event.isCancelled()){ - this.locked = locked; - } - } else { - // Unlock the island - IslandBaseEvent event = IslandEvent.builder().island(this).reason(Reason.UNLOCK).build(); - if(!event.isCancelled()){ - this.locked = locked; - } - } + this.locked = locked; } /** diff --git a/src/main/java/us/tastybento/bskyblock/database/objects/Players.java b/src/main/java/us/tastybento/bskyblock/database/objects/Players.java index fa8028375..69c9253b2 100755 --- a/src/main/java/us/tastybento/bskyblock/database/objects/Players.java +++ b/src/main/java/us/tastybento/bskyblock/database/objects/Players.java @@ -10,6 +10,8 @@ import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; +import com.google.gson.annotations.Expose; + import us.tastybento.bskyblock.BSkyBlock; /** @@ -18,12 +20,19 @@ import us.tastybento.bskyblock.BSkyBlock; * @author tastybento */ public class Players implements DataObject { + @Expose private Map homeLocations = new HashMap<>(); + @Expose private String uniqueId; + @Expose private String playerName; + @Expose private int resetsLeft; + @Expose private String locale = ""; + @Expose private int deaths; + @Expose private Map kickedList = new HashMap<>(); /** @@ -64,15 +73,6 @@ public class Players implements DataObject { * @return Location of this home or null if not available */ public Location getHomeLocation(int number) { - /* - Bukkit.getLogger().info("DEBUG: getting home location " + number); - - Bukkit.getLogger().info("DEBUG: " + homeLocations.toString()); - for (Entry en : homeLocations.entrySet()) { - Bukkit.getLogger().info("DEBUG: " + en.getKey() + " ==> " + en.getValue()); - if (number == en.getKey()) - Bukkit.getLogger().info("DEBUG: key = number"); - }*/ return homeLocations.get(number); } @@ -101,7 +101,6 @@ public class Players implements DataObject { * @param homeLocations the homeLocations to set */ public void setHomeLocations(Map homeLocations) { - //Bukkit.getLogger().info("DEBUG: " + homeLocations.toString()); this.homeLocations = homeLocations; } @@ -166,7 +165,7 @@ public class Players implements DataObject { * Set the uuid for this player object * @param uuid - UUID */ - public void setPlayerUUID(final UUID uuid) { + public void setPlayerUUID(UUID uuid) { uniqueId = uuid.toString(); } diff --git a/src/main/java/us/tastybento/bskyblock/listeners/JoinLeaveListener.java b/src/main/java/us/tastybento/bskyblock/listeners/JoinLeaveListener.java index 566523a22..31cced427 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/JoinLeaveListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/JoinLeaveListener.java @@ -11,8 +11,8 @@ import org.bukkit.event.player.PlayerQuitEvent; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.Constants; import us.tastybento.bskyblock.api.commands.User; -import us.tastybento.bskyblock.database.managers.PlayersManager; import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.managers.PlayersManager; public class JoinLeaveListener implements Listener { diff --git a/src/main/java/us/tastybento/bskyblock/listeners/flags/AbstractFlagListener.java b/src/main/java/us/tastybento/bskyblock/listeners/flags/AbstractFlagListener.java index ca06e4dc9..db430e68b 100644 --- a/src/main/java/us/tastybento/bskyblock/listeners/flags/AbstractFlagListener.java +++ b/src/main/java/us/tastybento/bskyblock/listeners/flags/AbstractFlagListener.java @@ -18,8 +18,8 @@ import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.api.commands.User; import us.tastybento.bskyblock.api.flags.Flag; import us.tastybento.bskyblock.api.flags.Flag.Type; -import us.tastybento.bskyblock.database.managers.island.IslandsManager; import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.managers.IslandsManager; /** * Abstract class for flag listeners. Provides common code. diff --git a/src/main/java/us/tastybento/bskyblock/managers/FlagsManager.java b/src/main/java/us/tastybento/bskyblock/managers/FlagsManager.java index 11138b8c5..ae0ead79c 100644 --- a/src/main/java/us/tastybento/bskyblock/managers/FlagsManager.java +++ b/src/main/java/us/tastybento/bskyblock/managers/FlagsManager.java @@ -4,7 +4,6 @@ import java.util.ArrayList; import java.util.List; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.event.Listener; import us.tastybento.bskyblock.BSkyBlock; diff --git a/src/main/java/us/tastybento/bskyblock/database/managers/island/IslandsManager.java b/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java similarity index 99% rename from src/main/java/us/tastybento/bskyblock/database/managers/island/IslandsManager.java rename to src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java index cc3108d12..de71f93cb 100644 --- a/src/main/java/us/tastybento/bskyblock/database/managers/island/IslandsManager.java +++ b/src/main/java/us/tastybento/bskyblock/managers/IslandsManager.java @@ -1,4 +1,4 @@ -package us.tastybento.bskyblock.database.managers.island; +package us.tastybento.bskyblock.managers; import java.util.Collection; import java.util.HashSet; @@ -23,9 +23,10 @@ import org.bukkit.util.Vector; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.Constants; import us.tastybento.bskyblock.api.commands.User; +import us.tastybento.bskyblock.database.AbstractDatabaseHandler; import us.tastybento.bskyblock.database.BSBDatabase; -import us.tastybento.bskyblock.database.managers.AbstractDatabaseHandler; import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.managers.island.IslandCache; import us.tastybento.bskyblock.util.DeleteIslandChunks; import us.tastybento.bskyblock.util.Util; import us.tastybento.bskyblock.util.teleport.SafeTeleportBuilder; @@ -744,6 +745,7 @@ public class IslandsManager { } } catch (Exception e) { plugin.getLogger().severe("Could not load islands to cache! " + e.getMessage()); + e.printStackTrace(); } if (DEBUG) { plugin.getLogger().info("DEBUG: islands loaded"); diff --git a/src/main/java/us/tastybento/bskyblock/database/managers/PlayersManager.java b/src/main/java/us/tastybento/bskyblock/managers/PlayersManager.java similarity index 99% rename from src/main/java/us/tastybento/bskyblock/database/managers/PlayersManager.java rename to src/main/java/us/tastybento/bskyblock/managers/PlayersManager.java index a8b2eafb0..7f06d54e8 100644 --- a/src/main/java/us/tastybento/bskyblock/database/managers/PlayersManager.java +++ b/src/main/java/us/tastybento/bskyblock/managers/PlayersManager.java @@ -1,4 +1,4 @@ -package us.tastybento.bskyblock.database.managers; +package us.tastybento.bskyblock.managers; import java.beans.IntrospectionException; import java.lang.reflect.InvocationTargetException; @@ -19,13 +19,14 @@ import org.bukkit.entity.Player; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.Constants; import us.tastybento.bskyblock.api.commands.User; +import us.tastybento.bskyblock.database.AbstractDatabaseHandler; import us.tastybento.bskyblock.database.BSBDatabase; import us.tastybento.bskyblock.database.objects.Island; import us.tastybento.bskyblock.database.objects.Players; public class PlayersManager{ - private static final boolean DEBUG = true; + private static final boolean DEBUG = false; private BSkyBlock plugin; private BSBDatabase database; private AbstractDatabaseHandler handler; diff --git a/src/main/java/us/tastybento/bskyblock/managers/island/IslandCache.java b/src/main/java/us/tastybento/bskyblock/managers/island/IslandCache.java new file mode 100644 index 000000000..78910a191 --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/managers/island/IslandCache.java @@ -0,0 +1,392 @@ +package us.tastybento.bskyblock.managers.island; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; +import java.util.UUID; + +import org.bukkit.ChatColor; +import org.bukkit.Location; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.util.Util; + +public class IslandCache { + private static final boolean DEBUG2 = false; + private static final boolean DEBUG = false; + private BSkyBlock plugin = BSkyBlock.getInstance(); + private BiMap islandsByLocation; + /** + * Every player who is associated with an island is in this map. + */ + private HashMap islandsByUUID; + // 2D islandGrid of islands, x,z + private TreeMap> islandGrid = new TreeMap<>(); + + public IslandCache() { + islandsByLocation = HashBiMap.create(); + islandsByUUID = new HashMap<>(); + } + + /** + * Adds an island to the grid + * @param island + */ + public void addIsland(Island island) { + islandsByLocation.put(island.getCenter(), island); + if (DEBUG) { + plugin.getLogger().info("DEBUG: owner = " + island.getOwner()); + } + islandsByUUID.put(island.getOwner(), island); + if (DEBUG) { + plugin.getLogger().info("DEBUG: island has " + island.getMemberSet().size() + " members"); + } + for (UUID member: island.getMemberSet()) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: " + member); + } + islandsByUUID.put(member, island); + } + addToGrid(island); + } + + public void addPlayer(UUID playerUUID, Island teamIsland) { + islandsByUUID.put(playerUUID, teamIsland); + } + + /** + * Adds an island to the grid register + * @param newIsland + */ + private void addToGrid(Island newIsland) { + if (islandGrid.containsKey(newIsland.getMinX())) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: min x is in the grid :" + newIsland.getMinX()); + } + TreeMap zEntry = islandGrid.get(newIsland.getMinX()); + if (zEntry.containsKey(newIsland.getMinZ())) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: min z is in the grid :" + newIsland.getMinZ()); + } + // Island already exists + Island conflict = islandGrid.get(newIsland.getMinX()).get(newIsland.getMinZ()); + plugin.getLogger().warning("*** Duplicate or overlapping islands! ***"); + plugin.getLogger().warning( + "Island at (" + newIsland.getCenter().getBlockX() + ", " + newIsland.getCenter().getBlockZ() + ") conflicts with (" + + conflict.getCenter().getBlockX() + ", " + conflict.getCenter().getBlockZ() + ")"); + if (conflict.getOwner() != null) { + plugin.getLogger().warning("Accepted island is owned by " + plugin.getPlayers().getName(conflict.getOwner())); + plugin.getLogger().warning(conflict.getOwner().toString() + ".yml"); + } else { + plugin.getLogger().warning("Accepted island is unowned."); + } + if (newIsland.getOwner() != null) { + plugin.getLogger().warning("Denied island is owned by " + plugin.getPlayers().getName(newIsland.getOwner())); + plugin.getLogger().warning(newIsland.getOwner().toString() + ".yml"); + } else { + plugin.getLogger().warning("Denied island is unowned and was just found in the islands folder. Skipping it..."); + } + plugin.getLogger().warning("Recommend that the denied player file is deleted otherwise weird things can happen."); + return; + } else { + // Add island + if (DEBUG) { + plugin.getLogger().info("DEBUG: added island to grid at " + newIsland.getMinX() + "," + newIsland.getMinZ()); + } + zEntry.put(newIsland.getMinZ(), newIsland); + islandGrid.put(newIsland.getMinX(), zEntry); + // plugin.getLogger().info("Debug: " + newIsland.toString()); + } + } else { + // Add island + if (DEBUG) { + plugin.getLogger().info("DEBUG: added island to grid at " + newIsland.getMinX() + "," + newIsland.getMinZ()); + } + TreeMap zEntry = new TreeMap<>(); + zEntry.put(newIsland.getMinZ(), newIsland); + islandGrid.put(newIsland.getMinX(), zEntry); + } + } + + public void clear() { + islandsByLocation.clear(); + islandsByUUID.clear(); + } + + public Island createIsland(Island island) { + islandsByLocation.put(island.getCenter(), island); + if (island.getOwner() != null) { + islandsByUUID.put(island.getOwner(), island); + } + addToGrid(island); + return island; + } + + /** + * Create an island with no owner at location + * @param location - the location + */ + public Island createIsland(Location location){ + return createIsland(location, null); + } + + /** + * Create an island with owner. Note this does not create the schematic. It just creates the island data object. + * @param location - the location + * @param owner - the island owner UUID + */ + public Island createIsland(Location location, UUID owner){ + if (DEBUG) { + plugin.getLogger().info("DEBUG: adding island for " + owner + " at " + location); + } + Island island = new Island(location, owner, plugin.getSettings().getIslandProtectionRange()); + islandsByLocation.put(location, island); + if (owner != null) { + islandsByUUID.put(owner, island); + } + addToGrid(island); + return island; + } + + /** + * Deletes an island from the database. Does not remove blocks + * @param island + */ + public void deleteIslandFromCache(Island island) { + if (!islandsByLocation.remove(island.getCenter(), island)) { + plugin.getLogger().severe("Could not remove island from cache!"); + } + Iterator> it = islandsByUUID.entrySet().iterator(); + while (it.hasNext()) { + Entry en = it.next(); + if (en.getValue().equals(island)) { + it.remove(); + } + } + // Remove from grid + if (DEBUG) { + plugin.getLogger().info("DEBUG: deleting island at " + island.getCenter()); + } + if (island != null) { + int x = island.getMinX(); + int z = island.getMinZ(); + if (DEBUG) { + plugin.getLogger().info("DEBUG: x = " + x + " z = " + z); + } + if (islandGrid.containsKey(x)) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: x found"); + } + TreeMap zEntry = islandGrid.get(x); + if (zEntry.containsKey(z)) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: z found - deleting the island"); + } + // Island exists - delete it + zEntry.remove(z); + islandGrid.put(x, zEntry); + } else { + if (DEBUG) { + plugin.getLogger().info("DEBUG: could not find z"); + } + } + } + } + } + + public Island get(Location location) { + return islandsByLocation.get(location); + } + + public Island get(UUID uuid) { + return islandsByUUID.get(uuid); + } + + /** + * Gets the island for this player. If they are in a team, the team island is returned + * @param uuid - UUID + * @return Island + */ + public Island getIsland(UUID uuid){ + return islandsByUUID.get(uuid); + } + + /** + * Returns the island at the x,z location or null if there is none. + * This includes the full island space, not just the protected area. + * + * @param x - x coordinate + * @param z - z coordinate + * @return Island or null + */ + public Island getIslandAt(int x, int z) { + if (DEBUG2) { + plugin.getLogger().info("DEBUG: getting island at " + x + "," + z); + plugin.getLogger().info("DEBUG: island grid is " + islandGrid.size()); + } + Entry> en = islandGrid.floorEntry(x); + if (en != null) { + Entry ent = en.getValue().floorEntry(z); + if (ent != null) { + // Check if in the island range + Island island = ent.getValue(); + if (island.inIslandSpace(x, z)) { + if (DEBUG2) { + plugin.getLogger().info("DEBUG: In island space"); + } + return island; + } + if (DEBUG2) { + plugin.getLogger().info("DEBUG: not in island space"); + } + } + } + return null; + } + + /** + * Returns the island at the location or null if there is none. + * This includes the full island space, not just the protected area + * + * @param location - the location + * @return Island object + */ + public Island getIslandAt(Location location) { + if (location == null) { + //plugin.getLogger().info("DEBUG: location is null"); + return null; + } + // World check + if (!Util.inWorld(location)) { + //plugin.getLogger().info("DEBUG: not in right world"); + return null; + } + return getIslandAt(location.getBlockX(), location.getBlockZ()); + } + + /** + * Returns the player's island location. + * Returns an island location OR a team island location + * + * @param playerUUID - the player's UUID + * @return Location of player's island or null if one does not exist + */ + public Location getIslandLocation(UUID playerUUID) { + if (hasIsland(playerUUID)) { + return getIsland(playerUUID).getCenter(); + } + return null; + } + + /** + * Get name of the island owned by owner + * @param owner - the island owner + * @return Returns the name of owner's island, or the owner's name if there is none. + */ + public String getIslandName(UUID owner) { + String result = plugin.getPlayers().getName(owner); + if (islandsByUUID.containsKey(owner)) { + Island island = islandsByUUID.get(owner); + if (island.getName() != null && !island.getName().isEmpty()) { + result = island.getName(); + } + } + return ChatColor.translateAlternateColorCodes('&', result) + ChatColor.RESET; + } + + public Collection getIslands() { + return Collections.unmodifiableCollection(islandsByLocation.values()); + } + + public Set getMembers(UUID playerUUID) { + Island island = islandsByUUID.get(playerUUID); + if (island != null) { + return island.getMemberSet(); + } + return new HashSet<>(0); + } + + public UUID getTeamLeader(UUID playerUUID) { + if (islandsByUUID.containsKey(playerUUID)) { + return islandsByUUID.get(playerUUID).getOwner(); + } + return null; + } + + /** + * @param playerUUID - the player's UUID + * @return true if player has island and owns it + */ + public boolean hasIsland(UUID playerUUID) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: checking if " + playerUUID + " has an island"); + plugin.getLogger().info("DEBUG: islandsByUUID : " + islandsByUUID.toString()); + + if (!islandsByUUID.containsKey(playerUUID)) { + plugin.getLogger().info("DEBUG: player is not in islandsByUUID"); + } else { + plugin.getLogger().info("DEBUG: owner = " + islandsByUUID.get(playerUUID).getOwner()); + } + } + if (islandsByUUID.containsKey(playerUUID) && islandsByUUID.get(playerUUID).getOwner() != null) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: checking for equals"); + } + if (islandsByUUID.get(playerUUID).getOwner().equals(playerUUID)) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: has island"); + } + return true; + } + } + if (DEBUG) { + plugin.getLogger().info("DEBUG: doesn't have island"); + } + return false; + } + + public void removePlayer(UUID playerUUID) { + Island island = islandsByUUID.get(playerUUID); + if (island != null) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: island found"); + } + if (island.getOwner() != null && island.getOwner().equals(playerUUID)) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: player is the owner of this island"); + } + // Clear ownership and members + island.getMembers().clear(); + island.setOwner(null); + } + island.removeMember(playerUUID); + } + if (DEBUG) { + plugin.getLogger().info("DEBUG: removing reference to island by UUID"); + } + islandsByUUID.remove(playerUUID); + + } + + public void setIslandName(UUID owner, String name) { + if (islandsByUUID.containsKey(owner)) { + Island island = islandsByUUID.get(owner); + island.setName(name); + } + + } + + public int size() { + return islandsByLocation.size(); + } + +} diff --git a/src/main/java/us/tastybento/bskyblock/managers/island/NewIsland.java b/src/main/java/us/tastybento/bskyblock/managers/island/NewIsland.java new file mode 100644 index 000000000..c14349b82 --- /dev/null +++ b/src/main/java/us/tastybento/bskyblock/managers/island/NewIsland.java @@ -0,0 +1,252 @@ +package us.tastybento.bskyblock.managers.island; + +import java.io.IOException; +import java.util.UUID; + +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.api.events.IslandBaseEvent; +import us.tastybento.bskyblock.api.events.island.IslandEvent; +import us.tastybento.bskyblock.api.events.island.IslandEvent.Reason; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.island.builders.IslandBuilder; +import us.tastybento.bskyblock.island.builders.IslandBuilder.IslandType; + +/** + * Create and paste a new island + * @author tastybento + * + */ +public class NewIsland { + private static final boolean DEBUG = false; + private BSkyBlock plugin; + private Island island; + private final Player player; + private final Reason reason; + + private NewIsland(Island oldIsland, Player player, Reason reason) { + super(); + plugin = BSkyBlock.getInstance(); + this.player = player; + this.reason = reason; + newIsland(); + if (oldIsland != null) { + // Delete the old island + plugin.getIslands().deleteIsland(oldIsland, true); + } + } + + /** + * @return the island that was created + */ + public Island getIsland() { + return island; + } + + /** + * Start building a new island + * @return New island builder object + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Build a new island for a player using a schematic + * @author tastybento + * + */ + public static class Builder { + private Island oldIsland; + private Player player; + private Reason reason; + + public Builder oldIsland(Island oldIsland) { + this.oldIsland = oldIsland; + return this; + } + + + public Builder player(Player player) { + this.player = player; + return this; + } + + public Builder reason(Reason reason) { + this.reason = reason; + return this; + } + + public Island build() throws IOException { + if (player != null) { + NewIsland newIsland = new NewIsland(oldIsland, player, reason); + return newIsland.getIsland(); + } + throw new IOException("Insufficient parameters. Must have a schematic and a player"); + } + } + + /** + * Makes an island. + */ + public void newIsland() { + if (DEBUG) { + plugin.getLogger().info("DEBUG: new island"); + } + //long time = System.nanoTime(); + final UUID playerUUID = player.getUniqueId(); + /* + boolean firstTime = false; + if (!plugin.getPlayers().hasIsland(playerUUID)) { + firstTime = true; + }*/ + if (DEBUG) { + plugin.getLogger().info("DEBUG: finding island location"); + } + Location next = getNextIsland(); + if (DEBUG) { + plugin.getLogger().info("DEBUG: found " + next); + } + + // Add to the grid + island = plugin.getIslands().createIsland(next, playerUUID); + // Save the player so that if the server is reset weird things won't happen + //plugin.getPlayers().save(true); + //plugin.getIslands().save(true); + + // Clear any old home locations (they should be clear, but just in case) + plugin.getPlayers().clearHomeLocations(playerUUID); + + // Set the biome + //BiomesPanel.setIslandBiome(next, schematic.getBiome()); + // Set home loction + plugin.getPlayers().setHomeLocation(playerUUID, next, 1); + + // Fire event + if (DEBUG) { + plugin.getLogger().info("DEBUG: firing event"); + } + IslandBaseEvent event = IslandEvent.builder() + .involvedPlayer(player.getUniqueId()) + .reason(reason) + .island(island) + .location(island.getCenter()) + .build(); + if (DEBUG) { + plugin.getLogger().info("DEBUG: event cancelled status = " + event.isCancelled()); + } + if (!event.isCancelled()) { + // Create island + new IslandBuilder(plugin, island) + .setPlayer(player) + .setChestItems(plugin.getSettings().getChestItems()) + .setType(IslandType.ISLAND) + .build(); + if (plugin.getSettings().isNetherGenerate() && plugin.getSettings().isNetherIslands() && plugin.getIslandWorldManager().getNetherWorld() != null) { + new IslandBuilder(plugin,island) + .setPlayer(player) + .setChestItems(plugin.getSettings().getChestItems()) + .setType(IslandType.NETHER) + .build(); + } + if (plugin.getSettings().isEndGenerate() && plugin.getSettings().isEndIslands() && plugin.getIslandWorldManager().getEndWorld() != null) { + new IslandBuilder(plugin,island) + .setPlayer(player) + .setChestItems(plugin.getSettings().getChestItems()) + .setType(IslandType.END) + .build(); + } + // Teleport player to their island + plugin.getIslands().homeTeleport(player); + // Fire exit event + Reason reasonDone = Reason.CREATED; + switch (reason) { + case CREATE: + reasonDone = Reason.CREATED; + break; + case RESET: + reasonDone = Reason.RESETTED; + break; + default: + break; + } + IslandEvent.builder() + .involvedPlayer(player.getUniqueId()) + .reason(reasonDone) + .island(island) + .location(island.getCenter()) + .build(); + } + } + + /** + * Get the location of next free island spot + * @return Location of island spot + */ + private Location getNextIsland() { + Location last = plugin.getIslands().getLast(); + + if (DEBUG) { + plugin.getLogger().info("DEBUG: last = " + last); + // Find the next free spot + } + + if (last == null) { + last = new Location(plugin.getIslandWorldManager().getIslandWorld(), plugin.getSettings().getIslandXOffset() + plugin.getSettings().getIslandStartX(), + plugin.getSettings().getIslandHeight(), plugin.getSettings().getIslandZOffset() + plugin.getSettings().getIslandStartZ()); + } + Location next = last.clone(); + if (DEBUG) { + plugin.getLogger().info("DEBUG: last 2 = " + last); + } + while (plugin.getIslands().isIsland(next)) { + if (DEBUG) { + plugin.getLogger().info("DEBUG: getting next loc"); + } + next = nextGridLocation(next); + } + // Make the last next, last + last = next.clone(); + if (DEBUG) { + plugin.getLogger().info("DEBUG: last 3 = " + last); + } + return next; + } + + /** + * Finds the next free island spot based off the last known island Uses + * island_distance setting from the config file Builds up in a grid fashion + * + * @param lastIsland + * @return Location of next free island + */ + private Location nextGridLocation(final Location lastIsland) { + int x = lastIsland.getBlockX(); + int z = lastIsland.getBlockZ(); + Location nextPos = lastIsland; + if (x < z) { + if (-1 * x < z) { + nextPos.setX(nextPos.getX() + plugin.getSettings().getIslandDistance()*2); + return nextPos; + } + nextPos.setZ(nextPos.getZ() + plugin.getSettings().getIslandDistance()*2); + return nextPos; + } + if (x > z) { + if (-1 * x >= z) { + nextPos.setX(nextPos.getX() - plugin.getSettings().getIslandDistance()*2); + return nextPos; + } + nextPos.setZ(nextPos.getZ() - plugin.getSettings().getIslandDistance()*2); + return nextPos; + } + if (x <= 0) { + nextPos.setZ(nextPos.getZ() + plugin.getSettings().getIslandDistance()*2); + return nextPos; + } + nextPos.setZ(nextPos.getZ() - plugin.getSettings().getIslandDistance()*2); + return nextPos; + } +} diff --git a/src/test/java/bskyblock/TestBSkyBlock.java b/src/test/java/bskyblock/TestBSkyBlock.java index 5739d38ed..73f346b4c 100644 --- a/src/test/java/bskyblock/TestBSkyBlock.java +++ b/src/test/java/bskyblock/TestBSkyBlock.java @@ -56,12 +56,12 @@ import us.tastybento.bskyblock.api.events.IslandBaseEvent; import us.tastybento.bskyblock.api.events.team.TeamEvent; import us.tastybento.bskyblock.api.flags.Flag; import us.tastybento.bskyblock.api.flags.FlagBuilder; -import us.tastybento.bskyblock.database.managers.island.IslandsManager; import us.tastybento.bskyblock.database.objects.Island; import us.tastybento.bskyblock.generators.IslandWorld; import us.tastybento.bskyblock.listeners.flags.AbstractFlagListener; import us.tastybento.bskyblock.lists.Flags; import us.tastybento.bskyblock.managers.FlagsManager; +import us.tastybento.bskyblock.managers.IslandsManager; import us.tastybento.bskyblock.managers.RanksManager; import us.tastybento.bskyblock.util.Util; diff --git a/src/test/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandlerTest.java b/src/test/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandlerTest.java index 63449b8de..6396dd63d 100644 --- a/src/test/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandlerTest.java +++ b/src/test/java/us/tastybento/bskyblock/database/mysql/MySQLDatabaseHandlerTest.java @@ -1,57 +1,81 @@ -/** - * - */ package us.tastybento.bskyblock.database.mysql; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.beans.IntrospectionException; -import java.lang.reflect.InvocationTargetException; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; -import java.sql.SQLException; import java.sql.Statement; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; import java.util.logging.Logger; import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.Server; import org.bukkit.World; +import org.bukkit.inventory.ItemFactory; +import org.bukkit.plugin.PluginManager; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.Mockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; +import org.powermock.reflect.Whitebox; import us.tastybento.bskyblock.BSkyBlock; +import us.tastybento.bskyblock.Settings; +import us.tastybento.bskyblock.api.flags.Flag; +import us.tastybento.bskyblock.database.mysql.MySQLDatabaseConnecter; +import us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandler; +import us.tastybento.bskyblock.database.objects.Island; +import us.tastybento.bskyblock.database.objects.Players; +import us.tastybento.bskyblock.lists.Flags; -/** - * @author ben - * - */ +@RunWith(PowerMockRunner.class) +@PrepareForTest( { BSkyBlock.class }) public class MySQLDatabaseHandlerTest { - - private static MySQLDatabaseHandler handler; - private static MySQLDatabaseHandlerTestDataObject instance; + + private static MySQLDatabaseHandler handler; + private static Island instance; private static String UNIQUE_ID = "xyz"; + private static MySQLDatabaseConnecter dbConn; + private static World world; + @Mock + static BSkyBlock plugin = mock(BSkyBlock.class); + - /** - * @throws java.lang.Exception - */ @BeforeClass - public static void setUp() throws Exception { + public static void setUpBeforeClass() throws Exception { Server server = mock(Server.class); - World world = mock(World.class); + world = mock(World.class); when(server.getLogger()).thenReturn(Logger.getAnonymousLogger()); when(server.getWorld("world")).thenReturn(world); when(server.getVersion()).thenReturn("BSB_Mocking"); + + PluginManager pluginManager = mock(PluginManager.class); + when(server.getPluginManager()).thenReturn(pluginManager); + + ItemFactory itemFactory = mock(ItemFactory.class); + when(server.getItemFactory()).thenReturn(itemFactory); + Bukkit.setServer(server); - BSkyBlock plugin = mock(BSkyBlock.class); when(Bukkit.getLogger()).thenReturn(Logger.getAnonymousLogger()); - MySQLDatabaseConnecter dbConn = mock(MySQLDatabaseConnecter.class); + + Whitebox.setInternalState(BSkyBlock.class, "instance", plugin); + + Settings settings = mock(Settings.class); + + when(plugin.getSettings()).thenReturn(settings); + when(settings.getDeathsMax()).thenReturn(10); + + when(Bukkit.getLogger()).thenReturn(Logger.getAnonymousLogger()); + dbConn = mock(MySQLDatabaseConnecter.class); Connection connection = mock(Connection.class); when(dbConn.createConnection()).thenReturn(connection); PreparedStatement ps = mock(PreparedStatement.class); @@ -61,152 +85,74 @@ public class MySQLDatabaseHandlerTest { ResultSet rs = mock(ResultSet.class); when(ps.executeQuery()).thenReturn(rs); when(statement.executeQuery(Mockito.anyString())).thenReturn(rs); - instance = new MySQLDatabaseHandlerTestDataObject(); + instance = new Island(); instance.setUniqueId(UNIQUE_ID); - handler = new MySQLDatabaseHandler<>(plugin, MySQLDatabaseHandlerTestDataObject.class, dbConn); + handler = new MySQLDatabaseHandler<>(plugin, Island.class, dbConn); } - - /** - * Test method for {@link us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandler#getColumns(boolean)}. - */ - @Test - public void testGetColumns() { - // This should be a list of 20 ?'s which related to the 20 - assertEquals("?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?", handler.getColumns(true)); - assertEquals("`uniqueId`, `center`, `range`, `minX`, `minZ`, `minProtectedX`, `minProtectedZ`, " + - "`protectionRange`, `world`, `name`, `createdDate`, `updatedDate`, `owner`, `members`, `locked`, " + - "`spawn`, `purgeProtected`, `flags`, `levelHandicap`, `spawnPoint`", - handler.getColumns(false)); - } - - /** - * Test method for {@link us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandler#createSelectQuery()}. - */ - @Test - public void testCreateSelectQuery() { - assertEquals("SELECT `uniqueId`, `center`, `range`, `minX`, `minZ`, `minProtectedX`, " + - "`minProtectedZ`, `protectionRange`, `world`, `name`, `createdDate`, `updatedDate`, " + - "`owner`, `members`, `locked`, `spawn`, `purgeProtected`, `flags`, `levelHandicap`, " + - "`spawnPoint` FROM `us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandlerTestDataObject`", - handler.createSelectQuery()); - } - - /** - * Test method for {@link us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandler#createInsertQuery()}. - */ - @Test - public void testCreateInsertQuery() { - assertEquals("REPLACE INTO `us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandlerTestDataObject`(`uniqueId`, " + - "`center`, `range`, `minX`, `minZ`, `minProtectedX`, `minProtectedZ`, `protectionRange`, " + - "`world`, `name`, `createdDate`, `updatedDate`, `owner`, `members`, `locked`, `spawn`, " + - "`purgeProtected`, `flags`, `levelHandicap`, `spawnPoint`) " + - "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", - handler.createInsertQuery()); - } - - /** - * Test method for {@link us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandler#createDeleteQuery()}. - */ - @Test - public void testCreateDeleteQuery() { - assertEquals("DELETE FROM [table_name] WHERE uniqueId = ?", handler.createDeleteQuery()); - } - - /** - * Test method for {@link us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandler#loadObjects()}. - */ - @Test - public void testLoadObjects() { - try { - java.util.List result = handler.loadObjects(); - System.out.println("Size of result " + result.size()); - } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException - | InvocationTargetException | ClassNotFoundException | SQLException | IntrospectionException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - /** - * Test method for {@link us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandler#loadObject(java.lang.String)}. - */ - @Test - public void testLoadObject() { - try { - MySQLDatabaseHandlerTestDataObject obj = (MySQLDatabaseHandlerTestDataObject) handler.loadObject(UNIQUE_ID); - assertNull(obj); - } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException - | SecurityException | ClassNotFoundException | IntrospectionException | SQLException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } - - /** - * Test method for {@link us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandler#saveObject(java.lang.Object)}. - */ @Test public void testSaveObject() { - try { - handler.saveObject(instance); - } catch (SecurityException | IllegalArgumentException | InstantiationException | IllegalAccessException - | InvocationTargetException | NoSuchMethodException | SQLException | IntrospectionException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } + handler.saveObject(instance); + BSkyBlock plugin = mock(BSkyBlock.class); + Settings settings = mock(Settings.class); + when(plugin.getSettings()).thenReturn(settings); + when(settings.getDeathsMax()).thenReturn(10); + Players players = new Players(); + players.setUniqueId(UUID.randomUUID().toString()); + players.setDeaths(23); + Location location = mock(Location.class); + Mockito.when(location.getWorld()).thenReturn(world); + Mockito.when(location.getBlockX()).thenReturn(0); + Mockito.when(location.getBlockY()).thenReturn(0); + Mockito.when(location.getBlockZ()).thenReturn(0); - /** - * Test method for {@link us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandler#deleteObject(java.lang.Object)}. - */ - @Test - public void testDeleteObject() { - try { - handler.deleteObject(instance); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException - | SecurityException | IntrospectionException | SQLException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } + players.setHomeLocation(location); + players.setHomeLocation(location, 1); + players.setHomeLocation(location, 2); + Map map = new HashMap<>(); + map.put(location, 324L); + players.setKickedList(map); + players.setLocale("sdfsd"); + players.setPlayerName("name"); + players.setPlayerUUID(UUID.randomUUID()); + players.setResetsLeft(3); + - /** - * Test method for {@link us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandler#objectExists(java.lang.String)}. - */ - @Test - public void testObjectExits() { - // This right now is not tested properly - assertFalse(handler.objectExists(UNIQUE_ID)); - } - - /** - * Test method for {@link us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandler#saveSettings(java.lang.Object)}. - */ - @Test - public void testSaveSettings() { - try { - handler.saveSettings(instance); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException - | IntrospectionException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + MySQLDatabaseHandler h = new MySQLDatabaseHandler<>(plugin, Players.class, dbConn); + h.saveObject(players); + + Island island = new Island(); + island.setUniqueId(UNIQUE_ID); + island.setCenter(location); + Map flags = new HashMap<>(); + for (Flag fl : Flags.values()) { + flags.put(fl, 100); } - } - - /** - * Test method for {@link us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandler#loadSettings(java.lang.String, java.lang.Object)}. - */ - @Test - public void testLoadSettings() { - try { - handler.loadSettings(UNIQUE_ID, instance); - } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException - | ClassNotFoundException | IntrospectionException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + island.setFlags(flags); + island.setLevelHandicap(10); + island.setLocked(true); + Map members = new HashMap<>(); + for (int i = 0; i < 100; i++) { + members.put(UUID.randomUUID(), i); } + island.setMembers(members); + island.setMinProtectedX(-100); + island.setMinProtectedZ(-300); + island.setMinX(-121); + island.setMinZ(-23423); + island.setName("ytasdgfsdfg"); + island.setOwner(UUID.randomUUID()); + island.setProtectionRange(100); + island.setPurgeProtected(true); + island.setRange(100); + island.setSpawn(true); + island.setSpawnPoint(location); + island.setWorld(world); + + MySQLDatabaseHandler ih = new MySQLDatabaseHandler<>(plugin, Island.class, dbConn); + ih.saveObject(island); + } } diff --git a/src/test/java/us/tastybento/bskyblock/database/mysqljson/Players.java b/src/test/java/us/tastybento/bskyblock/database/mysql/Players.java similarity index 100% rename from src/test/java/us/tastybento/bskyblock/database/mysqljson/Players.java rename to src/test/java/us/tastybento/bskyblock/database/mysql/Players.java diff --git a/src/test/java/us/tastybento/bskyblock/database/mysqljson/MySQLDatabaseHandlerJTest.java b/src/test/java/us/tastybento/bskyblock/database/mysqljson/MySQLDatabaseHandlerJTest.java deleted file mode 100644 index c4be2f900..000000000 --- a/src/test/java/us/tastybento/bskyblock/database/mysqljson/MySQLDatabaseHandlerJTest.java +++ /dev/null @@ -1,109 +0,0 @@ -package us.tastybento.bskyblock.database.mysqljson; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.Statement; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.logging.Logger; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Server; -import org.bukkit.World; -import org.bukkit.inventory.ItemFactory; -import org.bukkit.plugin.PluginManager; -import org.junit.BeforeClass; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mockito; -import org.powermock.modules.junit4.PowerMockRunner; - -import us.tastybento.bskyblock.BSkyBlock; -import us.tastybento.bskyblock.Settings; -import us.tastybento.bskyblock.database.mysql.MySQLDatabaseConnecter; -import us.tastybento.bskyblock.database.mysql.MySQLDatabaseHandlerTestDataObject; - -@RunWith(PowerMockRunner.class) -public class MySQLDatabaseHandlerJTest { - - private static MySQLDatabaseHandlerJ handler; - private static MySQLDatabaseHandlerTestDataObject instance; - private static String UNIQUE_ID = "xyz"; - private static MySQLDatabaseConnecter dbConn; - private static World world; - - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - Server server = mock(Server.class); - world = mock(World.class); - when(server.getLogger()).thenReturn(Logger.getAnonymousLogger()); - when(server.getWorld("world")).thenReturn(world); - when(server.getVersion()).thenReturn("BSB_Mocking"); - - PluginManager pluginManager = mock(PluginManager.class); - when(server.getPluginManager()).thenReturn(pluginManager); - - ItemFactory itemFactory = mock(ItemFactory.class); - when(server.getItemFactory()).thenReturn(itemFactory); - - Bukkit.setServer(server); - - when(Bukkit.getLogger()).thenReturn(Logger.getAnonymousLogger()); - - BSkyBlock plugin = mock(BSkyBlock.class); - when(Bukkit.getLogger()).thenReturn(Logger.getAnonymousLogger()); - dbConn = mock(MySQLDatabaseConnecter.class); - Connection connection = mock(Connection.class); - when(dbConn.createConnection()).thenReturn(connection); - PreparedStatement ps = mock(PreparedStatement.class); - when(connection.prepareStatement(Mockito.anyString())).thenReturn(ps); - Statement statement = mock(Statement.class); - when(connection.createStatement()).thenReturn(statement); - ResultSet rs = mock(ResultSet.class); - when(ps.executeQuery()).thenReturn(rs); - when(statement.executeQuery(Mockito.anyString())).thenReturn(rs); - instance = new MySQLDatabaseHandlerTestDataObject(); - instance.setUniqueId(UNIQUE_ID); - handler = new MySQLDatabaseHandlerJ<>(plugin, MySQLDatabaseHandlerTestDataObject.class, dbConn); - - } - - @Test - public void testSaveObject() { - handler.saveObject(instance); - BSkyBlock plugin = mock(BSkyBlock.class); - Settings settings = mock(Settings.class); - when(plugin.getSettings()).thenReturn(settings); - when(settings.getDeathsMax()).thenReturn(10); - Players players = new Players(); - players.setUniqueId(UUID.randomUUID().toString()); - players.setDeaths(23); - Location location = mock(Location.class); - Mockito.when(location.getWorld()).thenReturn(world); - Mockito.when(location.getBlockX()).thenReturn(0); - Mockito.when(location.getBlockY()).thenReturn(0); - Mockito.when(location.getBlockZ()).thenReturn(0); - - players.setHomeLocation(location); - players.setHomeLocation(location, 1); - players.setHomeLocation(location, 2); - Map map = new HashMap<>(); - map.put(location, 324L); - players.setKickedList(map); - players.setLocale("sdfsd"); - players.setPlayerName("name"); - players.setPlayerUUID(UUID.randomUUID()); - players.setResetsLeft(3); - - MySQLDatabaseHandlerJ h = new MySQLDatabaseHandlerJ<>(plugin, Players.class, dbConn); - h.saveObject(players); - } - -} diff --git a/src/test/java/us/tastybento/bskyblock/listeners/flags/FireListenerTest.java b/src/test/java/us/tastybento/bskyblock/listeners/flags/FireListenerTest.java index aab29e438..d34216cad 100644 --- a/src/test/java/us/tastybento/bskyblock/listeners/flags/FireListenerTest.java +++ b/src/test/java/us/tastybento/bskyblock/listeners/flags/FireListenerTest.java @@ -42,11 +42,11 @@ import org.powermock.modules.junit4.PowerMockRunner; import us.tastybento.bskyblock.BSkyBlock; import us.tastybento.bskyblock.Settings; import us.tastybento.bskyblock.api.commands.User; -import us.tastybento.bskyblock.database.managers.island.IslandsManager; import us.tastybento.bskyblock.database.objects.Island; import us.tastybento.bskyblock.generators.IslandWorld; import us.tastybento.bskyblock.lists.Flags; import us.tastybento.bskyblock.managers.FlagsManager; +import us.tastybento.bskyblock.managers.IslandsManager; import us.tastybento.bskyblock.managers.LocalesManager; @RunWith(PowerMockRunner.class) diff --git a/src/test/java/us/tastybento/bskyblock/listeners/flags/MobSpawnListenerTest.java b/src/test/java/us/tastybento/bskyblock/listeners/flags/MobSpawnListenerTest.java index 0c72480ac..51b6be670 100644 --- a/src/test/java/us/tastybento/bskyblock/listeners/flags/MobSpawnListenerTest.java +++ b/src/test/java/us/tastybento/bskyblock/listeners/flags/MobSpawnListenerTest.java @@ -33,11 +33,11 @@ import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import us.tastybento.bskyblock.BSkyBlock; -import us.tastybento.bskyblock.database.managers.island.IslandsManager; import us.tastybento.bskyblock.database.objects.Island; import us.tastybento.bskyblock.generators.IslandWorld; import us.tastybento.bskyblock.lists.Flags; import us.tastybento.bskyblock.managers.FlagsManager; +import us.tastybento.bskyblock.managers.IslandsManager; @RunWith(PowerMockRunner.class) @PrepareForTest( { Flags.class })