Enables game mode addons to run as the only world (#661)

* Enables game mode addons to run as the only world.

Requires game mode addons to do the following in their onLoad:

1. Register commands
2. Be able to provide the chunk generator object because it will be used
to generate the worlds
3. Be able to provide the WorldSettings because the world name (string)
is required

* Sets world in CompositeCommand after onEnable

* Added Javadoc to Addon#onEnable and Addon#onLoad to better explain where to do what.
This commit is contained in:
tastybento 2019-05-04 13:56:55 -07:00 committed by Florian CUNY
parent 5d299abae4
commit 2d94e4447a
5 changed files with 56 additions and 34 deletions

View File

@ -152,13 +152,16 @@ public class BentoBox extends JavaPlugin {
// Load addons. Addons may load worlds, so they must go before islands are loaded. // Load addons. Addons may load worlds, so they must go before islands are loaded.
addonsManager = new AddonsManager(this); addonsManager = new AddonsManager(this);
addonsManager.loadAddons(); addonsManager.loadAddons();
// Enable addons
addonsManager.enableAddons();
// Register default gamemode placeholders
addonsManager.getGameModeAddons().forEach(placeholdersManager::registerDefaultPlaceholders);
getServer().getScheduler().runTask(instance, () -> { getServer().getScheduler().runTask(instance, () -> {
// Enable addons
addonsManager.enableAddons();
// Register default gamemode placeholders
addonsManager.getGameModeAddons().forEach(placeholdersManager::registerDefaultPlaceholders);
// Register Listeners // Register Listeners
registerListeners(); registerListeners();

View File

@ -1,5 +1,15 @@
package world.bentobox.bentobox.api.addons; package world.bentobox.bentobox.api.addons;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.event.Listener;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.request.AddonRequestHandler;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.PlayersManager;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -10,17 +20,6 @@ import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.event.Listener;
import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.request.AddonRequestHandler;
import world.bentobox.bentobox.managers.IslandsManager;
import world.bentobox.bentobox.managers.PlayersManager;
/** /**
* Add-on class for BentoBox. Extend this to create an add-on. The operation * Add-on class for BentoBox. Extend this to create an add-on. The operation
* and methods are very similar to Bukkit's JavaPlugin. * and methods are very similar to Bukkit's JavaPlugin.
@ -44,6 +43,9 @@ public abstract class Addon {
/** /**
* Executes code when enabling the addon. * Executes code when enabling the addon.
* This is called after {@link #onLoad()}. * This is called after {@link #onLoad()}.
* <br/>
* Note that commands and worlds registration <b>must</b> be done in {@link #onLoad()}, if need be.
* Failure to do so <b>will</b> result in issues such as tab-completion not working for commands.
*/ */
public abstract void onEnable(); public abstract void onEnable();
@ -55,7 +57,7 @@ public abstract class Addon {
/** /**
* Executes code when loading the addon. * Executes code when loading the addon.
* This is called before {@link #onEnable()}. * This is called before {@link #onEnable()}.
* This should preferably be used to setup configuration and worlds. * This <b>must</b> be used to setup configuration, worlds and commands.
*/ */
public void onLoad() {} public void onLoad() {}

View File

@ -24,7 +24,6 @@ import org.eclipse.jdt.annotation.Nullable;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.Settings; import world.bentobox.bentobox.Settings;
import world.bentobox.bentobox.api.addons.Addon; import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.GameModeAddon;
import world.bentobox.bentobox.api.events.command.CommandEvent; import world.bentobox.bentobox.api.events.command.CommandEvent;
import world.bentobox.bentobox.api.localization.TextVariables; import world.bentobox.bentobox.api.localization.TextVariables;
import world.bentobox.bentobox.api.user.User; import world.bentobox.bentobox.api.user.User;
@ -135,10 +134,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
setDescription(COMMANDS + label + ".description"); setDescription(COMMANDS + label + ".description");
setParametersHelp(COMMANDS + label + ".parameters"); setParametersHelp(COMMANDS + label + ".parameters");
permissionPrefix = (addon != null) ? addon.getPermissionPrefix() : ""; permissionPrefix = (addon != null) ? addon.getPermissionPrefix() : "";
// Set up world if this is an AddonGameMode
if (addon instanceof GameModeAddon) {
setWorld(((GameModeAddon)addon).getOverWorld());
}
// Run setup // Run setup
setup(); setup();
if (!getSubCommand("help").isPresent() && !label.equals("help")) { if (!getSubCommand("help").isPresent() && !label.equals("help")) {
@ -190,8 +186,6 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
setUsage(""); setUsage("");
// Inherit permission prefix // Inherit permission prefix
this.permissionPrefix = parent.getPermissionPrefix(); this.permissionPrefix = parent.getPermissionPrefix();
// Inherit world
this.world = parent.getWorld();
// Default references to description and parameters // Default references to description and parameters
StringBuilder reference = new StringBuilder(); StringBuilder reference = new StringBuilder();
@ -649,7 +643,8 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
* @return the world * @return the world
*/ */
public World getWorld() { public World getWorld() {
return world; // Search up the tree until the world at the top is found
return parent != null ? parent.getWorld() : world;
} }
/** /**

View File

@ -42,12 +42,14 @@ public class AddonsManager {
@NonNull @NonNull
private final Map<String, Class<?>> classes; private final Map<String, Class<?>> classes;
private BentoBox plugin; private BentoBox plugin;
private @NonNull Map<@NonNull String, @Nullable GameModeAddon> worldNames;
public AddonsManager(@NonNull BentoBox plugin) { public AddonsManager(@NonNull BentoBox plugin) {
this.plugin = plugin; this.plugin = plugin;
addons = new ArrayList<>(); addons = new ArrayList<>();
loaders = new HashMap<>(); loaders = new HashMap<>();
classes = new HashMap<>(); classes = new HashMap<>();
worldNames = new HashMap<>();
} }
/** /**
@ -107,17 +109,12 @@ public class AddonsManager {
try { try {
// Run the onLoad. // Run the onLoad.
addon.onLoad(); addon.onLoad();
// If this is a GameModeAddon create the worlds, register it and load the schems // if game mode, get the world name and generate
if (addon instanceof GameModeAddon) { if (addon instanceof GameModeAddon) {
GameModeAddon gameMode = (GameModeAddon) addon; GameModeAddon gameMode = (GameModeAddon) addon;
// Create the gameWorlds if (!gameMode.getWorldSettings().getWorldName().isEmpty()) {
gameMode.createWorlds(); worldNames.put(gameMode.getWorldSettings().getWorldName(), gameMode);
plugin.getIWM().addGameMode(gameMode); }
// Register the schems
plugin.getSchemsManager().loadIslands(gameMode);
plugin.getBlueprintsManager().extractDefaultBlueprints(gameMode);
plugin.getBlueprintsManager().loadBlueprints(gameMode);
} }
// Addon successfully loaded // Addon successfully loaded
addon.setState(Addon.State.LOADED); addon.setState(Addon.State.LOADED);
@ -139,7 +136,25 @@ public class AddonsManager {
getLoadedAddons().forEach(addon -> { getLoadedAddons().forEach(addon -> {
try { try {
// If this is a GameModeAddon create the worlds, register it and load the schems
if (addon instanceof GameModeAddon) {
GameModeAddon gameMode = (GameModeAddon) addon;
// Create the gameWorlds
gameMode.createWorlds();
plugin.getIWM().addGameMode(gameMode);
// Register the schems
plugin.getSchemsManager().loadIslands(gameMode);
plugin.getBlueprintsManager().extractDefaultBlueprints(gameMode);
plugin.getBlueprintsManager().loadBlueprints(gameMode);
}
addon.onEnable(); addon.onEnable();
if (addon instanceof GameModeAddon) {
GameModeAddon gameMode = (GameModeAddon) addon;
// Set the worlds for the commands
gameMode.getPlayerCommand().ifPresent(c -> c.setWorld(gameMode.getOverWorld()));
gameMode.getAdminCommand().ifPresent(c -> c.setWorld(gameMode.getOverWorld()));
}
Bukkit.getPluginManager().callEvent(new AddonEvent().builder().addon(addon).reason(AddonEvent.Reason.ENABLE).build()); Bukkit.getPluginManager().callEvent(new AddonEvent().builder().addon(addon).reason(AddonEvent.Reason.ENABLE).build());
addon.setState(Addon.State.ENABLED); addon.setState(Addon.State.ENABLED);
plugin.log("Enabling " + addon.getDescription().getName() + "..."); plugin.log("Enabling " + addon.getDescription().getName() + "...");
@ -361,6 +376,11 @@ public class AddonsManager {
*/ */
@Nullable @Nullable
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
return getGameModeAddons().stream().filter(gm -> gm.inWorld(Bukkit.getWorld(worldName))).findFirst().map(gm -> gm.getDefaultWorldGenerator(worldName, id)).orElse(null); // Clean up world name
String w = worldName.replace("_nether", "").replace("_the_end", "");
if (worldNames.containsKey(w)) {
return worldNames.get(w).getDefaultWorldGenerator(worldName, id);
}
return null;
} }
} }

View File

@ -6,6 +6,8 @@ api-version: 1.13
authors: [tastybento, Poslovitch] authors: [tastybento, Poslovitch]
website: https://bentobox.world website: https://bentobox.world
load: STARTUP
loadbefore: [Multiverse-Core, Residence] loadbefore: [Multiverse-Core, Residence]
softdepend: [Vault, PlaceholderAPI, MVdWPlaceholderAPI] softdepend: [Vault, PlaceholderAPI, MVdWPlaceholderAPI]