Merge pull request #415 from BentoBoxWorld/gameworlds-and-gamemodes

GameWorlds and GameModes
This commit is contained in:
tastybento 2018-12-27 11:22:32 -08:00 committed by GitHub
commit bd3157366f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 231 additions and 41 deletions

View File

@ -3,12 +3,10 @@ package world.bentobox.bentobox;
import java.util.Optional; import java.util.Optional;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import world.bentobox.bentobox.api.configuration.Config; import world.bentobox.bentobox.api.configuration.Config;
import world.bentobox.bentobox.api.configuration.WorldSettings;
import world.bentobox.bentobox.api.events.BentoBoxReadyEvent; import world.bentobox.bentobox.api.events.BentoBoxReadyEvent;
import world.bentobox.bentobox.api.user.Notifier; import world.bentobox.bentobox.api.user.Notifier;
import world.bentobox.bentobox.commands.BentoBoxCommand; import world.bentobox.bentobox.commands.BentoBoxCommand;
@ -312,15 +310,6 @@ public class BentoBox extends JavaPlugin {
getLogger().warning(warning); getLogger().warning(warning);
} }
/**
* Registers a world as a world to be covered by this plugin
* @param world - Bukkit overworld
* @param worldSettings - settings for this world
*/
public void registerWorld(World world, WorldSettings worldSettings) {
islandWorldManager.addWorld(world, worldSettings);
}
/** /**
* @return the schemsManager * @return the schemsManager
*/ */

View File

@ -0,0 +1,65 @@
package world.bentobox.bentobox.api.addons;
import org.bukkit.Location;
import org.bukkit.World;
import world.bentobox.bentobox.api.configuration.WorldSettings;
import world.bentobox.bentobox.util.Util;
/**
* Defines the addon as a game mode.
* A game mode creates worlds, registers world settings and has schems in a jar folder.
* @author tastybento, Postlovitch
*
*/
public abstract class GameModeAddon extends Addon {
protected World islandWorld;
protected World netherWorld;
protected World endWorld;
/**
* Make the worlds for this GameMode in this method. BentoBox will call it
* after onLoad() and before onEnable().
* {@link #islandWorld} must be created and assigned,
* {@link #netherWorld} and {@link #endWorld} are optional and may be null.
*/
public abstract void createWorlds();
/**
* @return WorldSettings for this GameMode
*/
public abstract WorldSettings getWorldSettings();
/**
* Checks if a player is in any of the island worlds
* @param loc - player to check
* @return true if in a world or false if not
*/
public boolean inWorld(Location loc) {
return Util.sameWorld(loc.getWorld(), islandWorld);
}
/**
* @return over world
*/
public World getOverWorld() {
return islandWorld;
}
/**
* @return nether world, or null if it does not exist
*/
public World getNetherWorld() {
return netherWorld;
}
/**
* @return end world, or null if it does not exist
*/
public World getEndWorld() {
return endWorld;
}
}

View File

