Refactor startup logic.

This commit re-implements and rearranges a lot of the logic in the main plugin class. It also removes the ConfigCommand class and moves its functionality into the CommandHandler to allow for reloads to be a bit more special than normal commands.

In the refactoring of the main class, the startup logic is broken up into two phases, setup and (re)load:

- In the setup phase, we create the data folder, and the command handler, config serializer(s), plugin integrations, boss abilities, the global event listener, and metrics are initialized. The ArenaMaster is instantiated, but it isn't initialized. These are things that need to be set up just once and don't change on reloads.

- In the (re)load phase, the config-file is loaded from disk, the global messenger is instantiated, the arena master is initialized (loads settings, classes, and arenas), the announcements file is loaded from disk along with the sign data/templates. These are things that we want to be reloadable.

If anything goes wrong during these phases, we store the exception thrown. This puts MobArena into a state where it prints the exception message to anyone who types a non-reload MobArena command to bring attention to the error so it can be fixed.
This commit is contained in:
Andreas Troelsen 2018-08-10 22:39:38 +02:00
parent dc25a38d98
commit 2081405d3b
7 changed files with 296 additions and 268 deletions

View File

@ -16,6 +16,9 @@ These changes will (most likely) be included in the next version.
- Right-clicking is now allowed in the lobby. This makes it possible to activate blocks like buttons and levers.
- Snow and ice no longer melts in arenas.
- Much of the parsing logic has been rewritten so that MobArena now logs more user-friendly errors when it encounters invalid values in the config-file.
- If MobArena fails to load due to config-file errors, it now enters a type of "error state". In this state, it responds to all commands (except for the reload command) with a short message explaining why it's disabled.
- It is now possible to reload config-files with `/ma reload`.
- The reload command now also reloads global settings, e.g. the global messenger prefix.
Thanks to:
- PrinceIonia and Nesseley for help with test of dev builds

View File

