diff --git a/.classpath b/.classpath
index 1c7a2a9..4bdc242 100644
--- a/.classpath
+++ b/.classpath
@@ -17,14 +17,6 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 91a1e96..8038b51 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,19 +1,19 @@
4.0.0
- cz.marwland.mc
MarwCore
- 0.0.1-SNAPSHOT
MarwCore
Core plugin for MarwLand.cz Spigot-based Minecraft servers
https://git.lixko.eu/MarwLand/MarwCore
-
- MarwLand
- https://marwland.cz
-
https://git.lixko.eu/MarwLand/MarwCore/issues
Gitea Issue Tracker
+
+ cz.marwland.mc
+ MarwStuff
+ 0.0.1-SNAPSHOT
+ ../MarwStuff
+
src
@@ -53,62 +53,13 @@
-
- org.spigotmc
- spigot-api
- 1.12-R0.1-SNAPSHOT
- provided
-
-
- me.lucko.luckperms
- luckperms-api
- 4.2
- provided
-
-
- com.connorlinfoot
- BountifulAPI
- 1.6.4
- provided
-
-
- com.sk89q.worldedit
- worldedit-core
- 6.0.0-SNAPSHOT
- provided
-
-
- com.sk89q.worldguard
- worldguard-legacy
- 6.2
- provided
+
+ me.lucko.luckperms
+ luckperms-api
- com.massivecraft.massivecore
- MassiveCore
- 2.14.1-SNAPSHOT
- system
- /home/erik/Dokumenty/Java/marwland/res/MassiveCore.jar
-
-
- com.massivecraft.factions
- Factions
- 2.14.1-SNAPSHOT
- system
- /home/erik/Dokumenty/Java/marwland/res/Factions.jar
+ com.connorlinfoot
+ BountifulAPI
-
-
-
-
-
- spigot-repo
- https://hub.spigotmc.org/nexus/content/repositories/snapshots/
-
-
- sk89q-repo
- http://maven.sk89q.com/repo/
-
-
\ No newline at end of file
diff --git a/resources/config.yml b/resources/config.yml
new file mode 100644
index 0000000..dc85c86
--- /dev/null
+++ b/resources/config.yml
@@ -0,0 +1,2 @@
+#modules:
+# - cz.marwland.mc.features.Borders
diff --git a/resources/plugin.yml b/resources/plugin.yml
index a8fd570..f613184 100644
--- a/resources/plugin.yml
+++ b/resources/plugin.yml
@@ -6,3 +6,7 @@ author: ericek111
website: https://git.lixko.eu/MarwLand/MarwCore
depend: [LuckPerms]
softdepend: [WorldGuard, Factions]
+commands:
+ marw:
+ description: Core plugin controls.
+ usage: /marw
diff --git a/src/cz/marwland/mc/core/MarwCommandExecutor.java b/src/cz/marwland/mc/core/MarwCommandExecutor.java
new file mode 100644
index 0000000..05da6c9
--- /dev/null
+++ b/src/cz/marwland/mc/core/MarwCommandExecutor.java
@@ -0,0 +1,26 @@
+package cz.marwland.mc.core;
+
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandExecutor;
+import org.bukkit.command.CommandSender;
+
+import net.md_5.bungee.api.ChatColor;
+
+public class MarwCommandExecutor implements CommandExecutor {
+
+ @Override
+ public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (args.length < 1) {
+ sendHelp(sender);
+ } else if (args[0].equalsIgnoreCase("reload")) {
+ MarwCore.getInstance().reload();
+ sender.sendMessage(ChatColor.GREEN + "Reloaded!");
+ }
+ return true;
+ }
+
+ public void sendHelp(CommandSender sender) {
+ sender.sendMessage("Available commands:");
+ sender.sendMessage("/marw reload - Reload configs.");
+ }
+}
diff --git a/src/cz/marwland/mc/core/MarwCore.java b/src/cz/marwland/mc/core/MarwCore.java
index 526d586..2251d43 100644
--- a/src/cz/marwland/mc/core/MarwCore.java
+++ b/src/cz/marwland/mc/core/MarwCore.java
@@ -1,46 +1,43 @@
package cz.marwland.mc.core;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Path;
import java.util.HashMap;
+import java.util.logging.Level;
import org.bukkit.plugin.java.JavaPlugin;
import cz.marwland.mc.core.config.ConfigManager;
-import cz.marwland.mc.core.features.Base;
import cz.marwland.mc.core.features.Feature;
-import cz.marwland.mc.essentials.features.AntiVoid;
-import cz.marwland.mc.essentials.features.Borders;
-import cz.marwland.mc.essentials.features.ChatNotifier;
-import cz.marwland.mc.essentials.features.ChorusLimiter;
-import cz.marwland.mc.essentials.features.RandomTeleport;
+import cz.marwland.mc.core.plugins.ModuleClassLoader;
public class MarwCore extends JavaPlugin {
private ConfigManager configManager;
private HashMap features = new HashMap<>();
private static MarwCore INSTANCE = null;
+ private File modulesFolder = null;
+ private ModuleClassLoader moduleClassLoader;
@Override
public void onEnable() {
INSTANCE = this;
- //getServer().getPluginManager().registerEvents(new EventListener(this), this);
+ this.getCommand("marw").setExecutor(new MarwCommandExecutor());
configManager = new ConfigManager(this);
+ configManager.registerConfig("config.yml");
+ configManager.loadConfig("config.yml");
- this.addFeature(new AntiVoid());
- this.addFeature(new Base());
- this.addFeature(new Borders());
- this.addFeature(new ChatNotifier());
- this.addFeature(new ChorusLimiter());
- this.addFeature(new RandomTeleport());
-
- configManager.load();
- this.features.forEach((k, v) -> v.onEnable());
+ modulesFolder = this.getModulesFolderPath().toFile();
+ modulesFolder.mkdirs();
+ this.loadAndEnableModules();
}
@Override
public void onDisable() {
this.features.forEach((k, v) -> v.onDisable());
- configManager.save();
+ this.configManager.save();
}
@Override
@@ -50,7 +47,36 @@ public class MarwCore extends JavaPlugin {
public void reload() {
this.reloadConfig();
- this.features.forEach((k, v) -> v.onReload());
+ this.features.forEach((k, v) -> v.onDisable());
+ this.loadAndEnableModules();
+ }
+
+ public void loadModules() {
+ if (moduleClassLoader != null) {
+ try {
+ moduleClassLoader.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ moduleClassLoader = new ModuleClassLoader();
+ moduleClassLoader.addFromDirectory(modulesFolder);
+
+ for (String modClass : configManager.getConfig("config.yml").getStringList("modules")) {
+ Feature f = moduleClassLoader.doConstructor(modClass, this);
+ if (f == null)
+ continue;
+
+ this.addFeature(f);
+ this.getLogger().log(Level.INFO, "Loaded " + f.getName() + " @ " + modClass);
+ }
+ }
+
+ public void loadAndEnableModules() {
+ this.loadModules();
+ configManager.load();
+ this.features.forEach((k, v) -> v.onEnable());
}
public ConfigManager getConfigManager() {
@@ -73,4 +99,12 @@ public class MarwCore extends JavaPlugin {
return INSTANCE;
}
+ public Path getModulesFolderPath() {
+ return this.getDataFolder().toPath().resolve("modules");
+ }
+
+ public ModuleClassLoader getModuleClassLoader() {
+ return this.moduleClassLoader;
+ }
+
}
diff --git a/src/cz/marwland/mc/core/config/ConfigManager.java b/src/cz/marwland/mc/core/config/ConfigManager.java
index 344e000..6d107b6 100644
--- a/src/cz/marwland/mc/core/config/ConfigManager.java
+++ b/src/cz/marwland/mc/core/config/ConfigManager.java
@@ -22,6 +22,10 @@ public class ConfigManager {
configs.put(path, new ConfigFile(plugin, template, path));
}
+ public void loadConfig(String path) {
+ configs.get(path).load();
+ }
+
public void load() {
configs.forEach((k, v) -> v.load());
}
diff --git a/src/cz/marwland/mc/core/features/Base.java b/src/cz/marwland/mc/core/features/Base.java
deleted file mode 100644
index 72dc7bc..0000000
--- a/src/cz/marwland/mc/core/features/Base.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package cz.marwland.mc.core.features;
-
-import java.util.Arrays;
-
-import org.bukkit.command.CommandSender;
-import org.bukkit.command.defaults.BukkitCommand;
-import org.bukkit.configuration.file.FileConfiguration;
-
-import cz.marwland.mc.core.features.Feature;
-
-
-public class Base extends Feature {
-
- FileConfiguration cfg;
-
- public Base() {
- super("marw");
- // String name, String description, String usageMessage, List aliases)
- this.addCommand(new BukkitCommand("marw", "Core plugin controls.", "/marw", Arrays.asList()) {
- @Override
- public boolean execute(CommandSender sender, String commandLabel, String[] args) {
- if (args.length < 1) {
- sendHelp(sender);
- } else if (args[0].equalsIgnoreCase("reload")) {
- plugin.reload();
- sender.sendMessage("Reloaded!");
- }
- return true;
- }
-
- public void sendHelp(CommandSender sender) {
- sender.sendMessage("Available commands:");
- sender.sendMessage("/marw reload - Reload configs.");
- }
- });
- }
-
-}
diff --git a/src/cz/marwland/mc/core/features/Feature.java b/src/cz/marwland/mc/core/features/Feature.java
index 6d0fd70..ca10c11 100644
--- a/src/cz/marwland/mc/core/features/Feature.java
+++ b/src/cz/marwland/mc/core/features/Feature.java
@@ -41,6 +41,7 @@ public abstract class Feature implements Listener {
public void onEnable() {
if (cmap != null) {
for (BukkitCommand cmd : commands) {
+ System.out.println("Registering: " + cmd.getName());
cmap.register(plugin.getName().toLowerCase(), cmd);
}
}
@@ -54,9 +55,6 @@ public abstract class Feature implements Listener {
}
}
}
-
- public void onReload() {
- }
public String getName() {
return this.name;
diff --git a/src/cz/marwland/mc/core/plugins/ModuleClassLoader.java b/src/cz/marwland/mc/core/plugins/ModuleClassLoader.java
new file mode 100644
index 0000000..3fb6722
--- /dev/null
+++ b/src/cz/marwland/mc/core/plugins/ModuleClassLoader.java
@@ -0,0 +1,87 @@
+package cz.marwland.mc.core.plugins;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.jar.JarFile;
+import java.util.logging.Level;
+
+import org.bukkit.plugin.java.JavaPlugin;
+
+import cz.marwland.mc.core.features.Feature;
+
+public class ModuleClassLoader extends URLClassLoader {
+
+ private ArrayList jars = new ArrayList<>();
+
+ public ModuleClassLoader() {
+ super(new URL[] { }, ModuleClassLoader.class.getClassLoader());
+ }
+
+ public void addFile(File file) throws IOException {
+ this.addURL(file.toURI().toURL());
+ jars.add(new JarFile(file));
+ }
+
+ public void addFromDirectory(File modDir) {
+ if (!modDir.isDirectory())
+ throw new IllegalArgumentException("Provided 'modDir' argument is not a directory: " + modDir.getPath());
+
+ for (File mod : modDir.listFiles()) {
+ if (mod.isDirectory())
+ continue;
+ int lastdot = mod.getName().lastIndexOf('.');
+ if (lastdot < 0)
+ continue;
+
+ if (!mod.getName().substring(lastdot + 1).equalsIgnoreCase("jar"))
+ continue;
+
+ try {
+ this.addFile(mod);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public Feature doConstructor(String classPath)
+ throws ClassNotFoundException, ClassCastException, IllegalAccessException, InstantiationException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+ Class> jarClass;
+ jarClass = Class.forName(classPath, true, this);
+
+ Class extends Feature> pluginClass;
+ pluginClass = jarClass.asSubclass(Feature.class);
+
+ return pluginClass.getDeclaredConstructor().newInstance();
+ }
+
+ public Feature doConstructor(String classPath, JavaPlugin plugin) {
+ try {
+ return this.doConstructor(classPath);
+ } catch (ClassNotFoundException e) {
+ plugin.getLogger().log(Level.SEVERE, "Cannot find class '" + classPath + "'!");
+ } catch (ClassCastException e) {
+ plugin.getLogger().log(Level.SEVERE, "Class '" + classPath + "' does not extend Feature!");
+ } catch (IllegalAccessException e) {
+ plugin.getLogger().log(Level.SEVERE, "No public constructor in '" + classPath + "'!");
+ } catch (InstantiationException e) {
+ plugin.getLogger().log(Level.SEVERE, "Cannot instantiate '" + classPath + "'!");
+ } catch (IllegalArgumentException e) {
+ plugin.getLogger().log(Level.SEVERE, "Illegal arguments to the constructor of '" + classPath + "'!");
+ } catch (InvocationTargetException e) {
+ plugin.getLogger().log(Level.SEVERE, "Error occured whilst initializing '" + classPath + "'!");
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ plugin.getLogger().log(Level.SEVERE, "Class '" + classPath + "' does not have a public constructor!");
+ } catch (SecurityException e) {
+ plugin.getLogger().log(Level.SEVERE, "SecurityException occured whilst initializing '" + classPath + "'!");
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+}
diff --git a/src/cz/marwland/mc/essentials/features/AntiVoid.java b/src/cz/marwland/mc/essentials/features/AntiVoid.java
deleted file mode 100644
index faf42df..0000000
--- a/src/cz/marwland/mc/essentials/features/AntiVoid.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package cz.marwland.mc.essentials.features;
-
-import java.util.ArrayList;
-
-import org.bukkit.Bukkit;
-import org.bukkit.World;
-import org.bukkit.configuration.file.FileConfiguration;
-import org.bukkit.entity.Player;
-import org.bukkit.event.EventHandler;
-import org.bukkit.event.player.PlayerMoveEvent;
-
-import cz.marwland.mc.core.features.Feature;
-
-public class AntiVoid extends Feature {
-
- private FileConfiguration cfg;
- private ArrayList allowedWorlds = new ArrayList<>();
- private double triggery = 0d;
-
- public AntiVoid() {
- super();
- this.registerConfig("antivoid.yml");
- }
-
- @EventHandler
- public void onPlayerMove(PlayerMoveEvent e) {
- Player p = e.getPlayer();
- if (p.getLocation().getY() > triggery)
- return;
-
- World w = p.getWorld();
- if (!allowedWorlds.contains(w))
- return;
-
- p.teleport(w.getSpawnLocation());
- }
-
- @Override
- public void onEnable() {
- super.onEnable();
- this.onReload();
- }
-
- @Override
- public void onReload() {
- super.onReload();
- cfg = getConfig("antivoid.yml");
-
- triggery = cfg.getDouble("triggery", 0d);
- for (String wname : cfg.getStringList("worlds")) {
- World w = Bukkit.getWorld(wname);
-
- if (w == null)
- continue;
- allowedWorlds.add(w);
- }
- }
-
-}
diff --git a/src/cz/marwland/mc/essentials/features/Borders.java b/src/cz/marwland/mc/essentials/features/Borders.java
deleted file mode 100644
index 2c9e2a5..0000000
--- a/src/cz/marwland/mc/essentials/features/Borders.java
+++ /dev/null
@@ -1,230 +0,0 @@
-package cz.marwland.mc.essentials.features;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import org.bukkit.Bukkit;
-import org.bukkit.World;
-import org.bukkit.command.CommandSender;
-import org.bukkit.command.defaults.BukkitCommand;
-import org.bukkit.configuration.file.FileConfiguration;
-import org.bukkit.util.StringUtil;
-import org.bukkit.util.Vector;
-
-import cz.marwland.mc.core.config.ConfigEntry;
-import cz.marwland.mc.core.config.EntryManager;
-import cz.marwland.mc.core.config.IValueExecuter;
-import cz.marwland.mc.core.config.ValueValidator;
-import cz.marwland.mc.core.features.Feature;
-import net.md_5.bungee.api.ChatColor;
-
-public class Borders extends Feature {
-
- FileConfiguration cfg;
- EntryManager emgr = new EntryManager();
-
- public Borders() {
- super();
- // String name, String description, String usageMessage, List aliases)
- this.addCommand(new BukkitCommand(
- "worldborder",
- "Modify the world's borders",
- "/border [world] (key) (value)",
- Arrays.asList() ) {
- @Override
- public boolean execute(CommandSender sender, String commandLabel, String[] args) {
- if (!permissionMissingCheck(sender, this.getPermission()))
- return false;
-
- if (args.length < 2) {
- sender.sendMessage(
- ChatColor.YELLOW + "Format: " +
- ChatColor.GRAY + ChatColor.ITALIC + "/" + commandLabel +
- ChatColor.YELLOW + ChatColor.GRAY + " (world) (key) [value]");
- return true;
- }
- World w = Bukkit.getServer().getWorld(args[0]);
- if (w == null) {
- sender.sendMessage(ChatColor.RED + "Invalid world!");
- return true;
- }
-
- ConfigEntry> entry = emgr.getEntry(args[1]);
- if (entry == null) {
- sender.sendMessage(
- ChatColor.RED + "Invalid key " +
- ChatColor.YELLOW + args[1] +
- ChatColor.RED + "! Available: " +
- ChatColor.GRAY + String.join(", ", emgr.getKeys()));
- return true;
- }
-
- if (args.length == 2) { // get
- if (!cfg.contains(w.getName())) {
- sender.sendMessage(
- ChatColor.RED + "No border specified for " +
- ChatColor.YELLOW + args[0] +
- ChatColor.RED + "!");
- return true;
- }
- Object val = entry.getFrom(cfg, w.getName());
-
- sender.sendMessage(
- ChatColor.YELLOW + args[1] +
- ChatColor.GRAY + " @ " +
- ChatColor.AQUA + w.getName() +
- ChatColor.GRAY + ": " + (val == null ? ChatColor.ITALIC + "[" + entry.getDefaultValue() + "]": val));
- } else { // set
- String oldval = "" + entry.getFrom(cfg, w.getName());
- String newval = String.join(" ", args).substring(args[0].length() + args[1].length() + 2);
- if (entry.setIn(cfg, w.getName(), newval)) {
- plugin.getConfigManager().save();
- cfg = getConfig("borders.yml");
- loadWorlds();
- sender.sendMessage(
- ChatColor.GREEN + "Changed " +
- ChatColor.YELLOW + entry.getSubpath() +
- ChatColor.GRAY + " @ " +
- ChatColor.AQUA + w.getName() +
- ChatColor.GRAY + ": " + oldval +
- ChatColor.GOLD + " => " +
- ChatColor.GRAY + newval);
- } else {
- sender.sendMessage(
- ChatColor.RED + "Invalid value for " +
- ChatColor.YELLOW + args[1] +
- ChatColor.RED + ": " +
- ChatColor.GRAY + newval);
- }
- }
- return true;
- }
-
- @Override
- public List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException {
- ArrayList hints = new ArrayList();
- if (!sender.hasPermission(this.getPermission()) || args.length < 1)
- return hints;
-
- String lastWord = args[args.length - 1];
- if (args.length == 1) {
- for (World w : Bukkit.getServer().getWorlds()) {
- if (StringUtil.startsWithIgnoreCase(w.getName(), lastWord))
- hints.add(w.getName());
- }
- } else if(args.length == 2) {
- for (String key : emgr.getKeys()) {
- if (StringUtil.startsWithIgnoreCase(key, lastWord))
- hints.add(key);
- }
- }
-
- Collections.sort(hints, String.CASE_INSENSITIVE_ORDER);
- return hints;
- }
-
- @Override
- public String getPermission() {
- return getPermissionPath() + "." + this.getName().toLowerCase();
- }
- });
- emgr.addEntry(new ConfigEntry<>("center", ValueValidator.VECTOR, new Vector(0, 0, 0)));
-// emgr.addEntry(new ConfigEntry<>("size", ValueValidator.DOUBLE));
- emgr.addEntry(new ConfigEntry<>("radius", ValueValidator.INTEGER, 60000000));
- emgr.addEntry(new ConfigEntry<>("warningdist", ValueValidator.INTEGER, 5));
- emgr.addEntry(new ConfigEntry<>("warningtime", ValueValidator.INTEGER, 15));
- emgr.addEntry(new ConfigEntry<>("damage", ValueValidator.DOUBLE, 0.2d));
- emgr.addEntry(new ConfigEntry<>("buffer", ValueValidator.DOUBLE, 5d));
- this.registerConfig("borders.yml");
- }
-
- @Override
- public void onEnable() {
- super.onEnable();
- cfg = getConfig("borders.yml");
- this.loadWorlds();
- }
-
- public void loadWorlds() {
- for(World w : Bukkit.getServer().getWorlds()) {
- final String wname = w.getName();
- if (!cfg.contains(wname)) {
- w.getWorldBorder().reset();
- continue;
- }
-
- emgr.getEntry("center").doStuff(cfg, wname, new IValueExecuter