@ -22,6 +22,7 @@ import org.bukkit.entity.Player;
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;
@ -84,7 +85,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
/** /**
* The prefix to be used in this command * The prefix to be used in this command
*/ */
private String permissionPrefix = ""; private String permissionPrefix;
/** /**
* The world that this command operates in. This is an overworld and will cover any associated nether or end * The world that this command operates in. This is an overworld and will cover any associated nether or end
@ -100,7 +101,7 @@ public abstract class CompositeCommand extends Command implements PluginIdentifi
/** /**
* The top level label * The top level label
*/ */
private String topLabel = ""; private String topLabel;
/** /**
* Cool down tracker * Cool down tracker
@ -132,6 +133,11 @@ 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
setup(); setup();
if (!getSubCommand("help").isPresent() && !label.equals("help")) { if (!getSubCommand("help").isPresent() && !label.equals("help")) {
new DefaultHelpCommand(this); new DefaultHelpCommand(this);

View File

@ -24,6 +24,7 @@ import org.bukkit.configuration.file.YamlConfiguration;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
import world.bentobox.bentobox.api.addons.Addon; import world.bentobox.bentobox.api.addons.Addon;
import world.bentobox.bentobox.api.addons.AddonClassLoader; 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.addons.exceptions.InvalidAddonFormatException;
import world.bentobox.bentobox.api.events.addon.AddonEvent; import world.bentobox.bentobox.api.events.addon.AddonEvent;
@ -149,6 +150,15 @@ public class AddonsManager {
// 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 (addon instanceof GameModeAddon) {
GameModeAddon gameMode = (GameModeAddon)addon;
// Create the gameWorlds
gameMode.createWorlds();
plugin.getIWM().addWorld(gameMode.getOverWorld(), gameMode.getWorldSettings());
// Register the schems
plugin.getSchemsManager().loadIslands(gameMode);
}
} catch (Exception e) { } catch (Exception e) {
plugin.logError(e.getMessage()); plugin.logError(e.getMessage());
} }

View File

@ -139,7 +139,7 @@ public class LocalesManager {
// We cannot use Bukkit's saveResource, because we want it to go into a specific folder, so... // We cannot use Bukkit's saveResource, because we want it to go into a specific folder, so...
// Get the last part of the name // Get the last part of the name
int lastIndex = name.lastIndexOf('/'); int lastIndex = name.lastIndexOf('/');
File targetFile = new File(localeDir, name.substring(lastIndex >= 0 ? lastIndex : 0, name.length())); File targetFile = new File(localeDir, name.substring(lastIndex >= 0 ? lastIndex : 0));
copyFile(name, targetFile); copyFile(name, targetFile);
} }
} catch (IOException e) { } catch (IOException e) {

View File

@ -14,6 +14,7 @@ import org.bukkit.configuration.InvalidConfigurationException;
import world.bentobox.bentobox.BentoBox; import world.bentobox.bentobox.BentoBox;
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.database.objects.Island; import world.bentobox.bentobox.database.objects.Island;
import world.bentobox.bentobox.schems.Clipboard; import world.bentobox.bentobox.schems.Clipboard;
import world.bentobox.bentobox.util.Util; import world.bentobox.bentobox.util.Util;
@ -41,7 +42,7 @@ public class SchemsManager {
plugin.logError("Could not make schems folder!"); plugin.logError("Could not make schems folder!");
return; return;
} }
// Save any schems that // Save any schems that are in the jar
try (JarFile jar = new JarFile(addon.getFile())) { try (JarFile jar = new JarFile(addon.getFile())) {
Util.listJarFiles(jar, "schems", ".schem").forEach(name -> addon.saveResource(name, false)); Util.listJarFiles(jar, "schems", ".schem").forEach(name -> addon.saveResource(name, false));
} catch (IOException e) { } catch (IOException e) {
@ -60,33 +61,29 @@ public class SchemsManager {
/** /**
* Load schems for addon. Will try and load nether and end schems too if settings are set. * Load schems for addon. Will try and load nether and end schems too if settings are set.
* @param world - world * @param addon - GameModeAddon
*/ */
public void loadIslands(World world) { public void loadIslands(GameModeAddon addon) {
plugin.getIWM().getAddon(world).ifPresent(addon -> { File schems = new File(addon.getDataFolder(), "schems");
File schems = new File(addon.getDataFolder(), "schems"); // Copy any schems fould in the jar
// Copy any schems fould in the jar copySchems(addon, schems);
copySchems(addon, schems); // Load all schems in folder
// Load all schems in folder // Look through the folder
// Look through the folder FilenameFilter schemFilter = (File dir, String name) -> name.toLowerCase(java.util.Locale.ENGLISH).endsWith(".schem")
FilenameFilter schemFilter = (File dir, String name) -> name.toLowerCase(java.util.Locale.ENGLISH).endsWith(".schem") && !name.toLowerCase(java.util.Locale.ENGLISH).startsWith("nether-")
&& !name.toLowerCase(java.util.Locale.ENGLISH).startsWith("nether-") && !name.toLowerCase(java.util.Locale.ENGLISH).startsWith("end-");
&& !name.toLowerCase(java.util.Locale.ENGLISH).startsWith("end-"); Arrays.stream(Objects.requireNonNull(schems.list(schemFilter))).map(name -> name.substring(0, name.length() - 6)).forEach(name -> {
Arrays.stream(Objects.requireNonNull(schems.list(schemFilter))).map(name -> name.substring(0, name.length() - 6)).forEach(name -> { if (!plugin.getSchemsManager().loadSchem(addon.getOverWorld(), schems, name)) {
if (!plugin.getSchemsManager().loadSchem(world, schems, name)) { plugin.logError("Could not load " + name + ".schem for " + addon.getWorldSettings().getFriendlyName());
plugin.logError("Could not load " + name + ".schem for " + plugin.getIWM().getFriendlyName(world)); }
} if (addon.getWorldSettings().isNetherGenerate() && addon.getWorldSettings().isNetherIslands()
if (plugin.getIWM().isNetherGenerate(world) && plugin.getIWM().isNetherIslands(world) && !plugin.getSchemsManager().loadSchem(addon.getNetherWorld(), schems, "nether-" + name)) {
&& !plugin.getSchemsManager().loadSchem(plugin.getIWM().getNetherWorld(world), schems, "nether-" + name)) { plugin.logError("Could not load nether-" + name + ".schem for " + addon.getWorldSettings().getFriendlyName());
plugin.logError("Could not load nether-" + name + ".schem for " + plugin.getIWM().getFriendlyName(world)); }
} if (addon.getWorldSettings().isEndGenerate() && addon.getWorldSettings().isEndIslands()
if (plugin.getIWM().isEndGenerate(world) && plugin.getIWM().isEndIslands(world) && !plugin.getSchemsManager().loadSchem(addon.getEndWorld(), schems, "end-" + name)) {
&& !plugin.getSchemsManager().loadSchem(plugin.getIWM().getEndWorld(world), schems, "end-" + name)) { plugin.logError("Could not load end-" + name + ".schem for " + addon.getWorldSettings().getFriendlyName());
plugin.logError("Could not load end-" + name + ".schem for " + plugin.getIWM().getFriendlyName(world)); }
}
});
}); });
} }

