From de45eb1827d7a50e9fd467459f6a87052f406d4b Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 30 Nov 2018 16:35:58 -0500 Subject: [PATCH] Fixes #160 --- .../net/simon987/cubotplugin/CubotPlugin.java | 2 +- .../simon987/mischwplugin/MiscHWPlugin.java | 2 +- .../net/simon987/npcplugin/NpcPlugin.java | 2 +- .../simon987/biomassplugin/BiomassPlugin.java | 8 +- .../event/ObjectDeathListener.java | 1 - .../src/main/resources/plugin.properties | 3 +- .../RadioactiveCloudPlugin.java | 4 +- .../java/net/simon987/server/GameServer.java | 20 +-- .../simon987/server/plugin/PluginManager.java | 128 ++++++++++++++++-- .../simon987/server/plugin/ServerPlugin.java | 7 +- 10 files changed, 130 insertions(+), 47 deletions(-) diff --git a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotPlugin.java b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotPlugin.java index 5d90c32..0de8172 100644 --- a/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotPlugin.java +++ b/Plugin Cubot/src/main/java/net/simon987/cubotplugin/CubotPlugin.java @@ -34,6 +34,6 @@ public class CubotPlugin extends ServerPlugin { registry.registerHardware(CubotShield.class); registry.registerHardware(CubotCore.class); - LogManager.LOGGER.info("Initialised Cubot plugin"); + LogManager.LOGGER.info("(Cubot Plugin) Initialised Cubot plugin"); } } diff --git a/Plugin Misc HW/src/main/java/net/simon987/mischwplugin/MiscHWPlugin.java b/Plugin Misc HW/src/main/java/net/simon987/mischwplugin/MiscHWPlugin.java index 2bf52f7..d1e5b67 100644 --- a/Plugin Misc HW/src/main/java/net/simon987/mischwplugin/MiscHWPlugin.java +++ b/Plugin Misc HW/src/main/java/net/simon987/mischwplugin/MiscHWPlugin.java @@ -19,6 +19,6 @@ public class MiscHWPlugin extends ServerPlugin { registry.registerHardware(RandomNumberGenerator.class); registry.registerHardware(Clock.class); - LogManager.LOGGER.info("Initialised Misc Hardware Plugin"); + LogManager.LOGGER.info("(Mist HW Plugin) Initialised Misc Hardware Plugin"); } } diff --git a/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcPlugin.java b/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcPlugin.java index 63aecae..aa50804 100644 --- a/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcPlugin.java +++ b/Plugin NPC/src/main/java/net/simon987/npcplugin/NpcPlugin.java @@ -44,7 +44,7 @@ public class NpcPlugin extends ServerPlugin { radioTowers = new ArrayList<>(32); - LogManager.LOGGER.info("Initialised NPC plugin"); + LogManager.LOGGER.info("(NPC Plugin) Initialised NPC plugin"); } public static ArrayList getRadioTowers() { diff --git a/Plugin Plant/src/main/java/net/simon987/biomassplugin/BiomassPlugin.java b/Plugin Plant/src/main/java/net/simon987/biomassplugin/BiomassPlugin.java index 8028689..076b9f5 100644 --- a/Plugin Plant/src/main/java/net/simon987/biomassplugin/BiomassPlugin.java +++ b/Plugin Plant/src/main/java/net/simon987/biomassplugin/BiomassPlugin.java @@ -14,14 +14,10 @@ public class BiomassPlugin extends ServerPlugin { @Override public void init(ServerConfiguration config, GameRegistry registry) { + listeners.add(new WorldCreationListener()); listeners.add(new WorldUpdateListener(config)); - - if (registry.isGameObjectRegistered("net.simon987.npcplugin.HarvesterNPC")) { - listeners.add(new ObjectDeathListener(config)); - } else { - LogManager.LOGGER.severe("(BiomassPlugin) NPC plugin is not loaded so biomass will not spawn on death of HarvesterNPC"); - } + listeners.add(new ObjectDeathListener(config)); registry.registerGameObject(BiomassBlob.class); registry.registerItem(ItemBiomass.ID, ItemBiomass.class); diff --git a/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/ObjectDeathListener.java b/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/ObjectDeathListener.java index c689aaf..3a5deed 100644 --- a/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/ObjectDeathListener.java +++ b/Plugin Plant/src/main/java/net/simon987/biomassplugin/event/ObjectDeathListener.java @@ -19,7 +19,6 @@ public class ObjectDeathListener implements GameEventListener { public ObjectDeathListener(ServerConfiguration config) { biomassDropCount = config.getInt("harvester_biomass_drop_count"); - } @Override diff --git a/Plugin Plant/src/main/resources/plugin.properties b/Plugin Plant/src/main/resources/plugin.properties index 067c471..c9c6fc2 100644 --- a/Plugin Plant/src/main/resources/plugin.properties +++ b/Plugin Plant/src/main/resources/plugin.properties @@ -1,3 +1,4 @@ classpath=net.simon987.biomassplugin.BiomassPlugin name=Biomass Plugin -version=1.0 \ No newline at end of file +version=1.0 +depend=NPC Plugin \ No newline at end of file diff --git a/Plugin Radioactive Cloud/src/main/java/net/simon987/pluginradioactivecloud/RadioactiveCloudPlugin.java b/Plugin Radioactive Cloud/src/main/java/net/simon987/pluginradioactivecloud/RadioactiveCloudPlugin.java index efe34f2..10354ad 100644 --- a/Plugin Radioactive Cloud/src/main/java/net/simon987/pluginradioactivecloud/RadioactiveCloudPlugin.java +++ b/Plugin Radioactive Cloud/src/main/java/net/simon987/pluginradioactivecloud/RadioactiveCloudPlugin.java @@ -10,6 +10,6 @@ public class RadioactiveCloudPlugin extends ServerPlugin { @Override public void init(ServerConfiguration config, GameRegistry registry) { - LogManager.LOGGER.info("Initialised Radioactive cloud plugin."); + LogManager.LOGGER.info("(Radioactive cloud Plugin) Initialised Radioactive cloud plugin."); } -} +} \ No newline at end of file diff --git a/Server/src/main/java/net/simon987/server/GameServer.java b/Server/src/main/java/net/simon987/server/GameServer.java index 9112c44..2cd9d6b 100644 --- a/Server/src/main/java/net/simon987/server/GameServer.java +++ b/Server/src/main/java/net/simon987/server/GameServer.java @@ -24,7 +24,6 @@ import net.simon987.server.user.UserStatsHelper; import net.simon987.server.websocket.SocketServer; import org.bson.Document; -import java.io.File; import java.util.ArrayList; public class GameServer implements Runnable { @@ -68,8 +67,8 @@ public class GameServer implements Runnable { gameUniverse = new GameUniverse(config); gameUniverse.setMongo(mongo); - pluginManager = new PluginManager(); gameRegistry = new GameRegistry(); + pluginManager = new PluginManager(config, gameRegistry); maxExecutionTime = config.getInt("user_timeout"); @@ -84,21 +83,8 @@ public class GameServer implements Runnable { config.setString("secret_key", secretKey); } - //Load all plugins in plugins folder, if it doesn't exist, create it - File pluginDir = new File("plugins/"); - File[] pluginDirListing = pluginDir.listFiles(); - - if (pluginDirListing != null) { - for (File pluginFile : pluginDirListing) { - - if (pluginFile.getName().endsWith(".jar")) { - pluginManager.load(pluginFile, config, gameRegistry); - } - } - } else { - if (!pluginDir.mkdir()) { - LogManager.LOGGER.severe("Couldn't create plugin directory"); - } + if (!pluginManager.loadInFolder("plugins/")) { + System.exit(-1); } eventDispatcher = new GameEventDispatcher(pluginManager); diff --git a/Server/src/main/java/net/simon987/server/plugin/PluginManager.java b/Server/src/main/java/net/simon987/server/plugin/PluginManager.java index 74f0b92..12b03f5 100644 --- a/Server/src/main/java/net/simon987/server/plugin/PluginManager.java +++ b/Server/src/main/java/net/simon987/server/plugin/PluginManager.java @@ -5,30 +5,40 @@ import net.simon987.server.game.objects.GameRegistry; import net.simon987.server.logging.LogManager; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Constructor; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Properties; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; public class PluginManager { - private ArrayList plugins; + private ArrayList loadedPlugins; + private ArrayList toLoadPlugins; + private ServerConfiguration config; + private GameRegistry gameRegistry; - public PluginManager() { - this.plugins = new ArrayList<>(10); + public PluginManager(ServerConfiguration config, GameRegistry registry) { + this.config = config; + this.gameRegistry = registry; + this.toLoadPlugins = new ArrayList<>(10); + this.loadedPlugins = new ArrayList<>(10); } - public void load(File pluginFile, ServerConfiguration config, GameRegistry gameRegistry) { + private ServerPlugin load(File pluginFile) { LogManager.LOGGER.info("Loading plugin file " + pluginFile.getName()); + ZipFile zipFile = null; try { //Get the plugin config file from the archive - ZipFile zipFile = new ZipFile(pluginFile); + zipFile = new ZipFile(pluginFile); ZipEntry configEntry = zipFile.getEntry("plugin.properties"); @@ -38,7 +48,6 @@ public class PluginManager { Properties pluginConfig = new Properties(); pluginConfig.load(stream); - //Load the plugin ClassLoader loader = URLClassLoader.newInstance(new URL[]{pluginFile.toURI().toURL()}); Class aClass = Class.forName(pluginConfig.getProperty("classpath"), true, loader); Class pluginClass = aClass.asSubclass(ServerPlugin.class); @@ -48,26 +57,115 @@ public class PluginManager { plugin.setName(pluginConfig.getProperty("name")); plugin.setVersion(pluginConfig.getProperty("version")); - LogManager.LOGGER.info("Loaded " + plugin.name + " V" + plugin.version); + String dependStr = pluginConfig.getProperty("depend"); + if (dependStr != null) { + for (String dep : dependStr.split(",")) { + plugin.dependencies.add(dep.trim()); + } + } - //Add it to the list - plugins.add(plugin); - - //Init the plugin - plugin.init(config, gameRegistry); + return plugin; } else { LogManager.LOGGER.severe("Couldn't find plugin.properties in " + pluginFile.getName()); } - zipFile.close(); - } catch (Exception e) { e.printStackTrace(); + + } finally { + try { + if (zipFile != null) { + zipFile.close(); + } + } catch (IOException e) { + e.printStackTrace(); + } } + + return null; + } + + /** + * Load all plugins in plugins folder, if it doesn't exist, create it + * + * @return true if all the plugins could be loaded + */ + public boolean loadInFolder(String dir) { + + File pluginDir = new File(dir); + File[] pluginDirListing = pluginDir.listFiles(); + + if (pluginDirListing == null) { + if (!pluginDir.mkdir()) { + LogManager.LOGGER.severe("Couldn't create plugin directory"); + } + return false; + } + + for (File pluginFile : pluginDirListing) { + if (pluginFile.getName().endsWith(".jar")) { + toLoadPlugins.add(load(pluginFile)); + } + } + + while (toLoadPlugins.size() > 0) { + + ServerPlugin plugin = toLoadPlugins.get(0); + + if (!initWithDependencies(plugin)) { + LogManager.LOGGER.severe("Plugin " + plugin.name + " has unmet dependencies: " + + Arrays.toString(plugin.dependencies.toArray())); + return false; + } + } + + toLoadPlugins.clear(); + return true; + } + + private boolean initWithDependencies(ServerPlugin plugin) { + + for (String depName : plugin.dependencies) { + + if (!isLoaded(depName)) { + ServerPlugin dep = getPluginByName(depName, toLoadPlugins); + + if (dep != null) { + initWithDependencies(dep); + } else { + return false; + } + } + } + + initPlugin(plugin); + return true; + } + + private static ServerPlugin getPluginByName(String name, List plugins) { + + for (ServerPlugin p : plugins) { + if (p.name.equals(name)) { + return p; + } + } + + return null; + } + + private boolean isLoaded(String name) { + return getPluginByName(name, loadedPlugins) != null; + } + + private void initPlugin(ServerPlugin plugin) { + + toLoadPlugins.remove(plugin); + loadedPlugins.add(plugin); + plugin.init(config, gameRegistry); } public ArrayList getPlugins() { - return plugins; + return loadedPlugins; } } diff --git a/Server/src/main/java/net/simon987/server/plugin/ServerPlugin.java b/Server/src/main/java/net/simon987/server/plugin/ServerPlugin.java index 8f1cb1f..3246659 100644 --- a/Server/src/main/java/net/simon987/server/plugin/ServerPlugin.java +++ b/Server/src/main/java/net/simon987/server/plugin/ServerPlugin.java @@ -5,6 +5,7 @@ import net.simon987.server.event.GameEventListener; import net.simon987.server.game.objects.GameRegistry; import java.util.ArrayList; +import java.util.List; public abstract class ServerPlugin { @@ -21,7 +22,9 @@ public abstract class ServerPlugin { /** * List of event listeners */ - protected ArrayList listeners = new ArrayList<>(5); + protected List listeners = new ArrayList<>(5); + + protected List dependencies = new ArrayList<>(); /** * Called when the plugin is loaded @@ -44,7 +47,7 @@ public abstract class ServerPlugin { this.version = version; } - public ArrayList getListeners() { + public List getListeners() { return listeners; } }