diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0e1715c --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.gradle +.classpath +.project +.idea + +/.settings/ + +/build/ +/bin/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ab48fcd --- /dev/null +++ b/.travis.yml @@ -0,0 +1,5 @@ +language: java + +jdk: + - openjdk8 + - oraclejdk8 diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..bc4ba04 --- /dev/null +++ b/build.gradle @@ -0,0 +1,40 @@ +buildscript { + repositories { + jcenter() + } + dependencies { + classpath "com.github.jengelman.gradle.plugins:shadow:4.0.2" + } +} + +apply plugin: "com.github.johnrengelman.shadow" +apply plugin: "java" + +repositories { + jcenter() + maven { url "https://jitpack.io" } + + maven { url "https://hub.spigotmc.org/nexus/content/repositories/snapshots/" } + maven { url "https://oss.sonatype.org/content/repositories/snapshots" } +} + +dependencies { + implementation "com.github.RedstonerServer:CommandManager:master-SNAPSHOT" + implementation "com.github.RedstonerServer:ChatAPI:master-SNAPSHOT" + implementation "com.github.RedstonerServer:ChestAPI:master-SNAPSHOT" + + compile group: 'org.apache.logging.log4j', name: 'log4j-1.2-api', version: '2.11.1' + + compileOnly 'org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT' +} + +jar { + manifest { + attributes "Class-Path": "../lib/CommandManager.jar ../lib/ChatAPI.jar ../lib/ChestAPI.jar" + } +} + +task sourceJar(type: Jar, dependsOn: classes) { + classifier 'sources' + from sourceSets.main.allSource +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..28861d2 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..115e6ac --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..e95643d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/manifest.mf b/manifest.mf deleted file mode 100644 index c8b23f2..0000000 --- a/manifest.mf +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Class-Path: ../lib/CommandManager.jar ../lib/ChatAPI.jar ../lib/ChestAPI.jar - diff --git a/src/com/redstoner/annotations/AutoRegisterListener.java b/src/main/java/com/redstoner/annotations/AutoRegisterListener.java similarity index 100% rename from src/com/redstoner/annotations/AutoRegisterListener.java rename to src/main/java/com/redstoner/annotations/AutoRegisterListener.java diff --git a/src/com/redstoner/annotations/Commands.java b/src/main/java/com/redstoner/annotations/Commands.java similarity index 100% rename from src/com/redstoner/annotations/Commands.java rename to src/main/java/com/redstoner/annotations/Commands.java diff --git a/src/com/redstoner/annotations/Version.java b/src/main/java/com/redstoner/annotations/Version.java similarity index 100% rename from src/com/redstoner/annotations/Version.java rename to src/main/java/com/redstoner/annotations/Version.java diff --git a/src/com/redstoner/coremods/moduleLoader/ModuleLoader.cmd b/src/main/java/com/redstoner/coremods/moduleLoader/ModuleLoader.cmd similarity index 77% rename from src/com/redstoner/coremods/moduleLoader/ModuleLoader.cmd rename to src/main/java/com/redstoner/coremods/moduleLoader/ModuleLoader.cmd index eadeeb7..4e06bd0 100644 --- a/src/com/redstoner/coremods/moduleLoader/ModuleLoader.cmd +++ b/src/main/java/com/redstoner/coremods/moduleLoader/ModuleLoader.cmd @@ -9,16 +9,6 @@ command modules { perm moduleloader.modules.list; run list; } - -v { - help Lists all modules. Color indicates status: §aENABLED §cDISABLED; - perm moduleloader.modules.list; - run listv; - } - list -v { - help Lists all modules. Color indicates status: §aENABLED §cDISABLED; - perm moduleloader.modules.list; - run listv; - } load [string:name...] { help (Re)-Loads a module. WARNING: Handle with care! This has direct affect on code being executed. This command will temporarily halt the main thread until the class loading operation was completed.; perm moduleloader.modules.admin; diff --git a/src/com/redstoner/coremods/moduleLoader/ModuleLoader.java b/src/main/java/com/redstoner/coremods/moduleLoader/ModuleLoader.java similarity index 87% rename from src/com/redstoner/coremods/moduleLoader/ModuleLoader.java rename to src/main/java/com/redstoner/coremods/moduleLoader/ModuleLoader.java index b4fbbe4..3886dd1 100644 --- a/src/com/redstoner/coremods/moduleLoader/ModuleLoader.java +++ b/src/main/java/com/redstoner/coremods/moduleLoader/ModuleLoader.java @@ -1,14 +1,15 @@ package com.redstoner.coremods.moduleLoader; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.lang.reflect.Method; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -18,6 +19,7 @@ import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.event.HandlerList; import org.bukkit.event.Listener; +import org.bukkit.plugin.java.JavaPlugin; import com.nemez.cmdmgr.Command; import com.nemez.cmdmgr.Command.AsyncType; @@ -25,8 +27,9 @@ import com.nemez.cmdmgr.CommandManager; import com.redstoner.annotations.AutoRegisterListener; import com.redstoner.annotations.Commands; import com.redstoner.annotations.Version; -import com.redstoner.exceptions.MissingVersionException; +import com.redstoner.logging.PrivateLogManager; import com.redstoner.misc.Main; +import com.redstoner.misc.ModuleInfo; import com.redstoner.misc.VersionHelper; import com.redstoner.modules.CoreModule; import com.redstoner.modules.Module; @@ -37,11 +40,13 @@ import net.nemez.chatapi.click.Message; /** The module loader, mother of all modules. Responsible for loading and taking care of all modules. * * @author Pepich */ -@Version(major = 4, minor = 0, revision = 1, compatible = 4) +@Version(major = 5, minor = 2, revision = 0, compatible = 5) public final class ModuleLoader implements CoreModule { private static ModuleLoader instance; private static final HashMap modules = new HashMap<>(); + private static HashMap moduleInfos = new HashMap<>(); + private static HashMap> categorizes = new HashMap<>(); private static URL[] urls; private static URLClassLoader mainLoader; private static HashMap loaders = new HashMap<>(); @@ -70,7 +75,9 @@ public final class ModuleLoader implements CoreModule { if (instance == null) instance = new ModuleLoader(); - loggers.put(instance, new ModuleLogger("ModuleLoader")); + ModuleInfo info = new ModuleInfo(ModuleLoader.class.getResourceAsStream("module.info"), instance); + moduleInfos.put(instance, info); + loggers.put(instance, new ModuleLogger(info.getDisplayName())); CommandManager.registerCommand(ModuleLoader.class.getResourceAsStream("ModuleLoader.cmd"), instance, Main.plugin); } @@ -233,7 +240,35 @@ public final class ModuleLoader implements CoreModule { try { - loggers.put(module, new ModuleLogger(module.getClass().getSimpleName())); + InputStream infoFile = null; + + if (VersionHelper.isCompatible(VersionHelper.create(5, 0, 0, 5), module.getClass())) { + String basePath = "plugins/ModuleLoader/classes/" + module.getClass().getName().replace(".", "/"); + + try { + infoFile = new FileInputStream( + new File(basePath.substring(0, basePath.lastIndexOf('/')+1) + "module.info")); + } + catch(Exception e) { + infoFile = null; + } + } + ModuleInfo info = new ModuleInfo(infoFile, module); + + moduleInfos.put(module, info); + + String category = info.getCategory(); + if (!categorizes.containsKey(category)) + categorizes.put(category, new ArrayList<>(Arrays.asList(module))); + else { + List modsInCat = categorizes.get(category); + modsInCat.add(module); + categorizes.put(category, modsInCat); + } + + loggers.put(module, new ModuleLogger(info.getDisplayName())); + + if (module.onEnable()) { modules.put(module, true); @@ -241,9 +276,9 @@ public final class ModuleLoader implements CoreModule module.firstLoad(); else if (!VersionHelper.getVersion(module.getClass()).equals(VersionHelper.getString(oldVersion))) module.migrate(oldVersion); - if (VersionHelper.isCompatible(VersionHelper.create(4, 0, 0, 3), module.getClass())) + if (VersionHelper.isCompatible(VersionHelper.create(5, 0, 0, 3), module.getClass())) module.postEnable(); - if (VersionHelper.isCompatible(VersionHelper.create(4, 0, 0, 4), module.getClass())) + if (VersionHelper.isCompatible(VersionHelper.create(5, 0, 0, 4), module.getClass())) { Commands ann = module.getClass().getAnnotation(Commands.class); if (ann != null) @@ -288,50 +323,31 @@ public final class ModuleLoader implements CoreModule @Command(hook = "list", async = AsyncType.ALWAYS) public boolean listModulesCommand(CommandSender sender) { - Message m = new Message(sender, null); - m.appendText(getLogger().getHeader()); - m.appendText("§2Modules:\n&e"); - Module[] modules = ModuleLoader.modules.keySet().toArray(new Module[] {}); - for (int i = 0; i < modules.length; i++) - { - Module module = modules[i]; - String[] classPath = module.getClass().getName().split("\\."); - String classname = classPath[classPath.length - 1]; - m.appendText((ModuleLoader.modules.get(module) ? "§a" : "§c") + classname); - if (i + 1 < modules.length) - m.appendText("§7, "); - } - m.send(); - return true; - } - - /** This method lists all modules to the specified CommandSender. The modules will be color coded correspondingly to their enabled status. - * - * @param sender The person to send the info to, usually the issuer of the command or the console sender. - * @return true. */ - @Command(hook = "listv", async = AsyncType.ALWAYS) - public boolean listModulesCommandVersion(CommandSender sender) - { - Message m = new Message(sender, null); - m.appendText(getLogger().getHeader()); - m.appendText("§2Modules:\n&e"); - Module[] modules = ModuleLoader.modules.keySet().toArray(new Module[] {}); - for (int i = 0; i < modules.length; i++) - { - Module module = modules[i]; - String[] classPath = module.getClass().getName().split("\\."); - String classname = classPath[classPath.length - 1]; - try - { - m.appendText((ModuleLoader.modules.get(module) ? "§a" : "§c") + classname + "§e(" - + VersionHelper.getVersion(module.getClass()) + ")"); + boolean hasCategorys = hasCategories(); + Message m = new Message(sender, null); + ModuleInfo ml_info = moduleInfos.get(instance); + + m.appendText("§2--=[ ") + .appendTextHover("§2" + ml_info.getDisplayName(), ml_info.getModuleInfoHover()) + .appendText("§2 ]=--\nModules:\n"); + + for (String cat: categorizes.keySet()) { + if (hasCategorys) + m.appendText("\n&7" + cat + ":\n"); + + int curModule = 1; + List mods = categorizes.get(cat); + for (Module mod : mods) { + + ModuleInfo info = moduleInfos.get(mod); + m.appendTextHover((modules.get(mod) ? "§a" : "§c") + info.getDisplayName(), info.getModuleInfoHover()); + + if (curModule != mods.size()) + m.appendText("&7, "); + curModule++; } - catch (MissingVersionException e) - { - m.appendText((ModuleLoader.modules.get(module) ? "§a" : "§c") + classname + "§c" + "(Unknown Version)"); - } - if (i + 1 < modules.length) - m.appendText("§7, "); + m.appendText("\n"); + } m.send(); return true; @@ -354,8 +370,8 @@ public final class ModuleLoader implements CoreModule { HandlerList.unregisterAll((Listener) module); } - String[] commands = getAllHooks(module).toArray(new String[] {}); - CommandManager.unregisterAll(commands); + CommandManager.unregisterAllWithFallback(module.getClass().getSimpleName()); + PrivateLogManager.unregister(module); try { URLClassLoader loader = loaders.get(module); @@ -371,19 +387,6 @@ public final class ModuleLoader implements CoreModule } } - private static ArrayList getAllHooks(Module module) - { - ArrayList commands = new ArrayList<>(); - for (Method m : module.getClass().getMethods()) - { - Command cmd = m.getDeclaredAnnotation(Command.class); - if (cmd == null) - continue; - commands.add(cmd.hook()); - } - return commands; - } - @Command(hook = "load") public boolean loadModule(CommandSender sender, String name) { @@ -523,6 +526,9 @@ public final class ModuleLoader implements CoreModule disableModule(m); instance.getLogger().info("Disabled module, overriding the implementation"); modules.remove(m); + categorizes.get(moduleInfos.get(m).getCategory()).remove(m); + moduleInfos.remove(m); + try { if (loaders.containsKey(m)) @@ -614,6 +620,8 @@ public final class ModuleLoader implements CoreModule instance.getLogger().info("Attempting to disable module properly:"); disableModule(m); modules.remove(m); + categorizes.get(moduleInfos.get(m).getCategory()).remove(m); + moduleInfos.remove(m); instance.getLogger().info("Disabled module."); return true; } @@ -733,4 +741,12 @@ public final class ModuleLoader implements CoreModule e.printStackTrace(); } } + + public static JavaPlugin getPlugin() { + return Main.plugin; + } + + public static boolean hasCategories() { + return !(categorizes.size() == 1 && categorizes.containsKey("Other")); + } } diff --git a/src/com/redstoner/exceptions/MissingVersionException.java b/src/main/java/com/redstoner/exceptions/MissingVersionException.java similarity index 100% rename from src/com/redstoner/exceptions/MissingVersionException.java rename to src/main/java/com/redstoner/exceptions/MissingVersionException.java diff --git a/src/com/redstoner/exceptions/NonSaveableConfigException.java b/src/main/java/com/redstoner/exceptions/NonSaveableConfigException.java similarity index 100% rename from src/com/redstoner/exceptions/NonSaveableConfigException.java rename to src/main/java/com/redstoner/exceptions/NonSaveableConfigException.java diff --git a/src/main/java/com/redstoner/logging/Log4JFilter.java b/src/main/java/com/redstoner/logging/Log4JFilter.java new file mode 100644 index 0000000..1ebed09 --- /dev/null +++ b/src/main/java/com/redstoner/logging/Log4JFilter.java @@ -0,0 +1,54 @@ +package com.redstoner.logging; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Marker; +import org.apache.logging.log4j.core.LogEvent; +import org.apache.logging.log4j.core.Logger; +import org.apache.logging.log4j.core.filter.AbstractFilter; +import org.apache.logging.log4j.message.Message; + +public class Log4JFilter extends AbstractFilter { + + private static final long serialVersionUID = -5594073755007974254L; + + private static Result validateMessage(Message message) { + if (message == null) { + return Result.NEUTRAL; + } + return validateMessage(message.getFormattedMessage()); + } + + private static Result validateMessage(String message) { + return PrivateLogManager.isHidden(message) + ? Result.DENY + : Result.NEUTRAL; + } + + @Override + public Result filter(LogEvent event) { + Message candidate = null; + if (event != null) { + candidate = event.getMessage(); + } + return validateMessage(candidate); + } + + @Override + public Result filter(Logger logger, Level level, Marker marker, Message msg, Throwable t) { + return validateMessage(msg); + } + + @Override + public Result filter(Logger logger, Level level, Marker marker, String msg, Object... params) { + return validateMessage(msg); + } + + @Override + public Result filter(Logger logger, Level level, Marker marker, Object msg, Throwable t) { + String candidate = null; + if (msg != null) { + candidate = msg.toString(); + } + return validateMessage(candidate); + } +} \ No newline at end of file diff --git a/src/main/java/com/redstoner/logging/PrivateLogManager.java b/src/main/java/com/redstoner/logging/PrivateLogManager.java new file mode 100644 index 0000000..e8451e0 --- /dev/null +++ b/src/main/java/com/redstoner/logging/PrivateLogManager.java @@ -0,0 +1,89 @@ +package com.redstoner.logging; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.apache.logging.log4j.LogManager; + +import com.redstoner.misc.Utils; +import com.redstoner.modules.Module; +import com.redstoner.modules.ModuleLogger; + +public class PrivateLogManager { + + private static Map registrar = new HashMap<>(); + private static Map commands = new HashMap<>(); + + private static final String ISSUED_COMMAND_TEXT = "issued server command: /"; + private static final int ISSUED_COMMAND_TEXT_LENGTH = ISSUED_COMMAND_TEXT.length(); + + private static ModuleLogger logger; + + public static void initialize() { + org.apache.logging.log4j.core.Logger logger; + logger = (org.apache.logging.log4j.core.Logger) LogManager.getRootLogger(); + logger.addFilter(new Log4JFilter()); + PrivateLogManager.logger = new ModuleLogger("PrivateLogManager"); + } + + public static void register(Module module, String command, String replacement) { + command = command.toLowerCase(); + registrar.put(command, module); + commands.put(command, replacement); + logger.info(module.getClass().getSimpleName() + " registered &e/" + command + + (replacement.equals("")? "&7. Command will not be logged!" + : "&7, using replacement, &e" + replacement + "&7.")); + } + + public static void unregister(Module module) { + String unregestered = ""; + Iterator> i = registrar.entrySet().iterator(); + while (i.hasNext()) { + Map.Entry entry = i.next(); + if (entry.getValue() == module) { + i.remove(); + commands.remove(entry.getKey()); + unregestered += "&e" + entry.getKey() + "&7, "; + } + } + if (!unregestered.equals("")) + logger.info("Unregistered " + unregestered.substring(0, unregestered.length() - 2) + "&7 for module, " + module.getClass().getSimpleName() + "."); + } + + public static void unregister(Module module, String... toRemove) { + String unregestered = ""; + for (int i = 0; i < toRemove.length; i++) { + String command = toRemove[i].toLowerCase(); + registrar.remove(command); + if (commands.remove(command) != null) + unregestered += "&e" + command + "&7, "; + } + if (!unregestered.equals("")) + logger.info(module.getClass().getSimpleName() + " unregistered " + unregestered.substring(0, unregestered.length() - 2) + "&7."); + } + + public static boolean isHidden(String message) { + if (message == null) + return false; + + int index = message.indexOf(ISSUED_COMMAND_TEXT); + if (index == -1) + return false; + + String command = message.substring(index + ISSUED_COMMAND_TEXT_LENGTH); + + int spaceIndex = command.indexOf(" "); + command = spaceIndex == -1? command.toLowerCase() : command.substring(0, spaceIndex).toLowerCase(); + + String replacement = commands.get(command); + if (replacement == null) + return false; + if (replacement.equals("")) + return true; + + String player = message.substring(0, message.indexOf(" ")); + Utils.run(() -> System.out.println(replacement.replace("$s", player))); + return true; + } +} diff --git a/src/com/redstoner/misc/BroadcastFilter.java b/src/main/java/com/redstoner/misc/BroadcastFilter.java similarity index 100% rename from src/com/redstoner/misc/BroadcastFilter.java rename to src/main/java/com/redstoner/misc/BroadcastFilter.java diff --git a/src/com/redstoner/misc/CommandHolderType.java b/src/main/java/com/redstoner/misc/CommandHolderType.java similarity index 100% rename from src/com/redstoner/misc/CommandHolderType.java rename to src/main/java/com/redstoner/misc/CommandHolderType.java diff --git a/src/com/redstoner/misc/JsonManager.java b/src/main/java/com/redstoner/misc/JsonManager.java similarity index 100% rename from src/com/redstoner/misc/JsonManager.java rename to src/main/java/com/redstoner/misc/JsonManager.java diff --git a/src/com/redstoner/misc/Main.java b/src/main/java/com/redstoner/misc/Main.java similarity index 81% rename from src/com/redstoner/misc/Main.java rename to src/main/java/com/redstoner/misc/Main.java index b24e532..40894ee 100644 --- a/src/com/redstoner/misc/Main.java +++ b/src/main/java/com/redstoner/misc/Main.java @@ -4,6 +4,7 @@ import org.bukkit.plugin.java.JavaPlugin; import com.redstoner.annotations.Version; import com.redstoner.coremods.moduleLoader.ModuleLoader; +import com.redstoner.logging.PrivateLogManager; import com.redstoner.misc.mysql.MysqlHandler; import net.nemez.chatapi.ChatAPI; @@ -11,7 +12,7 @@ import net.nemez.chatapi.ChatAPI; /** Main class. Duh. * * @author Pepich */ -@Version(major = 4, minor = 0, revision = 0, compatible = -1) +@Version(major = 5, minor = 1, revision = 0, compatible = -1) public class Main extends JavaPlugin { public static JavaPlugin plugin; @@ -20,6 +21,9 @@ public class Main extends JavaPlugin public void onEnable() { plugin = this; + + PrivateLogManager.initialize(); + ChatAPI.initialize(this); // Configger.init(); MysqlHandler.init(); diff --git a/src/main/java/com/redstoner/misc/ModuleInfo.java b/src/main/java/com/redstoner/misc/ModuleInfo.java new file mode 100644 index 0000000..e96e813 --- /dev/null +++ b/src/main/java/com/redstoner/misc/ModuleInfo.java @@ -0,0 +1,81 @@ +package com.redstoner.misc; + +import java.io.InputStream; +import java.io.InputStreamReader; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import com.redstoner.coremods.moduleLoader.ModuleLoader; +import com.redstoner.exceptions.MissingVersionException; +import com.redstoner.modules.Module; + +public class ModuleInfo { + + private String simpleName; + private String displayName; + private String category; + private String description; + private String version; + + private String warning; + + public ModuleInfo(InputStream descriptor, Module module) { + try { + InputStreamReader reader = new InputStreamReader(descriptor); + FileConfiguration config = YamlConfiguration.loadConfiguration(reader); + + displayName = config.getString("displayName"); + category = config.getString("category"); + description = config.getString("description"); + } + catch (Exception e) { + warning = "Descriptor file could not be loaded, using the class's name."; + } + + simpleName = module.getClass().getSimpleName(); + + if (displayName == null) + displayName = simpleName; + + if (category == null) + category = "Other"; + + try { + version = VersionHelper.getVersion(module.getClass()); + } catch (MissingVersionException e) {} + } + + public String getSimpleName() { + return simpleName; + } + + public String getDisplayName() { + return displayName; + } + + public String getCategory() { + return category; + } + + public String getDescription() { + return description; + } + + public String getWarning() { + return warning; + } + + public String getVersion() { + return version; + } + + public String getModuleInfoHover() { + return "&8&o" + getSimpleName() + "\n" + + "&r&e" + (getVersion() == null? "&cVersion Missing" : getVersion()) + + "&r&9" + (ModuleLoader.hasCategories()? "\n" + getCategory() : "") + + "&r&7" + (getDescription() == null? "" : "\n\n" + getDescription()); + } + + +} diff --git a/src/com/redstoner/misc/Utils.java b/src/main/java/com/redstoner/misc/Utils.java similarity index 72% rename from src/com/redstoner/misc/Utils.java rename to src/main/java/com/redstoner/misc/Utils.java index 8186bcb..e3fd68c 100644 --- a/src/com/redstoner/misc/Utils.java +++ b/src/main/java/com/redstoner/misc/Utils.java @@ -11,6 +11,10 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import com.redstoner.annotations.Version; +import com.redstoner.coremods.moduleLoader.ModuleLoader; + +import net.nemez.chatapi.ChatAPI; +import net.nemez.chatapi.click.Message; /** The utils class containing utility functions. Those include but are not limited to sending formatted messages, broadcasts and more. * @@ -69,6 +73,45 @@ public final class Utils } } + /** This method broadcasts a message to all players and console that are allowed by the filter. Set the filter to NULL to broadcast to everyone.
+ * If you want to, you can set a message that will be logged to console. Set to null to not log anything.
+ * You can still allow console in the filter to log the original message. + * + * @param prefix The prefix for the message. Set to NULL to let it auto generate. + * @param message the message to be sent around + * @param filter the BroadcastFilter to be applied.
+ * Write a class implementing the interface and pass it to this method, the "sendTo()" method will be called for each recipient. + * @param logmessage the log message to appear in console. Set to null to not log this (you can still log the original message by returning true in the filter). + */ + public static int broadcast(String prefix, Message message, BroadcastFilter filter) + { + if (prefix == null) + prefix = "§8[§2" + getCaller() + "§8]: "; + if (filter == null) + { + for (Player p : Bukkit.getOnlinePlayers()) + ChatAPI.createMessage(p).appendText(prefix).appendMessage(message).send(); + Bukkit.getConsoleSender().sendMessage(prefix + message.getRawMessage()); + return Bukkit.getOnlinePlayers().size() + 1; + } + else + { + int count = 0; + for (Player p : Bukkit.getOnlinePlayers()) + if (filter.sendTo(p)) + { + ChatAPI.createMessage(p).appendText(prefix).appendMessage(message).send(); + count++; + } + if (filter.sendTo(Bukkit.getConsoleSender())) + { + Bukkit.getConsoleSender().sendMessage(prefix + message.getRawMessage()); + count++; + } + return count; + } + } + /** This method will find the next parent caller and return their class name, omitting package names. * * @return the Name of the calling class. */ @@ -146,4 +189,15 @@ public final class Utils { return UUID_pattern.matcher(toCheck).matches(); } + + public static void run(Runnable r) { + run(r, 0); + } + + public static void run(Runnable r, int delay) { + Bukkit.getScheduler().scheduleSyncDelayedTask(ModuleLoader.getPlugin(), r, delay); + } + + + } diff --git a/src/com/redstoner/misc/VersionHelper.java b/src/main/java/com/redstoner/misc/VersionHelper.java similarity index 100% rename from src/com/redstoner/misc/VersionHelper.java rename to src/main/java/com/redstoner/misc/VersionHelper.java diff --git a/src/com/redstoner/misc/mysql/Config.java b/src/main/java/com/redstoner/misc/mysql/Config.java similarity index 98% rename from src/com/redstoner/misc/mysql/Config.java rename to src/main/java/com/redstoner/misc/mysql/Config.java index 519b20a..d403c7b 100644 --- a/src/com/redstoner/misc/mysql/Config.java +++ b/src/main/java/com/redstoner/misc/mysql/Config.java @@ -66,9 +66,7 @@ public class Config private JSONObject loadConfig(File file) throws IOException, ParseException { FileReader reader = new FileReader(file); - JSONObject object = (JSONObject) parser.parse(reader); - reader.close(); - return object; + return (JSONObject) parser.parse(reader); } @Override diff --git a/src/com/redstoner/misc/mysql/JSONManager.java b/src/main/java/com/redstoner/misc/mysql/JSONManager.java similarity index 100% rename from src/com/redstoner/misc/mysql/JSONManager.java rename to src/main/java/com/redstoner/misc/mysql/JSONManager.java diff --git a/src/com/redstoner/misc/mysql/MysqlHandler.java b/src/main/java/com/redstoner/misc/mysql/MysqlHandler.java similarity index 100% rename from src/com/redstoner/misc/mysql/MysqlHandler.java rename to src/main/java/com/redstoner/misc/mysql/MysqlHandler.java diff --git a/src/com/redstoner/misc/mysql/MysqlQueryHandler.java b/src/main/java/com/redstoner/misc/mysql/MysqlQueryHandler.java similarity index 100% rename from src/com/redstoner/misc/mysql/MysqlQueryHandler.java rename to src/main/java/com/redstoner/misc/mysql/MysqlQueryHandler.java diff --git a/src/com/redstoner/misc/mysql/elements/ConstraintOperator.java b/src/main/java/com/redstoner/misc/mysql/elements/ConstraintOperator.java similarity index 100% rename from src/com/redstoner/misc/mysql/elements/ConstraintOperator.java rename to src/main/java/com/redstoner/misc/mysql/elements/ConstraintOperator.java diff --git a/src/com/redstoner/misc/mysql/elements/MysqlConstraint.java b/src/main/java/com/redstoner/misc/mysql/elements/MysqlConstraint.java similarity index 100% rename from src/com/redstoner/misc/mysql/elements/MysqlConstraint.java rename to src/main/java/com/redstoner/misc/mysql/elements/MysqlConstraint.java diff --git a/src/com/redstoner/misc/mysql/elements/MysqlDatabase.java b/src/main/java/com/redstoner/misc/mysql/elements/MysqlDatabase.java similarity index 100% rename from src/com/redstoner/misc/mysql/elements/MysqlDatabase.java rename to src/main/java/com/redstoner/misc/mysql/elements/MysqlDatabase.java diff --git a/src/com/redstoner/misc/mysql/elements/MysqlField.java b/src/main/java/com/redstoner/misc/mysql/elements/MysqlField.java similarity index 100% rename from src/com/redstoner/misc/mysql/elements/MysqlField.java rename to src/main/java/com/redstoner/misc/mysql/elements/MysqlField.java diff --git a/src/com/redstoner/misc/mysql/elements/MysqlResult.java b/src/main/java/com/redstoner/misc/mysql/elements/MysqlResult.java similarity index 100% rename from src/com/redstoner/misc/mysql/elements/MysqlResult.java rename to src/main/java/com/redstoner/misc/mysql/elements/MysqlResult.java diff --git a/src/com/redstoner/misc/mysql/elements/MysqlTable.java b/src/main/java/com/redstoner/misc/mysql/elements/MysqlTable.java similarity index 100% rename from src/com/redstoner/misc/mysql/elements/MysqlTable.java rename to src/main/java/com/redstoner/misc/mysql/elements/MysqlTable.java diff --git a/src/com/redstoner/misc/mysql/types/MysqlType.java b/src/main/java/com/redstoner/misc/mysql/types/MysqlType.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/MysqlType.java rename to src/main/java/com/redstoner/misc/mysql/types/MysqlType.java diff --git a/src/com/redstoner/misc/mysql/types/date/Date.java b/src/main/java/com/redstoner/misc/mysql/types/date/Date.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/date/Date.java rename to src/main/java/com/redstoner/misc/mysql/types/date/Date.java diff --git a/src/com/redstoner/misc/mysql/types/date/DateTime.java b/src/main/java/com/redstoner/misc/mysql/types/date/DateTime.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/date/DateTime.java rename to src/main/java/com/redstoner/misc/mysql/types/date/DateTime.java diff --git a/src/com/redstoner/misc/mysql/types/date/Time.java b/src/main/java/com/redstoner/misc/mysql/types/date/Time.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/date/Time.java rename to src/main/java/com/redstoner/misc/mysql/types/date/Time.java diff --git a/src/com/redstoner/misc/mysql/types/date/TimeStamp.java b/src/main/java/com/redstoner/misc/mysql/types/date/TimeStamp.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/date/TimeStamp.java rename to src/main/java/com/redstoner/misc/mysql/types/date/TimeStamp.java diff --git a/src/com/redstoner/misc/mysql/types/date/Year.java b/src/main/java/com/redstoner/misc/mysql/types/date/Year.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/date/Year.java rename to src/main/java/com/redstoner/misc/mysql/types/date/Year.java diff --git a/src/com/redstoner/misc/mysql/types/number/BigInt.java b/src/main/java/com/redstoner/misc/mysql/types/number/BigInt.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/number/BigInt.java rename to src/main/java/com/redstoner/misc/mysql/types/number/BigInt.java diff --git a/src/com/redstoner/misc/mysql/types/number/Decimal.java b/src/main/java/com/redstoner/misc/mysql/types/number/Decimal.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/number/Decimal.java rename to src/main/java/com/redstoner/misc/mysql/types/number/Decimal.java diff --git a/src/com/redstoner/misc/mysql/types/number/Double.java b/src/main/java/com/redstoner/misc/mysql/types/number/Double.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/number/Double.java rename to src/main/java/com/redstoner/misc/mysql/types/number/Double.java diff --git a/src/com/redstoner/misc/mysql/types/number/Float.java b/src/main/java/com/redstoner/misc/mysql/types/number/Float.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/number/Float.java rename to src/main/java/com/redstoner/misc/mysql/types/number/Float.java diff --git a/src/com/redstoner/misc/mysql/types/number/Int.java b/src/main/java/com/redstoner/misc/mysql/types/number/Int.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/number/Int.java rename to src/main/java/com/redstoner/misc/mysql/types/number/Int.java diff --git a/src/com/redstoner/misc/mysql/types/number/MediumInt.java b/src/main/java/com/redstoner/misc/mysql/types/number/MediumInt.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/number/MediumInt.java rename to src/main/java/com/redstoner/misc/mysql/types/number/MediumInt.java diff --git a/src/com/redstoner/misc/mysql/types/number/SmallInt.java b/src/main/java/com/redstoner/misc/mysql/types/number/SmallInt.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/number/SmallInt.java rename to src/main/java/com/redstoner/misc/mysql/types/number/SmallInt.java diff --git a/src/com/redstoner/misc/mysql/types/number/TinyInt.java b/src/main/java/com/redstoner/misc/mysql/types/number/TinyInt.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/number/TinyInt.java rename to src/main/java/com/redstoner/misc/mysql/types/number/TinyInt.java diff --git a/src/com/redstoner/misc/mysql/types/text/Blob.java b/src/main/java/com/redstoner/misc/mysql/types/text/Blob.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/text/Blob.java rename to src/main/java/com/redstoner/misc/mysql/types/text/Blob.java diff --git a/src/com/redstoner/misc/mysql/types/text/Char.java b/src/main/java/com/redstoner/misc/mysql/types/text/Char.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/text/Char.java rename to src/main/java/com/redstoner/misc/mysql/types/text/Char.java diff --git a/src/com/redstoner/misc/mysql/types/text/Enum.java b/src/main/java/com/redstoner/misc/mysql/types/text/Enum.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/text/Enum.java rename to src/main/java/com/redstoner/misc/mysql/types/text/Enum.java diff --git a/src/com/redstoner/misc/mysql/types/text/LongBlob.java b/src/main/java/com/redstoner/misc/mysql/types/text/LongBlob.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/text/LongBlob.java rename to src/main/java/com/redstoner/misc/mysql/types/text/LongBlob.java diff --git a/src/com/redstoner/misc/mysql/types/text/LongText.java b/src/main/java/com/redstoner/misc/mysql/types/text/LongText.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/text/LongText.java rename to src/main/java/com/redstoner/misc/mysql/types/text/LongText.java diff --git a/src/com/redstoner/misc/mysql/types/text/MediumBlob.java b/src/main/java/com/redstoner/misc/mysql/types/text/MediumBlob.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/text/MediumBlob.java rename to src/main/java/com/redstoner/misc/mysql/types/text/MediumBlob.java diff --git a/src/com/redstoner/misc/mysql/types/text/MediumText.java b/src/main/java/com/redstoner/misc/mysql/types/text/MediumText.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/text/MediumText.java rename to src/main/java/com/redstoner/misc/mysql/types/text/MediumText.java diff --git a/src/com/redstoner/misc/mysql/types/text/Set.java b/src/main/java/com/redstoner/misc/mysql/types/text/Set.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/text/Set.java rename to src/main/java/com/redstoner/misc/mysql/types/text/Set.java diff --git a/src/com/redstoner/misc/mysql/types/text/Text.java b/src/main/java/com/redstoner/misc/mysql/types/text/Text.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/text/Text.java rename to src/main/java/com/redstoner/misc/mysql/types/text/Text.java diff --git a/src/com/redstoner/misc/mysql/types/text/TinyText.java b/src/main/java/com/redstoner/misc/mysql/types/text/TinyText.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/text/TinyText.java rename to src/main/java/com/redstoner/misc/mysql/types/text/TinyText.java diff --git a/src/com/redstoner/misc/mysql/types/text/VarChar.java b/src/main/java/com/redstoner/misc/mysql/types/text/VarChar.java similarity index 100% rename from src/com/redstoner/misc/mysql/types/text/VarChar.java rename to src/main/java/com/redstoner/misc/mysql/types/text/VarChar.java diff --git a/src/com/redstoner/modules/CoreModule.java b/src/main/java/com/redstoner/modules/CoreModule.java similarity index 100% rename from src/com/redstoner/modules/CoreModule.java rename to src/main/java/com/redstoner/modules/CoreModule.java diff --git a/src/com/redstoner/modules/Module.java b/src/main/java/com/redstoner/modules/Module.java similarity index 100% rename from src/com/redstoner/modules/Module.java rename to src/main/java/com/redstoner/modules/Module.java diff --git a/src/com/redstoner/modules/ModuleLogger.java b/src/main/java/com/redstoner/modules/ModuleLogger.java similarity index 90% rename from src/com/redstoner/modules/ModuleLogger.java rename to src/main/java/com/redstoner/modules/ModuleLogger.java index 8141976..11d71b6 100644 --- a/src/com/redstoner/modules/ModuleLogger.java +++ b/src/main/java/com/redstoner/modules/ModuleLogger.java @@ -13,6 +13,7 @@ public class ModuleLogger { public static final String PREFIX_WARN = "§8[§eWARN§8]:§7 "; public static final String PREFIX_ERROR = "§8[§cERROR§8]:§7 "; + public static final String PREFIX_INFO = "§8[§fINFO§8]:§7 "; private String name; @@ -23,7 +24,7 @@ public class ModuleLogger public void info(final String message) { - Bukkit.getConsoleSender().sendMessage(getPrefix() + ChatAPI.colorify(null, message)); + Bukkit.getConsoleSender().sendMessage(PREFIX_INFO + getPrefix() + ChatAPI.colorify(null, message)); } public void warn(final String message) diff --git a/plugin.yml b/src/main/resources/plugin.yml similarity index 100% rename from plugin.yml rename to src/main/resources/plugin.yml