Database transition (#662)

- JSON is now the default database type
- JSON database files are now pretty-printed
- It is now possible to migrate from a database type to another through the use of a command and specific transition database types
- It is recommended to move from YAML to JSON.

= Commits breakdown =

* Proposal to make JSON the default database and retire YAML.

* Make JSON file format easier to read.

* Fix tests.

* Adds a hybrid Yaml2Json database type.

This database always tries to use JSON if it is available. If a YAML
file is found, it will be loaded and replaced with a JSON file.

* Move to generic database transition code

* Better comments

* Adds transitional database options so admins can choose.

Adds Yaml2MySQL option and changes config.yml to add instructions.

* Enables full database migration between databases.

Adds /bbox migrate command.

Adds a number of transition databases. DB starts transition  when the
server boots up and will migrate organically. The admin can force an
immediate update using the bbox migrate command.

This operation requires an API breaking change: Addons that use the
Config API must now implement ConfigObject in their config class instead
of DataObject. This is to differentiate YAML config classes from YAML
database classes. If a class is already implements WorldSettings
(GameModeAddons), then no change is required because WorldSettings
implements ConfigObject now. If an old addon is used that does not
implement ConfigObject, BentoBox will not load.

* Added null check to YAML deletion

* Removed the 2YAML transition dbs because YAML is deprecated.

YAML does not support some data structures so conversion could corrupt
data.

* Fixed some javadoc and added missing DatabaseType#JSON2MARIADB

* Renamed package database/transitiondb to database/transition
This commit is contained in:
tastybento 2019-05-08 12:15:22 -07:00 committed by Florian CUNY
parent 0f4baad703
commit 180b88544a
23 changed files with 435 additions and 48 deletions

View File

@ -2,9 +2,9 @@ package world.bentobox.bentobox;
import world.bentobox.bentobox.api.configuration.ConfigComment;
import world.bentobox.bentobox.api.configuration.ConfigEntry;
import world.bentobox.bentobox.api.configuration.ConfigObject;
import world.bentobox.bentobox.api.configuration.StoreAt;
import world.bentobox.bentobox.database.DatabaseSetup.DatabaseType;
import world.bentobox.bentobox.database.objects.DataObject;
import world.bentobox.bentobox.managers.RanksManager;
import java.util.HashMap;
@ -21,7 +21,7 @@ import java.util.Set;
@ConfigComment("This config file is dynamic and is updated right after BentoBox loaded its settings from it.")
@ConfigComment("You can edit it while the server is online and you can do '/bbox reload' to take the changes into account.")
@ConfigComment("However, it is a better practice to edit this file while the server is offline.")
public class Settings implements DataObject {
public class Settings implements ConfigObject {
// ---------------------------------------------
@ -38,13 +38,18 @@ public class Settings implements DataObject {
private boolean useEconomy = true;
// Database
@ConfigComment("YAML, JSON, MYSQL, MARIADB (10.2.3+), MONGODB.")
@ConfigComment("YAML and JSON are both file-based databases.")
@ConfigComment("JSON, MYSQL, MARIADB (10.2.3+), MONGODB, and YAML(deprecated).")
@ConfigComment("Transition database options are:")
@ConfigComment(" YAML2JSON, YAML2MARIADB, YAML2MYSQL")
@ConfigComment(" JSON2MARIADB, JSON2MYSQL, MYSQL2JSON")
@ConfigComment("If you need others, please make a feature request.")
@ConfigComment("Transition options enable migration from one database type to another. Use /bbox migrate.")
@ConfigComment("YAML and JSON are file-based databases.")
@ConfigComment("MYSQL might not work with all implementations: if available, use a dedicated database type (e.g. MARIADB).")
@ConfigComment("If you use MONGODB, you must also run the BSBMongo plugin (not addon).")
@ConfigComment("See https://github.com/tastybento/bsbMongo/releases/.")
@ConfigEntry(path = "general.database.type", needsReset = true)
private DatabaseType databaseType = DatabaseType.YAML;
@ConfigEntry(path = "general.database.type")
private DatabaseType databaseType = DatabaseType.JSON;
@ConfigEntry(path = "general.database.host")
private String databaseHost = "localhost";
@ -190,10 +195,6 @@ public class Settings implements DataObject {
@ConfigEntry(path = "web.updater.check-updates.addons", since = "1.3.0", hidden = true)
private boolean checkAddonsUpdates = true;
//---------------------------------------------------------------------------------------/
@ConfigComment("These settings should not be edited")
private String uniqueId = "config";
//---------------------------------------------------------------------------------------/
// Getters and setters
@ -435,22 +436,6 @@ public class Settings implements DataObject {
this.autoOwnershipTransferIgnoreRanks = autoOwnershipTransferIgnoreRanks;
}
/**
* @return the uniqueId
*/
@Override
public String getUniqueId() {
return uniqueId;
}
/**
* @param uniqueId the uniqueId to set
*/
@Override
public void setUniqueId(String uniqueId) {
this.uniqueId = uniqueId;
}
public boolean isLogCleanSuperFlatChunks() {
return logCleanSuperFlatChunks;
}

View File

@ -0,0 +1,31 @@
package world.bentobox.bentobox.api.configuration;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.database.objects.DataObject;
/**
* Config object for YAML objects
* @author tastybento
* @since 1.5.0
*/
public interface ConfigObject extends DataObject {
@Override
default BentoBox getPlugin() {
return BentoBox.getInstance();
}
/**
* @return the uniqueId
*/
@Override
default String getUniqueId() {
return "config";
}
/**
* @param uniqueId - unique ID the uniqueId to set
*/
@Override
default void setUniqueId(String uniqueId) {}
}

View File

@ -16,7 +16,7 @@ import world.bentobox.bentobox.api.flags.Flag;
* Depending on your implementation, you may need to add setters.
* @author tastybento
*/
public interface WorldSettings {
public interface WorldSettings extends ConfigObject {
/**
* Get the default game mode for this game world, e.g. SURVIVAL

View File

@ -23,6 +23,10 @@ public class BentoBoxCommand extends CompositeCommand {
new BentoBoxCatalogCommand(this);
new BentoBoxReloadCommand(this);
new BentoBoxLocaleCommand(this);
// Database names with a 2 in them are migration databases
if (getPlugin().getSettings().getDatabaseType().name().contains("2")) {
new BentoBoxMigrateCommand(this);
}
}
@Override

View File

@ -0,0 +1,55 @@
package world.bentobox.bentobox.commands;
import java.util.List;
import world.bentobox.bentobox.api.commands.CompositeCommand;
import world.bentobox.bentobox.api.commands.ConfirmableCommand;
import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.Database;
import world.bentobox.bentobox.database.objects.Names;
import world.bentobox.bentobox.database.objects.Players;
/**
* Forces migration from one database to another
*
* @author tastybento
* @since 1.5.0
*/
public class BentoBoxMigrateCommand extends ConfirmableCommand {
/**
* Reloads settings, addons and localization command
* @param parent command parent
*/
public BentoBoxMigrateCommand(CompositeCommand parent) {
super(parent, "migrate");
}
@Override
public void setup() {
setPermission("admin.migrate");
setDescription("commands.bentobox.migrate.description");
}
@Override
public boolean execute(User user, String label, List<String> args) {
this.askConfirmation(user, () -> {
// Migrate BentoBox data
user.sendMessage("commands.bentobox.migrate.players");
new Database<>(getPlugin(), Players.class).loadObjects();
user.sendMessage("commands.bentobox.migrate.migrated");
user.sendMessage("commands.bentobox.migrate.names");
new Database<>(getPlugin(), Names.class).loadObjects();
user.sendMessage("commands.bentobox.migrate.migrated");
// Migrate addons data
user.sendMessage("commands.bentobox.migrate.addons");
getPlugin().getAddonsManager().getDataObjects().forEach(t -> {
user.sendMessage("commands.bentobox.migrate.class", TextVariables.DESCRIPTION, t.getCanonicalName());
new Database<>(getPlugin(), t).loadObjects();
user.sendMessage("commands.bentobox.migrate.migrated");
});
});
return true;
}
}

View File

@ -77,6 +77,8 @@ public abstract class AbstractDatabaseHandler<T> {
this.dataObject = type;
}
protected AbstractDatabaseHandler() {}
/**
* Loads all the records in this table and returns a list of them
* @return list of <T>

View File

@ -5,10 +5,18 @@ import world.bentobox.bentobox.database.json.JSONDatabase;
import world.bentobox.bentobox.database.mariadb.MariaDBDatabase;
import world.bentobox.bentobox.database.mongodb.MongoDBDatabase;
import world.bentobox.bentobox.database.mysql.MySQLDatabase;
import world.bentobox.bentobox.database.transition.Json2MariaDBDatabase;
import world.bentobox.bentobox.database.transition.Json2MySQLDatabase;
import world.bentobox.bentobox.database.transition.MySQL2JsonDatabase;
import world.bentobox.bentobox.database.transition.Yaml2JsonDatabase;
import world.bentobox.bentobox.database.transition.Yaml2MariaDBDatabase;
import world.bentobox.bentobox.database.transition.Yaml2MySQLDatabase;
import world.bentobox.bentobox.database.yaml.YamlDatabase;
import java.util.Arrays;
/**
* @author Poslovitch
* @author Poslovitch, tastybento
*/
public interface DatabaseSetup {
@ -20,23 +28,60 @@ public interface DatabaseSetup {
*/
static DatabaseSetup getDatabase() {
BentoBox plugin = BentoBox.getInstance();
for(DatabaseType type : DatabaseType.values()){
if(type == plugin.getSettings().getDatabaseType()) {
return type.database;
}
}
return DatabaseType.YAML.database;
return Arrays.stream(DatabaseType.values())
.filter(plugin.getSettings().getDatabaseType()::equals)
.findFirst()
.map(t -> t.database)
.orElse(DatabaseType.JSON.database);
}
/**
* Database types
*
*/
enum DatabaseType {
YAML(new YamlDatabase()),
/**
* Transition database, from YAML to JSON
* @since 1.5.0
*/
YAML2JSON(new Yaml2JsonDatabase()),
/**
* Transition database, from YAML to MySQL
* @since 1.5.0
*/
YAML2MYSQL(new Yaml2MySQLDatabase()),
/**
* Transition database, from YAML to MySQL (MariaDB)
* @since 1.5.0
*/
YAML2MARIADB(new Yaml2MariaDBDatabase()),
JSON(new JSONDatabase()),
/**
* Transition database, from JSON to MySQL
* @since 1.5.0
*/
JSON2MYSQL(new Json2MySQLDatabase()),
/**
* Transition database, from JSON to MySQL (MariaDB)
* @since 1.5.0
*/
JSON2MARIADB(new Json2MariaDBDatabase()),
MYSQL(new MySQLDatabase()),
/**
* Transition database, from MySQL to JSON
* @since 1.5.0
*/
MYSQL2JSON(new MySQL2JsonDatabase()),
/**
* @since 1.1
*/
MARIADB(new MariaDBDatabase()),
MONGODB(new MongoDBDatabase());
DatabaseSetup database;
DatabaseType(DatabaseSetup database){

View File

@ -45,7 +45,7 @@ public abstract class AbstractJSONDatabaseHandler<T> extends AbstractDatabaseHan
// 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();
GsonBuilder builder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().enableComplexMapKeySerialization().setPrettyPrinting();
// Register adapters
builder.registerTypeAdapter(Location.class, new LocationAdapter()) ;
builder.registerTypeAdapter(World.class, new WorldAdapter());

View File

@ -139,7 +139,7 @@ public class JSONDatabaseHandler<T> extends AbstractJSONDatabaseHandler<T> {
// Obtain the file and delete it
File file = new File(tableFolder, uniqueId);
try {
Files.delete(file.toPath());
Files.deleteIfExists(file.toPath());
} catch (IOException e) {
plugin.logError("Could not delete json database object! " + file.getName() + " - " + e.getMessage());
}

View File

@ -0,0 +1,19 @@
package world.bentobox.bentobox.database.transition;
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseSetup;
import world.bentobox.bentobox.database.json.JSONDatabase;
import world.bentobox.bentobox.database.mariadb.MariaDBDatabase;
/**
* @author tastybento
* @since 1.5.0
*/
public class Json2MariaDBDatabase implements DatabaseSetup {
@Override
public <T> AbstractDatabaseHandler<T> getHandler(Class<T> type) {
return new TransitionDatabaseHandler<>(type, new JSONDatabase().getHandler(type), new MariaDBDatabase().getHandler(type));
}
}

View File

@ -0,0 +1,19 @@
package world.bentobox.bentobox.database.transition;
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseSetup;
import world.bentobox.bentobox.database.json.JSONDatabase;
import world.bentobox.bentobox.database.mysql.MySQLDatabase;
/**
* @author tastybento
* @since 1.5.0
*/
public class Json2MySQLDatabase implements DatabaseSetup {
@Override
public <T> AbstractDatabaseHandler<T> getHandler(Class<T> type) {
return new TransitionDatabaseHandler<>(type, new JSONDatabase().getHandler(type), new MySQLDatabase().getHandler(type));
}
}

View File

@ -0,0 +1,19 @@
package world.bentobox.bentobox.database.transition;
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseSetup;
import world.bentobox.bentobox.database.json.JSONDatabase;
import world.bentobox.bentobox.database.mysql.MySQLDatabase;
/**
* @author tastybento
* @since 1.5.0
*/
public class MySQL2JsonDatabase implements DatabaseSetup {
@Override
public <T> AbstractDatabaseHandler<T> getHandler(Class<T> type) {
return new TransitionDatabaseHandler<>(type, new MySQLDatabase().getHandler(type), new JSONDatabase().getHandler(type));
}
}

View File

@ -0,0 +1,114 @@
package world.bentobox.bentobox.database.transition;
import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
/**
* Class that transitions from one database type to another
*
* @author tastybento
*
* @param <T> Class <T> that is to be handled
* @since 1.5.0
*/
public class TransitionDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
private AbstractDatabaseHandler<T> fromHandler;
private AbstractDatabaseHandler<T> toHandler;
/**
* Constructor
* @param type - class to store in the database
* @param fromHandler - the database being moved away from
* @param toHandler - the database being moved to
*/
TransitionDatabaseHandler(Class<T> type, AbstractDatabaseHandler<T> fromHandler, AbstractDatabaseHandler<T> toHandler) {
this.fromHandler = fromHandler;
this.toHandler = toHandler;
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.database.AbstractDatabaseHandler#loadObjects()
*/
@Override
public List<T> loadObjects() throws InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, IntrospectionException, NoSuchMethodException {
// Load all objects from both databases
List<T> listFrom = fromHandler.loadObjects();
List<T> listTo = toHandler.loadObjects();
// If source database has objects, then delete and save them in the destination database
for (T object : listFrom) {
toHandler.saveObject(object);
fromHandler.deleteObject(object);
}
// Merge results
listTo.addAll(listFrom);
return listTo;
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.database.AbstractDatabaseHandler#loadObject(java.lang.String)
*/
@Override
public T loadObject(String uniqueId) throws InstantiationException, IllegalAccessException, InvocationTargetException, ClassNotFoundException, IntrospectionException, NoSuchMethodException {
// Try destination database
@Nullable
T object = toHandler.loadObject(uniqueId);
if (object == null) {
// Try source database
object = fromHandler.loadObject(uniqueId);
if (object != null) {
// Save the object in the new database and delete it from the old one
toHandler.saveObject(object);
fromHandler.deleteObject(object);
}
}
return object;
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.database.AbstractDatabaseHandler#objectExists(java.lang.String)
*/
@Override
public boolean objectExists(String uniqueId) {
// True if this object is in either database
return toHandler.objectExists(uniqueId) || fromHandler.objectExists(uniqueId);
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.database.AbstractDatabaseHandler#saveObject(java.lang.Object)
*/
@Override
public void saveObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
// Save only in the destination database
toHandler.saveObject(instance);
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.database.AbstractDatabaseHandler#deleteID(java.lang.String)
*/
@Override
public void deleteID(String uniqueId) {
// Delete in both databases if the object exists
toHandler.deleteID(uniqueId);
fromHandler.deleteID(uniqueId);
}
/* (non-Javadoc)
* @see world.bentobox.bentobox.database.AbstractDatabaseHandler#deleteObject(java.lang.Object)
*/
@Override
public void deleteObject(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
// Delete in both databases if the object exists
toHandler.deleteObject(instance);
fromHandler.deleteObject(instance);
}
@Override
public void close() {
// Not used
}
}

View File

@ -0,0 +1,19 @@
package world.bentobox.bentobox.database.transition;
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseSetup;
import world.bentobox.bentobox.database.json.JSONDatabase;
import world.bentobox.bentobox.database.yaml.YamlDatabase;
/**
* @author tastybento
* @since 1.5.0
*/
public class Yaml2JsonDatabase implements DatabaseSetup {
@Override
public <T> AbstractDatabaseHandler<T> getHandler(Class<T> type) {
return new TransitionDatabaseHandler<>(type, new YamlDatabase().getHandler(type), new JSONDatabase().getHandler(type));
}
}

View File

@ -0,0 +1,19 @@
package world.bentobox.bentobox.database.transition;
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseSetup;
import world.bentobox.bentobox.database.mariadb.MariaDBDatabase;
import world.bentobox.bentobox.database.yaml.YamlDatabase;
/**
* @author tastybento
* @since 1.5.0
*/
public class Yaml2MariaDBDatabase implements DatabaseSetup {
@Override
public <T> AbstractDatabaseHandler<T> getHandler(Class<T> type) {
return new TransitionDatabaseHandler<>(type, new YamlDatabase().getHandler(type), new MariaDBDatabase().getHandler(type));
}
}

View File

@ -0,0 +1,19 @@
package world.bentobox.bentobox.database.transition;
import world.bentobox.bentobox.database.AbstractDatabaseHandler;
import world.bentobox.bentobox.database.DatabaseSetup;
import world.bentobox.bentobox.database.mysql.MySQLDatabase;
import world.bentobox.bentobox.database.yaml.YamlDatabase;
/**
* @author tastybento
* @since 1.5.0
*/
public class Yaml2MySQLDatabase implements DatabaseSetup {
@Override
public <T> AbstractDatabaseHandler<T> getHandler(Class<T> type) {
return new TransitionDatabaseHandler<>(type, new YamlDatabase().getHandler(type), new MySQLDatabase().getHandler(type));
}
}

View File

@ -4,6 +4,7 @@ import java.beans.IntrospectionException;
import java.lang.reflect.InvocationTargetException;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.configuration.ConfigObject;
import world.bentobox.bentobox.database.DatabaseConnector;
/**
@ -18,9 +19,16 @@ public class ConfigHandler<T> extends YamlDatabaseHandler<T> {
public ConfigHandler(BentoBox plugin, Class<T> type, DatabaseConnector databaseConnector) {
super(plugin, type, databaseConnector);
if (!ConfigObject.class.isAssignableFrom(type)) {
throw new java.lang.ClassFormatError("Config classes must implement ConfigObject");
}
}
public void saveSettings(T instance) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
// ConfigObject check
if (!(instance instanceof ConfigObject)) {
throw new java.lang.ClassFormatError("Config classes must implement ConfigObject");
}
configFlag = true;
saveObject(instance);
}

View File

@ -652,6 +652,9 @@ public class YamlDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
}
private void delete(String uniqueId) {
if (uniqueId == null) {
return;
}
// The filename of the YAML file is the value of uniqueId field plus .yml. Sometimes the .yml is already appended.
if (!uniqueId.endsWith(YML)) {
uniqueId = uniqueId + YML;
@ -663,7 +666,7 @@ public class YamlDatabaseHandler<T> extends AbstractDatabaseHandler<T> {
// Obtain the file and delete it
File file = new File(tableFolder, uniqueId);
try {
Files.delete(file.toPath());
Files.deleteIfExists(file.toPath());
} catch (IOException e) {
plugin.logError("Could not delete yml database object! " + file.getName() + " - " + e.getMessage());
}

View File

@ -11,7 +11,9 @@ import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.AddonClassLoader;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.addons.exceptions.InvalidAddonFormatException;
import world.bentobox.bentobox.api.configuration.ConfigObject;
import world.bentobox.bentobox.api.events.addon.AddonEvent;
import world.bentobox.bentobox.database.objects.DataObject;
import java.io.BufferedReader;
import java.io.File;
@ -383,4 +385,19 @@ public class AddonsManager {
}
return null;
}
/**
* Get a list of addon classes that are of type {@link DataObject}
* but not {@link ConfigObject}. Configs are not transitioned to database.
* Used in database transition.
* @return list of DataObjects
* @since 1.5.0
*/
public List<Class<?>> getDataObjects() {
return classes.values().stream()
.filter(DataObject.class::isAssignableFrom)
// Do not include config files
.filter(c -> !ConfigObject.class.isAssignableFrom(c))
.collect(Collectors.toList());
}
}

View File

@ -11,13 +11,17 @@ general:
# If there is no economy plugin present anyway, money will be automatically disabled.
use-economy: true
database:
# YAML, JSON, MYSQL, MARIADB (10.2.3+), MONGODB.
# YAML and JSON are both file-based databases.
# JSON, MYSQL, MARIADB (10.2.3+), MONGODB, and YAML(deprecated).
# Transition database options are:
# YAML2JSON, YAML2MARIADB, YAML2MYSQL
# JSON2YAML, JSON2MARIADB, JSON2MYSQL
# MYSQL2JSON, MYSQL2YAML
# If you need others, make a feature request.
# Transition options enable migration from one database type to another. Use /bbox migrate.
# MYSQL might not work with all implementations: if available, use a dedicated database type (e.g. MARIADB).
# If you use MONGODB, you must also run the BSBMongo plugin (not addon).
# See https://github.com/tastybento/bsbMongo/releases/.
# /!\ BentoBox currently does not support changing this value mid-game. If you do need to change it, do a full reset of your databases and worlds.
type: YAML
type: JSON
host: localhost
# Port 3306 is MySQL's default. Port 27017 is MongoDB's default.
port: 3306

View File

@ -274,6 +274,14 @@ commands:
see-console: |-
&aCheck the console to see the feedback.
&aThis command is so spammy that the feedback cannot be read from chat...
migrate:
description: "migrates data from one database to another"
players: "&6Migrating players"
names: "&6Migrating names"
addons: "&6Migrating addons"
class: "&6Migrating [description]"
migrated: "&AMigrated"
confirmation:
confirm: "&cType command again within &b[seconds]s&c to confirm."
previous-request-cancelled: "&6Previous confirmation request cancelled."

View File

@ -59,6 +59,7 @@ import world.bentobox.bentobox.Settings;
import world.bentobox.bentobox.api.configuration.WorldSettings;
import world.bentobox.bentobox.api.events.island.IslandEvent.IslandDeleteEvent;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.DatabaseSetup.DatabaseType;
import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.lists.Flags;
import world.bentobox.bentobox.managers.island.IslandCache;
@ -104,6 +105,7 @@ public class IslandsManagerTest {
// Settings
Settings s = mock(Settings.class);
when(plugin.getSettings()).thenReturn(s);
when(s.getDatabaseType()).thenReturn(DatabaseType.JSON);
// Player
player = mock(Player.class);
@ -363,13 +365,6 @@ public class IslandsManagerTest {
*/
@Test
public void testBigScan() {
Settings settings = mock(Settings.class);
when(plugin.getSettings()).thenReturn(settings);
IslandWorldManager iwm = mock(IslandWorldManager.class);
when(plugin.getIWM()).thenReturn(iwm);
IslandsManager manager = new IslandsManager(plugin);
Location location = mock(Location.class);

View File

@ -43,6 +43,7 @@ import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.Settings;
import world.bentobox.bentobox.api.user.User;
import world.bentobox.bentobox.database.Database;
import world.bentobox.bentobox.database.DatabaseSetup.DatabaseType;
import world.bentobox.bentobox.database.objects.Players;
import world.bentobox.bentobox.util.Util;
@ -90,6 +91,7 @@ public class PlayersManagerTest {
// Settings
Settings s = mock(Settings.class);
when(plugin.getSettings()).thenReturn(s);
when(s.getDatabaseType()).thenReturn(DatabaseType.JSON);
// Set up spawn
Location netherSpawn = mock(Location.class);