View File

@ -0,0 +1,123 @@
@startuml
note as N1
This UML Class Diagram introduces the
GameWorlds and GameModes concepts that
are introduced in 1.0.
This diagram is not meant to be updated
alongside modifications that could be done
to GameWorlds and GameModes: it is meant
to serve as a template, and hopefully to keep
track of what we had in mind when we started
to work on this API.
- Poslovitch, @BentoBoxWorld
December 24th, 2018.
end note
package world.bentobox.bentobox {
class BentoBox << (M,orchid) Main >> {
- addonsManager : AddonsManager
- worldsManager : WorldsManager
+ getAddons() : AddonsManager
+ getWorlds() : WorldsManager
}
package api {
package addons {
abstract class Addon
abstract class GameMode extends Addon {
Specific Addon implementation allowing to register GameWorlds.
+ registerGameWorld(gameWorld:GameWorld) : void
+ getGameWorlds() : List<GameWorld>
}
}
package worlds {
interface WorldSettings
class GameWorld {
Represents a set of three Worlds
(Overworld, Nether, End) which is
registered by a GameMode addon and
managed by BentoBox.
It features its own implementation
of WorldSettings and provides
Islands and Schems managers.
__ Fields __
- name : String
- friendlyName : String
- overWorld : World
- netherWorld : World
- endWorld : World
- worldSettings : WorldSettings
.. Managers ..
- islandsManager : IslandsManager
- schemsManager : SchemsManager
__ Methods __
+ createWorlds() : boolean
+ inWorld(location:Location) : boolean
.. Getters ..
+ getName() : String
+ getFriendlyName() : String
+ getOverWorld() : World
+ getNetherWorld() : World
+ getEndWorld() : World
+ getSettings() : WorldSettings
+ getIslands() : IslandsManager
+ getSchems() : SchemsManager
}
GameWorld *-- "1" WorldSettings
GameMode *-- "*" GameWorld
}
}
package managers {
class AddonsManager
BentoBox *-- "1" AddonsManager
AddonsManager *-- "*" Addon
class WorldsManager {
Manages GameWorlds that are registered by GameMode addons.
It basically replaces IslandWorldManager.
__ Fields __
- gameWorlds : Map<GameMode, List<GameWorld>>
__ Methods __
+ registerGameWorld(gameMode:GameMode, gameWorld:GameWorld) : boolean
.. Getters ..
+ getGameWorldsMap() : Map<GameMode, List<GameWorld>>
+ getGameWorldsList() : List<GameWorld>
+ getGameWorlds(gameMode:GameMode) : List<GameWorld>
+ getGameWorld(name:String) : Optional<GameWorld>
+ getGameWorld(world:World) : Optional<GameWorld>
.. Multiverse ..
+ registerWorldsToMultiverse() : void
+ registerWorldToMultiverse(gameWorld:GameWorld) : void
}
BentoBox *-- "1" WorldsManager
WorldsManager *-- "*" GameWorld
class SchemsManager {
- schems : List<Clipboard>
- copySchems(schems:File, name:String) : void
- loadSchem(name:String) : boolean
+ getSchems() : List<Clipboard>
+ paste(island:Island, task:Runnable) : void
+ paste(island:Island) : void
}
GameWorld *-- "1" SchemsManager
}
}
@enduml