@ -33,7 +33,6 @@ import java.util.stream.Collectors;
public class ArenaMasterImpl implements ArenaMaster
{
private MobArena plugin;
private FileConfiguration config;
private List<Arena> arenas;
private Map<Player, Arena> arenaMap;
@ -53,7 +52,6 @@ public class ArenaMasterImpl implements ArenaMaster
*/
public ArenaMasterImpl(MobArena plugin) {
this.plugin = plugin;
this.config = plugin.getConfig();
this.arenas = new ArrayList<>();
this.arenaMap = new HashMap<>();
@ -62,8 +60,6 @@ public class ArenaMasterImpl implements ArenaMaster
this.allowedCommands = new HashSet<>();
this.spawnsPets = new SpawnsPets(Material.BONE, Material.RAW_FISH);
this.enabled = config.getBoolean("global-settings.enabled", true);
this.joinInterruptTimer = new JoinInterruptTimer();
}
@ -84,16 +80,21 @@ public class ArenaMasterImpl implements ArenaMaster
}
public boolean isEnabled() {
return enabled;
return plugin.getLastFailureCause() == null && enabled;
}
public void setEnabled(boolean value) {
enabled = value;
config.set("global-settings.enabled", enabled);
FileConfiguration config = plugin.getConfig();
if (config != null) {
config.set("global-settings.enabled", enabled);
plugin.saveConfig();
}
}
public boolean notifyOnUpdates() {
return config.getBoolean("global-settings.update-notification", false);
FileConfiguration config = plugin.getConfig();
return config != null && config.getBoolean("global-settings.update-notification", false);
}
public List<Arena> getArenas() {
@ -257,6 +258,8 @@ public class ArenaMasterImpl implements ArenaMaster
ConfigurationSection section = plugin.getConfig().getConfigurationSection("global-settings");
ConfigUtils.addMissingRemoveObsolete(plugin, "global-settings.yml", section);
enabled = section.getBoolean("enabled", true);
// Grab the commands string
String cmds = section.getString("allowed-commands", "");
@ -316,6 +319,7 @@ public class ArenaMasterImpl implements ArenaMaster
* Helper method for loading a single class.
*/
private ArenaClass loadClass(String classname) {
FileConfiguration config = plugin.getConfig();
ConfigurationSection section = config.getConfigurationSection("classes." + classname);
String lowercase = classname.toLowerCase().replace(" ", "");
@ -490,6 +494,7 @@ public class ArenaMasterImpl implements ArenaMaster
* Load all arena-related stuff.
*/
public void loadArenas() {
FileConfiguration config = plugin.getConfig();
ConfigurationSection section = makeSection(config, "arenas");
Set<String> arenanames = section.getKeys(false);
@ -505,6 +510,7 @@ public class ArenaMasterImpl implements ArenaMaster
}
public void loadArenasInWorld(String worldName) {
FileConfiguration config = plugin.getConfig();
Set<String> arenaNames = config.getConfigurationSection("arenas").getKeys(false);
if (arenaNames == null || arenaNames.isEmpty()) {
return;
@ -521,6 +527,7 @@ public class ArenaMasterImpl implements ArenaMaster
}
public void unloadArenasInWorld(String worldName) {
FileConfiguration config = plugin.getConfig();
Set<String> arenaNames = config.getConfigurationSection("arenas").getKeys(false);
if (arenaNames == null || arenaNames.isEmpty()) {
return;
@ -539,6 +546,7 @@ public class ArenaMasterImpl implements ArenaMaster
// Load an already existing arena node
private Arena loadArena(String arenaname) {
FileConfiguration config = plugin.getConfig();
ConfigurationSection section = makeSection(config, "arenas." + arenaname);
ConfigurationSection settings = makeSection(section, "settings");
String worldName = settings.getString("world", "");
@ -573,7 +581,6 @@ public class ArenaMasterImpl implements ArenaMaster
arenas.remove(arena);
plugin.reloadConfig();
config = plugin.getConfig();
loadArena(name);
return true;
@ -582,6 +589,7 @@ public class ArenaMasterImpl implements ArenaMaster
// Create and load a new arena node
@Override
public Arena createArenaNode(String arenaName, World world) {
FileConfiguration config = plugin.getConfig();
ConfigurationSection section = makeSection(config, "arenas");
return createArenaNode(section, arenaName, world, true);
}
@ -607,6 +615,7 @@ public class ArenaMasterImpl implements ArenaMaster
public void removeArenaNode(Arena arena) {
arenas.remove(arena);
FileConfiguration config = plugin.getConfig();
config.set("arenas." + arena.configName(), null);
plugin.saveConfig();
}
@ -616,17 +625,7 @@ public class ArenaMasterImpl implements ArenaMaster
}
public void reloadConfig() {
boolean wasEnabled = isEnabled();
if (wasEnabled) setEnabled(false);
for (Arena a : arenas) {
a.forceEnd();
}
plugin.reloadConfig();
config = plugin.getConfig();
initialize();
plugin.reloadSigns();
plugin.reloadAnnouncementsFile();
if (wasEnabled) setEnabled(true);
plugin.reload();
}
public void saveConfig() {

View File

@ -1,6 +1,7 @@
package com.garbagemule.MobArena;
import com.garbagemule.MobArena.commands.CommandHandler;
import com.garbagemule.MobArena.config.LoadsConfigFile;
import com.garbagemule.MobArena.framework.Arena;
import com.garbagemule.MobArena.framework.ArenaMaster;
import com.garbagemule.MobArena.listeners.MAGlobalListener;
@ -35,10 +36,8 @@ import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
/**
* MobArena
@ -47,13 +46,13 @@ import java.util.Random;
public class MobArena extends JavaPlugin
{
private ArenaMaster arenaMaster;
private CommandHandler commandHandler;
// Vault
private Economy economy;
private File configFile;
private FileConfiguration config;
private LoadsConfigFile loadsConfigFile;
private Throwable lastFailureCause;
public static final double MIN_PLAYER_DISTANCE_SQUARED = 225D;
public static Random random = new Random();
@ -70,141 +69,155 @@ public class MobArena extends JavaPlugin
public void onEnable() {
ServerVersionCheck.check(getServer());
try {
setup();
reload();
checkForUpdates();
} catch (ConfigError e) {
getLogger().log(Level.SEVERE, "You have an error in your config-file!\n\n " + e.getMessage() + "\n");
getLogger().log(Level.SEVERE, "Fix it, then run /ma load");
}
}
public void onDisable() {
if (arenaMaster != null) {
arenaMaster.getArenas().forEach(Arena::forceEnd);
arenaMaster.resetArenaMap();
arenaMaster = null;
}
loadsConfigFile = null;
ConfigurationSerialization.unregisterClass(ArenaSign.class);
VersionChecker.shutdown();
}
// Initialize config-file
configFile = new File(getDataFolder(), "config.yml");
config = new YamlConfiguration();
private void setup() {
try {
createDataFolder();
setupArenaMaster();
setupCommandHandler();
registerConfigurationSerializers();
setupVault();
setupMagicSpells();
setupBossAbilities();
setupListeners();
setupMetrics();
} catch (RuntimeException e) {
setLastFailureCauseAndRethrow(e);
}
lastFailureCause = null;
}
private void createDataFolder() {
File dir = getDataFolder();
if (!dir.exists()) {
if (dir.mkdir()) {
getLogger().info("Data folder plugins/MobArena created.");
} else {
getLogger().warning("Failed to create data folder plugins/MobArena!");
}
}
}
private void setupArenaMaster() {
arenaMaster = new ArenaMasterImpl(this);
}
private void setupCommandHandler() {
CommandHandler handler = new CommandHandler(this);
getCommand("ma").setExecutor(handler);
getCommand("mobarena").setExecutor(handler);
}
private void registerConfigurationSerializers() {
ConfigurationSerialization.registerClass(ArenaSign.class);
reloadConfig();
}
private void setupVault() {
Plugin vaultPlugin = this.getServer().getPluginManager().getPlugin("Vault");
if (vaultPlugin == null) {
getLogger().info("Vault was not found. Economy rewards will not work.");
return;
}
ServicesManager manager = this.getServer().getServicesManager();
RegisteredServiceProvider<Economy> e = manager.getRegistration(net.milkbowl.vault.economy.Economy.class);
if (e != null) {
economy = e.getProvider();
getLogger().info("Vault found; economy rewards enabled.");
} else {
getLogger().warning("Vault found, but no economy plugin detected. Economy rewards will not work!");
}
}
private void setupMagicSpells() {
Plugin spells = this.getServer().getPluginManager().getPlugin("MagicSpells");
if (spells == null) {
return;
}
// Initialize global messenger
getLogger().info("MagicSpells found, loading config-file.");
this.getServer().getPluginManager().registerEvents(new MagicSpellsListener(this), this);
}
private void setupBossAbilities() {
AbilityManager.loadCoreAbilities();
AbilityManager.loadCustomAbilities(getDataFolder());
}
private void setupListeners() {
PluginManager pm = this.getServer().getPluginManager();
pm.registerEvents(new MAGlobalListener(this, arenaMaster), this);
}
private void setupMetrics() {
Metrics metrics = new Metrics(this);
metrics.addCustomChart(new VaultChart(this));
metrics.addCustomChart(new ArenaCountChart(this));
metrics.addCustomChart(new ClassCountChart(this));
metrics.addCustomChart(new ClassChestsChart(this));
metrics.addCustomChart(new FoodRegenChart(this));
metrics.addCustomChart(new IsolatedChatChart(this));
metrics.addCustomChart(new MonsterInfightChart(this));
metrics.addCustomChart(new PvpEnabledChart(this));
}
public void reload() {
try {
reloadConfig();
reloadGlobalMessenger();
reloadArenaMaster();
reloadAnnouncementsFile();
reloadSigns();
} catch (RuntimeException e) {
setLastFailureCauseAndRethrow(e);
}
lastFailureCause = null;
}
@Override
public void reloadConfig() {
if (loadsConfigFile == null) {
loadsConfigFile = new LoadsConfigFile(this);
}
config = loadsConfigFile.load();
}
private void reloadGlobalMessenger() {
String prefix = config.getString("global-settings.prefix", "");
if (prefix.isEmpty()) {
prefix = ChatColor.GREEN + "[MobArena] ";
}
messenger = new Messenger(prefix);
// Set the header and save
getConfig().options().header(getHeader());
saveConfig();
// Initialize announcements-file
reloadAnnouncementsFile();
// Load boss abilities
loadAbilities();
// Set up soft dependencies
setupVault();
setupMagicSpells();
// Set up the ArenaMaster
arenaMaster = new ArenaMasterImpl(this);
try {
arenaMaster.initialize();
} catch (ConfigError e) {
getLogger().severe(e.getMessage());
return;
}
// Load signs after Messenger and ArenaMaster
reloadSigns();
// Register event listeners
registerListeners();
// Setup bStats metrics
setupMetrics();
// Announce enable!
getLogger().info("v" + this.getDescription().getVersion() + " enabled.");
// Check for updates
if (getConfig().getBoolean("global-settings.update-notification", false)) {
VersionChecker.checkForUpdates(this, null);
}
}
public void onDisable() {
// Force all arenas to end.
if (arenaMaster == null) return;
for (Arena arena : arenaMaster.getArenas()) {
arena.forceEnd();
}
arenaMaster.resetArenaMap();
VersionChecker.shutdown();
ConfigurationSerialization.unregisterClass(ArenaSign.class);
getLogger().info("disabled.");
}
public File getPluginFile() {
return getFile();
private void reloadArenaMaster() {
arenaMaster.getArenas().forEach(Arena::forceEnd);
arenaMaster.initialize();
}
@Override
public FileConfiguration getConfig() {
return config;
}
@Override
public void reloadConfig() {
// Make sure the data folder exists
File data = new File(getDataFolder(), "data");
if (!data.exists()) {
boolean created = data.mkdirs();
if (!created) {
throw new IllegalStateException("Failed to create data folder!");
}
getLogger().info("Created data folder.");
}
// Check if the config-file exists
if (!configFile.exists()) {
getLogger().info("No config-file found, creating default...");
saveDefaultConfig();
}
// Check for tab characters in config-file
try {
Path path = getDataFolder().toPath().resolve("config.yml");
List<String> lines = Files.readAllLines(path);
for (int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
int index = line.indexOf('\t');
if (index != -1) {
String indent = new String(new char[index]).replace('\0', ' ');
throw new IllegalArgumentException(
"Found tab in config-file on line " + (i + 1) + "! NEVER use tabs! ALWAYS use spaces!\n\n" +
line + "\n" +
indent + "^"
);
}
}
} catch (IOException e) {
throw new RuntimeException("There was an error reading the config-file:\n" + e.getMessage());
}
// Reload the config-file
try {
config.load(configFile);
} catch (IOException e) {
throw new RuntimeException("There was an error reading the config-file:\n" + e.getMessage());
} catch (InvalidConfigurationException e) {
throw new RuntimeException("\n\n>>>\n>>> There is an error in your config-file! Handle it!\n>>> Here is what snakeyaml says:\n>>>\n\n" + e.getMessage());
}
}
void reloadSigns() {
if (signListeners != null) {
signListeners.unregister();
}
SignBootstrap bootstrap = SignBootstrap.create(this);
signListeners = new SignListeners();
signListeners.register(bootstrap);
}
void reloadAnnouncementsFile() {
private void reloadAnnouncementsFile() {
// Create if missing
File file = new File(getDataFolder(), "announcements.yml");
try {
@ -230,87 +243,47 @@ public class MobArena extends JavaPlugin
throw new RuntimeException("\n\n>>>\n>>> There is an error in your announements-file! Handle it!\n>>> Here's what snakeyaml says:\n>>>\n\n" + e.getMessage());
}
}
private void reloadSigns() {
if (signListeners != null) {
signListeners.unregister();
}
SignBootstrap bootstrap = SignBootstrap.create(this);
signListeners = new SignListeners();
signListeners.register(bootstrap);
}
private void checkForUpdates() {
if (getConfig().getBoolean("global-settings.update-notification", false)) {
VersionChecker.checkForUpdates(this, null);
}
}
private void setLastFailureCauseAndRethrow(RuntimeException up) {
lastFailureCause = up;
throw up;
}
public Throwable getLastFailureCause() {
return lastFailureCause;
}
public File getPluginFile() {
return getFile();
}
@Override
public void saveConfig() {
try {
config.save(configFile);
} catch (IOException e) {
e.printStackTrace();
public FileConfiguration getConfig() {
if (config == null) {
reloadConfig();
}
}
private void registerListeners() {
// Bind the /ma, /mobarena commands to MACommands.
commandHandler = new CommandHandler(this);
getCommand("ma").setExecutor(commandHandler);
getCommand("mobarena").setExecutor(commandHandler);
PluginManager pm = this.getServer().getPluginManager();
pm.registerEvents(new MAGlobalListener(this, arenaMaster), this);
}
private void setupVault() {
Plugin vaultPlugin = this.getServer().getPluginManager().getPlugin("Vault");
if (vaultPlugin == null) {
getLogger().info("Vault was not found. Economy rewards will not work.");
return;
}
ServicesManager manager = this.getServer().getServicesManager();
RegisteredServiceProvider<Economy> e = manager.getRegistration(net.milkbowl.vault.economy.Economy.class);
if (e != null) {
economy = e.getProvider();
getLogger().info("Vault found; economy rewards enabled.");
} else {
getLogger().warning("Vault found, but no economy plugin detected. Economy rewards will not work!");
}
}
private void setupMagicSpells() {
Plugin spells = this.getServer().getPluginManager().getPlugin("MagicSpells");
if (spells == null) return;
getLogger().info("MagicSpells found, loading config-file.");
this.getServer().getPluginManager().registerEvents(new MagicSpellsListener(this), this);
}
private void setupMetrics() {
Metrics metrics = new Metrics(this);
metrics.addCustomChart(new VaultChart(this));
metrics.addCustomChart(new ArenaCountChart(this));
metrics.addCustomChart(new ClassCountChart(this));
metrics.addCustomChart(new ClassChestsChart(this));
metrics.addCustomChart(new FoodRegenChart(this));
metrics.addCustomChart(new IsolatedChatChart(this));
metrics.addCustomChart(new MonsterInfightChart(this));
metrics.addCustomChart(new PvpEnabledChart(this));
}
private void loadAbilities() {
File dir = new File(this.getDataFolder(), "abilities");
if (!dir.exists()) dir.mkdir();
AbilityManager.loadCoreAbilities();
AbilityManager.loadCustomAbilities(dir);
return config;
}
public ArenaMaster getArenaMaster() {
return arenaMaster;
}
public CommandHandler getCommandHandler() {
return commandHandler;
}
private String getHeader() {
String sep = System.getProperty("line.separator");
return "MobArena v" + this.getDescription().getVersion() + " - Config-file" + sep +
"Read the Wiki for details on how to set up this file: http://goo.gl/F5TTc" + sep +
"Note: You -must- use spaces instead of tabs!";
}
public Economy getEconomy() {
return economy;
}

View File

@ -1,5 +1,7 @@
package com.garbagemule.MobArena.commands;
import com.garbagemule.MobArena.ConfigError;
import com.garbagemule.MobArena.Messenger;
import com.garbagemule.MobArena.MobArena;
import com.garbagemule.MobArena.Msg;
import com.garbagemule.MobArena.commands.admin.DisableCommand;
@ -12,7 +14,6 @@ import com.garbagemule.MobArena.commands.setup.AutoGenerateCommand;
import com.garbagemule.MobArena.commands.setup.CheckDataCommand;
import com.garbagemule.MobArena.commands.setup.CheckSpawnsCommand;
import com.garbagemule.MobArena.commands.setup.ClassChestCommand;
import com.garbagemule.MobArena.commands.setup.ConfigCommand;
import com.garbagemule.MobArena.commands.setup.EditArenaCommand;
import com.garbagemule.MobArena.commands.setup.ListClassesCommand;
import com.garbagemule.MobArena.commands.setup.RemoveArenaCommand;
@ -44,13 +45,13 @@ import java.util.Map.Entry;
public class CommandHandler implements CommandExecutor
{
private MobArena plugin;
private ArenaMaster am;
private Messenger fallbackMessenger;
private Map<String,Command> commands;
public CommandHandler(MobArena plugin) {
this.plugin = plugin;
this.am = plugin.getArenaMaster();
this.fallbackMessenger = new Messenger("&a[MobArena] ");
registerCommands();
}
@ -68,7 +69,17 @@ public class CommandHandler implements CommandExecutor
// If there's no base argument, show a helpful message.
if (base.equals("")) {
am.getGlobalMessenger().tell(sender, Msg.MISC_HELP);
return safeTell(sender, Msg.MISC_HELP);
}
// Reloads are special
if (base.equals("reload") || (base.equals("config") && args.length > 1 && args[1].equals("reload"))) {
return reload(sender);
}
Throwable lastFailureCause = plugin.getLastFailureCause();
if (lastFailureCause != null) {
fallbackMessenger.tell(sender, "MobArena is disabled, because:\n" + ChatColor.RED + lastFailureCause.getMessage());
return true;
}
@ -78,6 +89,8 @@ public class CommandHandler implements CommandExecutor
return true;
}
ArenaMaster am = plugin.getArenaMaster();
// Get all commands that match the base.
List<Command> matches = getMatchingCommands(base);
@ -119,6 +132,31 @@ public class CommandHandler implements CommandExecutor
}
return true;
}
private boolean reload(CommandSender sender) {
if (!sender.hasPermission("mobarena.setup.load") && !sender.hasPermission("mobarena.setup.config")) {
return safeTell(sender, Msg.MISC_NO_ACCESS);
}
try {
plugin.reload();
plugin.getArenaMaster().getGlobalMessenger().tell(sender, "Reload complete.");
} catch (ConfigError e) {
fallbackMessenger.tell(sender, "Reload failed due to config-file error:\n" + ChatColor.RED + e.getMessage());
} catch (Exception e) {
fallbackMessenger.tell(sender, "Reload failed:\n" + ChatColor.RED + e.getMessage());
}
return true;
}
private boolean safeTell(CommandSender sender, Msg msg) {
ArenaMaster am = plugin.getArenaMaster();
if (am != null) {
am.getGlobalMessenger().tell(sender, msg);
} else {
fallbackMessenger.tell(sender, msg);
}
return true;
}
/**
* Get all commands that match a given string.
@ -187,6 +225,8 @@ public class CommandHandler implements CommandExecutor
.append(ChatColor.YELLOW).append(info.desc());
}
ArenaMaster am = plugin.getArenaMaster();
if (admin.length() == 0 && setup.length() == 0) {
am.getGlobalMessenger().tell(sender, "Available commands: " + user.toString());
} else {
@ -221,7 +261,6 @@ public class CommandHandler implements CommandExecutor
register(RestoreCommand.class);
// mobarena.setup
register(ConfigCommand.class);
register(SetupCommand.class);
register(SettingCommand.class);

View File

@ -1,40 +0,0 @@
package com.garbagemule.MobArena.commands.setup;
import com.garbagemule.MobArena.commands.Command;
import com.garbagemule.MobArena.commands.CommandInfo;
import com.garbagemule.MobArena.framework.ArenaMaster;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
@CommandInfo(
name = "config",
pattern = "config|cfg",
usage = "/ma config reload|save",
desc = "reload or save the config-file",
permission = "mobarena.setup.config"
)
public class ConfigCommand implements Command
{
@Override
public boolean execute(ArenaMaster am, CommandSender sender, String... args) {
// Require reload/save
if (args.length != 1) return false;
if (args[0].equals("reload")) {
try {
am.reloadConfig();
am.getGlobalMessenger().tell(sender, "Config reloaded.");
} catch (Exception e) {
am.getGlobalMessenger().tell(sender, ChatColor.RED + "ERROR:" + ChatColor.RESET + "\n" + e.getMessage());
am.getGlobalMessenger().tell(sender, "MobArena has been " + ChatColor.RED + "disabled" + ChatColor.RESET + ".");
am.getGlobalMessenger().tell(sender, "Fix the config-file, then reload it again, and then type " + ChatColor.YELLOW + "/ma enable" + ChatColor.RESET + " to re-enable MobArena.");
}
} else if (args[0].equals("save")) {
am.saveConfig();
am.getGlobalMessenger().tell(sender, "Config saved.");
} else {
return false;
}
return true;
}
}

View File

@ -0,0 +1,49 @@
package com.garbagemule.MobArena.config;
import com.garbagemule.MobArena.MobArena;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
public class LoadsConfigFile {
private final MobArena plugin;
public LoadsConfigFile(MobArena plugin) {
this.plugin = plugin;
}
public FileConfiguration load() {
try {
return loadConfiguration();
} catch (IOException | InvalidConfigurationException e) {
throw new IllegalStateException("Failed to load config-file", e);
}
}
private FileConfiguration loadConfiguration() throws IOException, InvalidConfigurationException {
File folder = createDataFolder();
File file = new File(folder, "config.yml");
if (!file.exists()) {
plugin.getLogger().info("No config-file found. Creating default...");
plugin.saveDefaultConfig();
}
YamlConfiguration yaml = new YamlConfiguration();
yaml.load(file);
return yaml;
}
private File createDataFolder() {
File folder = plugin.getDataFolder();
if (!folder.exists()) {
if (!folder.mkdirs()) {
throw new IllegalStateException("Failed to create data folder");
}
}
return folder;
}
}

View File

@ -93,11 +93,16 @@ public class AbilityManager
/**
* Load the custom abilities from the specified directory.
* @param classDir a directory of .class (and/or .java) files
* @param dataDir main plugin data folder
*/
public static void loadCustomAbilities(File classDir) {
public static void loadCustomAbilities(File dataDir) {
if (abilities == null) abilities = new HashMap<>();
File classDir = new File(dataDir, "abilities");
if (!classDir.exists()) {
return;
}
// Grab the source directory.
File javaDir = new File(classDir, "src");