diff --git a/src/main/java/net/minestom/server/MinecraftServer.java b/src/main/java/net/minestom/server/MinecraftServer.java index 74fdceac0..92795c6a0 100644 --- a/src/main/java/net/minestom/server/MinecraftServer.java +++ b/src/main/java/net/minestom/server/MinecraftServer.java @@ -31,6 +31,7 @@ import net.minestom.server.network.packet.server.play.PluginMessagePacket; import net.minestom.server.network.packet.server.play.ServerDifficultyPacket; import net.minestom.server.particle.Particle; import net.minestom.server.ping.ResponseDataConsumer; +import net.minestom.server.plugins.PluginManager; import net.minestom.server.potion.PotionType; import net.minestom.server.recipe.RecipeManager; import net.minestom.server.registry.ResourceGatherer; @@ -113,6 +114,8 @@ public class MinecraftServer { private static DimensionTypeManager dimensionTypeManager; private static AdvancementManager advancementManager; + private static PluginManager pluginManager; + private static UpdateManager updateManager; private static MinecraftServer minecraftServer; @@ -166,6 +169,8 @@ public class MinecraftServer { updateManager = new UpdateManager(); + pluginManager = PluginManager.getInstance(); + lootTableManager = new LootTableManager(); tagManager = new TagManager(); @@ -300,6 +305,9 @@ public class MinecraftServer { MinecraftServer.responseDataConsumer = responseDataConsumer; updateManager.start(); nettyServer.start(address, port); + long t1 = -System.nanoTime(); + pluginManager.loadPlugins(); + LOGGER.info("Plugins loaded in " + (t1+System.nanoTime())/1_000_000D + "ms"); LOGGER.info("Minestom server started successfully."); } diff --git a/src/main/java/net/minestom/server/plugins/Plugin.java b/src/main/java/net/minestom/server/plugins/Plugin.java new file mode 100644 index 000000000..3bde83176 --- /dev/null +++ b/src/main/java/net/minestom/server/plugins/Plugin.java @@ -0,0 +1,5 @@ +package net.minestom.server.plugins; + +public abstract class Plugin { + +} diff --git a/src/main/java/net/minestom/server/plugins/PluginDescription.java b/src/main/java/net/minestom/server/plugins/PluginDescription.java new file mode 100644 index 000000000..63cbbaf74 --- /dev/null +++ b/src/main/java/net/minestom/server/plugins/PluginDescription.java @@ -0,0 +1,8 @@ +package net.minestom.server.plugins; + +public @interface PluginDescription { + + String name(); + String description(); + String version(); +} diff --git a/src/main/java/net/minestom/server/plugins/PluginLoader.java b/src/main/java/net/minestom/server/plugins/PluginLoader.java new file mode 100644 index 000000000..6d6af6a0a --- /dev/null +++ b/src/main/java/net/minestom/server/plugins/PluginLoader.java @@ -0,0 +1,70 @@ +package net.minestom.server.plugins; + +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +@Slf4j +public class PluginLoader { + + private static PluginLoader instance = null; + + //Singleton + public static PluginLoader getInstance() { + if (instance == null) { + instance = new PluginLoader(); + } + return instance; + } + + private PluginLoader() { + + } + + public List loadPlugin(String path) { + JarFile jarFile; + URLClassLoader cl; + try { + jarFile = new JarFile(path); + URL[] urls = new URL[]{new URL("jar:file:" + path + "!/")}; + cl = URLClassLoader.newInstance(urls); + } catch (IOException e) { + e.printStackTrace(); + return new ArrayList<>(); + } + final List plugins = new ArrayList<>(); + final Enumeration e = jarFile.entries(); + while (e.hasMoreElements()) { + try { + final JarEntry je = e.nextElement(); + if (je.isDirectory() || !je.getName().endsWith(".class")) continue; + // -6 because of .class + String className = je.getName().substring(0, je.getName().length() - 6); + className = className.replace('/', '.'); + final Class c; + c = cl.loadClass(className); + Type superclass = c.getGenericSuperclass(); + if (superclass != null && Plugin.class.getTypeName().equals(superclass.getTypeName())) + try { + plugins.add((Plugin) c.getConstructor().newInstance()); + } catch (final ReflectiveOperationException | ArrayIndexOutOfBoundsException ex) { + ex.printStackTrace(); + } + } catch (final Throwable ex) { + ex.printStackTrace(); + } + } + + return Collections.unmodifiableList(plugins); + } + +} diff --git a/src/main/java/net/minestom/server/plugins/PluginManager.java b/src/main/java/net/minestom/server/plugins/PluginManager.java new file mode 100644 index 000000000..37aaa0d2e --- /dev/null +++ b/src/main/java/net/minestom/server/plugins/PluginManager.java @@ -0,0 +1,43 @@ +package net.minestom.server.plugins; + +import lombok.extern.slf4j.Slf4j; + +import java.io.File; + +@Slf4j +public class PluginManager { + + private static PluginManager instance = null; + + //Singleton + public static PluginManager getInstance() { + if (instance == null) { + instance = new PluginManager(); + } + return instance; + } + + private final PluginLoader loader = PluginLoader.getInstance(); + + private final File pluginsDir; + + private PluginManager() { + pluginsDir = new File("plugins"); + if (!pluginsDir.exists()||!pluginsDir.isDirectory()) { + if (!pluginsDir.mkdir()) { + log.error("Couldn't create plugins dir, plugins will not be loaded."); + return; + } + } + } + + public void loadPlugins() { + + File[] files = pluginsDir.listFiles(); + if(files != null) { + for (final File plugin : files) { + loader.loadPlugin(plugin.getPath()); + } + } + } +}