Moved files to use the gradle structure
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
package com.redstoner.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/** The auto register annotation, to be put onto Classes that implement listener when you are too lazy to register the events yourself.
|
||||
*
|
||||
* @author Pepich */
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Version(major = 1, minor = 0, revision = 1, compatible = 1)
|
||||
public @interface AutoRegisterListener
|
||||
{}
|
||||
15
src/main/java/com/redstoner/annotations/Commands.java
Normal file
15
src/main/java/com/redstoner/annotations/Commands.java
Normal file
@@ -0,0 +1,15 @@
|
||||
package com.redstoner.annotations;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import com.redstoner.misc.CommandHolderType;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Commands
|
||||
{
|
||||
CommandHolderType value();
|
||||
}
|
||||
32
src/main/java/com/redstoner/annotations/Version.java
Normal file
32
src/main/java/com/redstoner/annotations/Version.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package com.redstoner.annotations;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/** The Version annotation, to be applied to all Classes that are part of the project.
|
||||
*
|
||||
* @author Pepich */
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Version
|
||||
{
|
||||
/** The major indicator of the version. Will be used for compatibility detection.
|
||||
*
|
||||
* @return the major version as an int */
|
||||
int major();
|
||||
|
||||
int minor();
|
||||
|
||||
int revision();
|
||||
|
||||
/** The compatibility part of the version number. Will be used for compatibility detection.</br>
|
||||
* Set to -1 if it is supposed to be always compatible.</br>
|
||||
* Defaults to 1.
|
||||
*
|
||||
* @return the smallest compatible version as an int. */
|
||||
int compatible() default 1;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
command modules {
|
||||
[empty] {
|
||||
help Lists all modules. Color indicates status: §aENABLED §cDISABLED;
|
||||
perm moduleloader.modules.list;
|
||||
run list;
|
||||
}
|
||||
list {
|
||||
help Lists all modules. Color indicates status: §aENABLED §cDISABLED;
|
||||
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;
|
||||
run load name;
|
||||
type console;
|
||||
}
|
||||
unload [string:name...] {
|
||||
help Unloads 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;
|
||||
run unload name;
|
||||
type console;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,736 @@
|
||||
package com.redstoner.coremods.moduleLoader;
|
||||
|
||||
import java.io.File;
|
||||
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.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import com.nemez.cmdmgr.Command;
|
||||
import com.nemez.cmdmgr.Command.AsyncType;
|
||||
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.misc.Main;
|
||||
import com.redstoner.misc.VersionHelper;
|
||||
import com.redstoner.modules.CoreModule;
|
||||
import com.redstoner.modules.Module;
|
||||
import com.redstoner.modules.ModuleLogger;
|
||||
|
||||
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)
|
||||
public final class ModuleLoader implements CoreModule
|
||||
{
|
||||
private static ModuleLoader instance;
|
||||
private static final HashMap<Module, Boolean> modules = new HashMap<>();
|
||||
private static URL[] urls;
|
||||
private static URLClassLoader mainLoader;
|
||||
private static HashMap<Module, URLClassLoader> loaders = new HashMap<>();
|
||||
private static File configFile;
|
||||
private static FileConfiguration config;
|
||||
private static boolean debugMode = false;
|
||||
private static HashMap<Module, ModuleLogger> loggers = new HashMap<>();
|
||||
|
||||
private ModuleLoader()
|
||||
{
|
||||
try
|
||||
{
|
||||
config = Main.plugin.getConfig();
|
||||
configFile = new File(Main.plugin.getDataFolder(), "config.yml");
|
||||
urls = new URL[] {(new File(Main.plugin.getDataFolder(), "classes")).toURI().toURL()};
|
||||
mainLoader = new URLClassLoader(urls, this.getClass().getClassLoader());
|
||||
}
|
||||
catch (MalformedURLException e)
|
||||
{
|
||||
System.out.println("Sumtin is wong with ya filesüstem m8. Fix eeeet or I won't werk!");
|
||||
Bukkit.getPluginManager().disablePlugin(Main.plugin);
|
||||
}
|
||||
}
|
||||
|
||||
public static void init()
|
||||
{
|
||||
if (instance == null)
|
||||
instance = new ModuleLoader();
|
||||
loggers.put(instance, new ModuleLogger("ModuleLoader"));
|
||||
CommandManager.registerCommand(ModuleLoader.class.getResourceAsStream("ModuleLoader.cmd"), instance,
|
||||
Main.plugin);
|
||||
}
|
||||
|
||||
public static final void loadFromConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!configFile.exists())
|
||||
{
|
||||
configFile.getParentFile().mkdirs();
|
||||
configFile.createNewFile();
|
||||
}
|
||||
config.load(configFile);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
catch (InvalidConfigurationException e)
|
||||
{
|
||||
configFile.delete();
|
||||
try
|
||||
{
|
||||
configFile.createNewFile();
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
e1.printStackTrace();
|
||||
}
|
||||
instance.getLogger().error("Invalid config file! Creating new, blank file!");
|
||||
}
|
||||
List<String> coremods = config.getStringList("coremods");
|
||||
if (coremods == null || coremods.isEmpty())
|
||||
{
|
||||
config.set("coremods", new String[] {"# Add the coremodules here!"});
|
||||
Main.plugin.saveConfig();
|
||||
try
|
||||
{
|
||||
config.save(configFile);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
List<String> autoload = config.getStringList("autoload");
|
||||
if (autoload == null || autoload.isEmpty())
|
||||
{
|
||||
config.set("autoload", new String[] {"# Add the modules here!"});
|
||||
Main.plugin.saveConfig();
|
||||
try
|
||||
{
|
||||
config.save(configFile);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (!config.contains("debugMode"))
|
||||
{
|
||||
config.set("debugMode", false);
|
||||
try
|
||||
{
|
||||
config.save(configFile);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
debugMode = config.getBoolean("debugMode");
|
||||
for (String s : coremods)
|
||||
if (!s.startsWith("#"))
|
||||
if (!ModuleLoader.addDynamicModule(s))
|
||||
{
|
||||
instance.getLogger().error("Couldn't autocomplete path for module name: " + s
|
||||
+ "! If you're on a case sensitive filesystem, please take note that case correction does not work. Make sure that the classname has proper capitalisation.");
|
||||
|
||||
}
|
||||
for (String s : autoload)
|
||||
if (!s.startsWith("#"))
|
||||
if (!ModuleLoader.addDynamicModule(s))
|
||||
{
|
||||
instance.getLogger().error("Couldn't autocomplete path for module name: " + s
|
||||
+ "! If you're on a case sensitive filesystem, please take note that case correction does not work. Make sure that the classname has proper capitalisation.");
|
||||
|
||||
}
|
||||
updateConfig();
|
||||
}
|
||||
|
||||
/** This method enables a specific module. If no module with that name is known to the loader yet it will be added to the list.</br>
|
||||
* This method is deprecated, use enableDynamicModule instead. When using this method, dynamic reloading of the module will not be supported.
|
||||
*
|
||||
* @param clazz The class of the module to be enabled.
|
||||
* @return true, when the module was successfully enabled. */
|
||||
@Deprecated
|
||||
public static final boolean enableModule(Class<? extends Module> clazz)
|
||||
{
|
||||
for (Module module : modules.keySet())
|
||||
{
|
||||
if (module.getClass().equals(clazz))
|
||||
{
|
||||
if (modules.get(module))
|
||||
{
|
||||
instance.getLogger().info("Module was already enabled! Ignoring module.!");
|
||||
return true;
|
||||
}
|
||||
if (module.onEnable())
|
||||
{
|
||||
if (module.getClass().isAnnotationPresent(AutoRegisterListener.class)
|
||||
&& (module instanceof Listener))
|
||||
{
|
||||
Bukkit.getPluginManager().registerEvents((Listener) module, Main.plugin);
|
||||
}
|
||||
instance.getLogger().info("Enabled module " + module.getClass().getName());
|
||||
instance.getLogger().info("Loaded module " + module.getClass().getName());
|
||||
modules.put(module, true);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
instance.getLogger().error("Failed to enable module " + module.getClass().getName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
Module m = clazz.newInstance();
|
||||
modules.put(m, false);
|
||||
if (m.onEnable())
|
||||
{
|
||||
if (m.getClass().isAnnotationPresent(AutoRegisterListener.class) && (m instanceof Listener))
|
||||
{
|
||||
Bukkit.getPluginManager().registerEvents((Listener) m, Main.plugin);
|
||||
}
|
||||
instance.getLogger().info("Loaded and enabled module " + m.getClass().getName());
|
||||
instance.getLogger().info("Loaded module " + m.getClass().getName());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
instance.getLogger().error("Failed to enable module " + m.getClass().getName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException e)
|
||||
{
|
||||
instance.getLogger()
|
||||
.error("Could not add " + clazz.getName() + " to the list, constructor not accessible.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static final void enableLoadedModule(Module module, Version oldVersion)
|
||||
{
|
||||
try
|
||||
{
|
||||
loggers.put(module, new ModuleLogger(module.getClass().getSimpleName()));
|
||||
if (module.onEnable())
|
||||
{
|
||||
modules.put(module, true);
|
||||
if (VersionHelper.getString(oldVersion).equals("0.0.0.0"))
|
||||
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()))
|
||||
module.postEnable();
|
||||
if (VersionHelper.isCompatible(VersionHelper.create(4, 0, 0, 4), module.getClass()))
|
||||
{
|
||||
Commands ann = module.getClass().getAnnotation(Commands.class);
|
||||
if (ann != null)
|
||||
{
|
||||
switch (ann.value())
|
||||
{
|
||||
case File:
|
||||
File f = new File("plugins/ModuleLoader/classes/"
|
||||
+ module.getClass().getName().replace(".", "/") + ".cmd");
|
||||
CommandManager.registerCommand(f, module, Main.plugin);
|
||||
break;
|
||||
case Stream:
|
||||
InputStream stream = module.getClass()
|
||||
.getResourceAsStream(module.getClass().getSimpleName() + ".cmd");
|
||||
CommandManager.registerCommand(stream, module, Main.plugin);
|
||||
case String:
|
||||
CommandManager.registerCommand(module.getCommandString(), module, Main.plugin);
|
||||
break;
|
||||
case None:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
instance.getLogger().info("Loaded module " + module.getClass().getName());
|
||||
if (module.getClass().isAnnotationPresent(AutoRegisterListener.class) && (module instanceof Listener))
|
||||
Bukkit.getPluginManager().registerEvents((Listener) module, Main.plugin);
|
||||
}
|
||||
else
|
||||
instance.getLogger().error("Failed to load module " + module.getClass().getName());
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
instance.getLogger().error("Failed to load module " + module.getClass().getName());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/** 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 = "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()) + ")");
|
||||
}
|
||||
catch (MissingVersionException e)
|
||||
{
|
||||
m.appendText((ModuleLoader.modules.get(module) ? "§a" : "§c") + classname + "§c" + "(Unknown Version)");
|
||||
}
|
||||
if (i + 1 < modules.length)
|
||||
m.appendText("§7, ");
|
||||
}
|
||||
m.send();
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void disableModules()
|
||||
{
|
||||
for (Module module : modules.keySet())
|
||||
{
|
||||
disableModule(module);
|
||||
}
|
||||
}
|
||||
|
||||
public static void disableModule(Module module)
|
||||
{
|
||||
if (modules.get(module))
|
||||
{
|
||||
module.onDisable();
|
||||
if (module.getClass().isAnnotationPresent(AutoRegisterListener.class) && (module instanceof Listener))
|
||||
{
|
||||
HandlerList.unregisterAll((Listener) module);
|
||||
}
|
||||
String[] commands = getAllHooks(module).toArray(new String[] {});
|
||||
CommandManager.unregisterAll(commands);
|
||||
try
|
||||
{
|
||||
URLClassLoader loader = loaders.get(module);
|
||||
if (loader != null)
|
||||
loader.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{}
|
||||
finally
|
||||
{
|
||||
loaders.remove(module);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static ArrayList<String> getAllHooks(Module module)
|
||||
{
|
||||
ArrayList<String> 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)
|
||||
{
|
||||
if (!addDynamicModule(name))
|
||||
{
|
||||
instance.getLogger().message(sender, true, "Couldn't autocomplete path for module name: " + name
|
||||
+ "! If you're on a case sensitive filesystem, please take note that case correction does not work. Make sure that the classname has proper capitalisation.");
|
||||
|
||||
}
|
||||
updateConfig();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Command(hook = "unload")
|
||||
public boolean unloadModule(CommandSender sender, String name)
|
||||
{
|
||||
if (!removeDynamicModule(name))
|
||||
instance.getLogger().error("Couldn't find module! Couldn't disable nonexisting module!");
|
||||
return true;
|
||||
}
|
||||
|
||||
public static final boolean addDynamicModule(String raw_name)
|
||||
{
|
||||
String[] raw = raw_name.split(" ");
|
||||
String name = raw[0];
|
||||
Version oldVersion;
|
||||
if (raw.length > 1)
|
||||
oldVersion = VersionHelper.getVersion(raw[1]);
|
||||
else
|
||||
oldVersion = VersionHelper.create(0, 0, 0, 0);
|
||||
for (Module m : modules.keySet())
|
||||
{
|
||||
if (m.getClass().getName().equals(name))
|
||||
{
|
||||
instance.getLogger().info(
|
||||
"Found existing module, attempting override. WARNING! This operation will halt the main thread until it is completed.");
|
||||
instance.getLogger()
|
||||
.info("Attempting to load new class definition before disabling and removing the old module");
|
||||
boolean differs = false;
|
||||
instance.getLogger().info("Old class definition: Class@" + m.getClass().hashCode());
|
||||
ClassLoader delegateParent = mainLoader.getParent();
|
||||
Class<?> newClass = null;
|
||||
URLClassLoader cl = new URLClassLoader(urls, delegateParent);
|
||||
try
|
||||
{
|
||||
newClass = cl.loadClass(m.getClass().getName());
|
||||
instance.getLogger().info("Found new class definition: Class@" + newClass.hashCode());
|
||||
differs = m.getClass() != newClass;
|
||||
}
|
||||
catch (ClassNotFoundException e)
|
||||
{
|
||||
instance.getLogger().error("Could not find a class definition, aborting now!");
|
||||
e.printStackTrace();
|
||||
try
|
||||
{
|
||||
cl.close();
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
e1.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!differs)
|
||||
{
|
||||
if (!debugMode)
|
||||
{
|
||||
instance.getLogger().warn(
|
||||
"New class definition equals old definition, are you sure you did everything right?");
|
||||
instance.getLogger().info("Aborting now...");
|
||||
try
|
||||
{
|
||||
cl.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
instance.getLogger().warn(
|
||||
"New class definition equals old definition, but debugMode is enabled. Loading anyways.");
|
||||
}
|
||||
else
|
||||
instance.getLogger().info("Found new class definition, attempting to instantiate:");
|
||||
Module module = null;
|
||||
try
|
||||
{
|
||||
module = (Module) newClass.newInstance();
|
||||
}
|
||||
catch (InstantiationException | IllegalAccessException e)
|
||||
{
|
||||
instance.getLogger().error("Could not instantiate the module, aborting!");
|
||||
e.printStackTrace();
|
||||
try
|
||||
{
|
||||
cl.close();
|
||||
}
|
||||
catch (IOException e1)
|
||||
{
|
||||
e1.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
instance.getLogger().info("Instantiated new class definition, checking versions");
|
||||
oldVersion = m.getClass().getAnnotation(Version.class);
|
||||
instance.getLogger().info("Current version: " + VersionHelper.getString(oldVersion));
|
||||
Version newVersion = module.getClass().getAnnotation(Version.class);
|
||||
instance.getLogger().info("Version of remote class: " + VersionHelper.getString(newVersion));
|
||||
if (oldVersion.equals(newVersion))
|
||||
{
|
||||
if (!debugMode)
|
||||
{
|
||||
instance.getLogger().error("Detected equal module versions, " + (debugMode
|
||||
? " aborting now... Set debugMode to true in your config if you want to continue!"
|
||||
: " continueing anyways."));
|
||||
if (!debugMode)
|
||||
{
|
||||
try
|
||||
{
|
||||
cl.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
instance.getLogger()
|
||||
.warn("New version equals old version, but debugMode is enabled. Loading anyways.");
|
||||
}
|
||||
else
|
||||
instance.getLogger().info("Versions differ, disabling old module");
|
||||
disableModule(m);
|
||||
instance.getLogger().info("Disabled module, overriding the implementation");
|
||||
modules.remove(m);
|
||||
try
|
||||
{
|
||||
if (loaders.containsKey(m))
|
||||
loaders.remove(m).close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
modules.put(module, false);
|
||||
loaders.put(module, cl);
|
||||
instance.getLogger().info("Successfully updated class definition. Enabling new implementation:");
|
||||
enableLoadedModule(module, oldVersion);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
ClassLoader delegateParent = mainLoader.getParent();
|
||||
URLClassLoader cl = new URLClassLoader(urls, delegateParent);
|
||||
try
|
||||
{
|
||||
Class<?> clazz = cl.loadClass(name);
|
||||
Module module = (Module) clazz.newInstance();
|
||||
modules.put(module, false);
|
||||
loaders.put(module, cl);
|
||||
enableLoadedModule(module, oldVersion);
|
||||
return true;
|
||||
}
|
||||
catch (NoClassDefFoundError | ClassNotFoundException | InstantiationException | IllegalAccessException e)
|
||||
{
|
||||
try
|
||||
{
|
||||
cl.close();
|
||||
}
|
||||
catch (IOException e1)
|
||||
{}
|
||||
if (e instanceof NoClassDefFoundError)
|
||||
{
|
||||
NoClassDefFoundError exception = (NoClassDefFoundError) e;
|
||||
String[] exMessage = exception.getMessage().split(" ");
|
||||
String moduleName = exMessage[exMessage.length - 1]
|
||||
.substring(0, exMessage[exMessage.length - 1].length()
|
||||
- (exMessage[exMessage.length - 1].endsWith(")") ? 1 : 0))
|
||||
.replace("/", ".");
|
||||
if (!moduleName.equalsIgnoreCase(name))
|
||||
{
|
||||
instance.getLogger()
|
||||
.error("Class &e" + moduleName + "&r couldn't be found! Suspecting a missing dependency!");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
instance.getLogger().warn(
|
||||
"Couldn't find class definition, attempting to get proper classname from thrown Exception.");
|
||||
if (addDynamicModule(moduleName))
|
||||
return true;
|
||||
}
|
||||
if (name.endsWith(".class"))
|
||||
{
|
||||
instance.getLogger().warn(
|
||||
"Couldn't find class definition, but path ends with .class -> Attempting again with removed file suffix.");
|
||||
if (addDynamicModule(name.replaceAll(".class$", "")))
|
||||
return true;
|
||||
}
|
||||
if (!name.contains("."))
|
||||
{
|
||||
instance.getLogger().warn(
|
||||
"Couldn't find class definition, suspecting incomplete path. Attempting autocompletion of path by adding a package name and trying again.");
|
||||
if (addDynamicModule(name.toLowerCase() + "." + name))
|
||||
return true;
|
||||
}
|
||||
if (!name.startsWith("com.redstoner.modules.") && name.contains("."))
|
||||
{
|
||||
instance.getLogger().warn(
|
||||
"Couldn't find class definition, suspecting incomplete path. Attempting autocompletion of package name and trying again.");
|
||||
if (addDynamicModule("com.redstoner.modules." + name))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static final boolean removeDynamicModule(String name)
|
||||
{
|
||||
for (Module m : modules.keySet())
|
||||
{
|
||||
if (m.getClass().getName().equals(name))
|
||||
{
|
||||
instance.getLogger().info(
|
||||
"Found existing module, attempting unload. WARNING! This operation will halt the main thread until it is completed.");
|
||||
instance.getLogger().info("Attempting to disable module properly:");
|
||||
disableModule(m);
|
||||
modules.remove(m);
|
||||
instance.getLogger().info("Disabled module.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!name.startsWith("com.redstoner.modules."))
|
||||
{
|
||||
if (name.endsWith(".class"))
|
||||
{
|
||||
instance.getLogger().warn(
|
||||
"Couldn't find class definition, but path ends with .class -> Attempting again with removed file suffix.");
|
||||
if (removeDynamicModule(name.replaceAll(".class$", "")))
|
||||
return true;
|
||||
}
|
||||
if (!name.contains("."))
|
||||
{
|
||||
instance.getLogger().warn(
|
||||
"Couldn't find class definition, suspecting incomplete path. Attempting autocompletion of path by adding a package name and trying again.");
|
||||
if (removeDynamicModule(name.toLowerCase() + "." + name))
|
||||
return true;
|
||||
}
|
||||
if (!name.startsWith("com.redstoner.modules."))
|
||||
{
|
||||
instance.getLogger().warn(
|
||||
"Couldn't find class definition, suspecting incomplete path. Attempting autocompletion of package name and trying again.");
|
||||
if (removeDynamicModule("com.redstoner.modules." + name))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Finds a module by name for other modules to reference it.
|
||||
*
|
||||
* @param name the name of the module. Use the full path if you are not sure about the module's SimpleClassName being unique.
|
||||
* @return the instance of the module or @null it none could be found */
|
||||
public static Module getModule(String name)
|
||||
{
|
||||
for (Module m : modules.keySet())
|
||||
if (m.getClass().getSimpleName().equalsIgnoreCase(name) || m.getClass().getName().equalsIgnoreCase(name))
|
||||
return m;
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Finds a module by name for other modules to reference it.
|
||||
*
|
||||
* @param name the name of the module. Use the full path if you are not sure about the module's SimpleClassName being unique.
|
||||
* @return the instance of the module or @null it none could be found */
|
||||
public static boolean exists(String name)
|
||||
{
|
||||
for (Module m : modules.keySet())
|
||||
if (m.getClass().getSimpleName().equals(name) || m.getClass().getName().equals(name))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static ModuleLogger getModuleLogger(Module module)
|
||||
{
|
||||
return loggers.get(module);
|
||||
}
|
||||
|
||||
public static void updateConfig()
|
||||
{
|
||||
List<String> coremods = config.getStringList("coremods");
|
||||
ArrayList<String> new_coremods = new ArrayList<>();
|
||||
List<String> autoload = config.getStringList("autoload");
|
||||
ArrayList<String> new_autoload = new ArrayList<>();
|
||||
|
||||
for (String s : coremods)
|
||||
{
|
||||
if (s.startsWith("#"))
|
||||
{
|
||||
new_coremods.add(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = s.split(" ")[0];
|
||||
try
|
||||
{
|
||||
new_coremods.add(getModule(s).getClass().getName() + " "
|
||||
+ VersionHelper.getVersion(getModule(s).getClass()));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
new_coremods.add(s + " " + VersionHelper.getString(VersionHelper.create(0, 0, 0, 0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String s : autoload)
|
||||
{
|
||||
if (s.startsWith("#"))
|
||||
{
|
||||
new_autoload.add(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
s = s.split(" ")[0];
|
||||
try
|
||||
{
|
||||
new_autoload.add(getModule(s).getClass().getName() + " "
|
||||
+ VersionHelper.getVersion(getModule(s).getClass()));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
new_autoload.add(s + " " + VersionHelper.getString(VersionHelper.create(0, 0, 0, 0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config.set("coremods", new_coremods);
|
||||
config.set("autoload", new_autoload);
|
||||
try
|
||||
{
|
||||
config.save(configFile);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.redstoner.exceptions;
|
||||
|
||||
import com.redstoner.annotations.Version;
|
||||
|
||||
/** To be thrown when a module is not annotated with its version. If this gets thrown, then oh boy, you're in trouble now.
|
||||
*
|
||||
* @author Pepich */
|
||||
@Version(major = 1, minor = 0, revision = 0, compatible = -1)
|
||||
public class MissingVersionException extends Exception
|
||||
{
|
||||
private static final long serialVersionUID = 4940161335512222539L;
|
||||
|
||||
public MissingVersionException()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public MissingVersionException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.redstoner.exceptions;
|
||||
|
||||
public class NonSaveableConfigException extends Exception {
|
||||
private static final long serialVersionUID = -7271481973389455510L;
|
||||
|
||||
public NonSaveableConfigException() {
|
||||
super("This config does not support saving!");
|
||||
}
|
||||
}
|
||||
14
src/main/java/com/redstoner/misc/BroadcastFilter.java
Normal file
14
src/main/java/com/redstoner/misc/BroadcastFilter.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package com.redstoner.misc;
|
||||
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.redstoner.annotations.Version;
|
||||
|
||||
/** Classes implementing this interface can be used to define a filter for the Utils.broadcast method for sending a message to more than one, but less than all users.
|
||||
*
|
||||
* @author Pepich */
|
||||
@Version(major = 1, minor = 0, revision = 0, compatible = 1)
|
||||
public interface BroadcastFilter
|
||||
{
|
||||
public boolean sendTo(CommandSender recipient);
|
||||
}
|
||||
13
src/main/java/com/redstoner/misc/CommandHolderType.java
Normal file
13
src/main/java/com/redstoner/misc/CommandHolderType.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package com.redstoner.misc;
|
||||
|
||||
import com.redstoner.annotations.Version;
|
||||
|
||||
/** @author Pepich */
|
||||
@Version(major = 4, minor = 0, revision = 0, compatible = -1)
|
||||
public enum CommandHolderType
|
||||
{
|
||||
Stream,
|
||||
File,
|
||||
String,
|
||||
None
|
||||
}
|
||||
149
src/main/java/com/redstoner/misc/JsonManager.java
Normal file
149
src/main/java/com/redstoner/misc/JsonManager.java
Normal file
@@ -0,0 +1,149 @@
|
||||
package com.redstoner.misc;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.redstoner.annotations.Version;
|
||||
|
||||
/** This class provides simple JSON handling, like storing and loading from and to files.
|
||||
*
|
||||
* @author Pepich */
|
||||
@Version(major = 1, minor = 0, revision = 2, compatible = -1)
|
||||
public class JsonManager
|
||||
{
|
||||
private JsonManager()
|
||||
{}
|
||||
|
||||
/** Loads a JSONObject from a file.
|
||||
*
|
||||
* @param source the file to load from.
|
||||
* @return the JSONObject or null if the source does not contain a valid JSONObject. */
|
||||
public static JSONObject getObject(File source)
|
||||
{
|
||||
if (!source.exists())
|
||||
return null;
|
||||
JSONParser parser = new JSONParser();
|
||||
try
|
||||
{
|
||||
FileReader reader = new FileReader(source);
|
||||
Object rawObject = parser.parse(reader);
|
||||
reader.close();
|
||||
JSONObject jsonObject = (JSONObject) rawObject;
|
||||
return jsonObject;
|
||||
}
|
||||
catch (IOException | ParseException e)
|
||||
{}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Saves a JSONObject to a file. Will create the necessary FileStructure like folders and the file itself.</br>
|
||||
* Note that this operation will be run on a different thread and you do not need to take care of that yourself.
|
||||
*
|
||||
* @param object the JSONObject to save.
|
||||
* @param destination the file to write to. */
|
||||
public static void save(JSONObject object, File destination)
|
||||
{
|
||||
Thread t = new Thread(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
saveSync(object, destination);
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
}
|
||||
|
||||
/** Saves a JSONObject to a file. Will create the necessary FileStructure like folders and the file itself.</br>
|
||||
* Note that this operation will be run on the same thread that you are calling it from!
|
||||
*
|
||||
* @param object the JSONObject to save.
|
||||
* @param destination the file to write to. */
|
||||
public static void saveSync(JSONObject object, File destination)
|
||||
{
|
||||
if (destination.exists())
|
||||
destination.delete();
|
||||
else if (!destination.getParentFile().exists())
|
||||
destination.getParentFile().mkdirs();
|
||||
try
|
||||
{
|
||||
destination.createNewFile();
|
||||
FileWriter writer = new FileWriter(destination);
|
||||
String json_string = object.toJSONString();
|
||||
writer.write(json_string);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{}
|
||||
}
|
||||
|
||||
/** Loads a JSONArray from a file.
|
||||
*
|
||||
* @param source the file to load from.
|
||||
* @return the JSONArray or null if the source does not contain a valid JSONArray. */
|
||||
public static JSONArray getArray(File source)
|
||||
{
|
||||
if (!source.exists())
|
||||
return null;
|
||||
JSONParser parser = new JSONParser();
|
||||
try
|
||||
{
|
||||
Object rawObject = parser.parse(new FileReader(source));
|
||||
JSONArray jsonArray = (JSONArray) rawObject;
|
||||
return jsonArray;
|
||||
}
|
||||
catch (IOException | ParseException e)
|
||||
{}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Saves a JSONArray to a file. Will create the necessary FileStructure like folders and the file itself.</br>
|
||||
* Note that this operation will be run on a different thread and you do not need to take care of that yourself.
|
||||
*
|
||||
* @param object the JSONArray to save.
|
||||
* @param destination the file to write to. */
|
||||
public static void save(JSONArray array, File destination)
|
||||
{
|
||||
Thread t = new Thread(new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
saveSync(array, destination);
|
||||
}
|
||||
});
|
||||
t.start();
|
||||
}
|
||||
|
||||
/** Saves a JSONArray to a file. Will create the necessary FileStructure like folders and the file itself.</br>
|
||||
* Note that this operation will be run on the same thread that you are calling it from!
|
||||
*
|
||||
* @param object the JSONArray to save.
|
||||
* @param destination the file to write to. */
|
||||
public static void saveSync(JSONArray array, File destination)
|
||||
{
|
||||
if (destination.exists())
|
||||
destination.delete();
|
||||
else if (!destination.getParentFile().exists())
|
||||
destination.getParentFile().mkdirs();
|
||||
try
|
||||
{
|
||||
destination.createNewFile();
|
||||
FileWriter writer = new FileWriter(destination);
|
||||
String json_string = array.toJSONString();
|
||||
writer.write(json_string);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{}
|
||||
}
|
||||
}
|
||||
36
src/main/java/com/redstoner/misc/Main.java
Normal file
36
src/main/java/com/redstoner/misc/Main.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package com.redstoner.misc;
|
||||
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import com.redstoner.annotations.Version;
|
||||
import com.redstoner.coremods.moduleLoader.ModuleLoader;
|
||||
import com.redstoner.misc.mysql.MysqlHandler;
|
||||
|
||||
import net.nemez.chatapi.ChatAPI;
|
||||
|
||||
/** Main class. Duh.
|
||||
*
|
||||
* @author Pepich */
|
||||
@Version(major = 4, minor = 0, revision = 0, compatible = -1)
|
||||
public class Main extends JavaPlugin
|
||||
{
|
||||
public static JavaPlugin plugin;
|
||||
|
||||
@Override
|
||||
public void onEnable()
|
||||
{
|
||||
plugin = this;
|
||||
ChatAPI.initialize(this);
|
||||
// Configger.init();
|
||||
MysqlHandler.init();
|
||||
ModuleLoader.init();
|
||||
// Load modules from config
|
||||
ModuleLoader.loadFromConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable()
|
||||
{
|
||||
ModuleLoader.disableModules();
|
||||
}
|
||||
}
|
||||
149
src/main/java/com/redstoner/misc/Utils.java
Normal file
149
src/main/java/com/redstoner/misc/Utils.java
Normal file
@@ -0,0 +1,149 @@
|
||||
package com.redstoner.misc;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import com.redstoner.annotations.Version;
|
||||
|
||||
/** The utils class containing utility functions. Those include but are not limited to sending formatted messages, broadcasts and more.
|
||||
*
|
||||
* @author Pepich */
|
||||
@Version(major = 4, minor = 0, revision = 2, compatible = 1)
|
||||
public final class Utils
|
||||
{
|
||||
/** The @SimpleDateFormat used for getting the current date. */
|
||||
public static SimpleDateFormat dateFormat = new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]");
|
||||
|
||||
/** The Pattern for a UUID*/
|
||||
private static final Pattern UUID_pattern = Pattern.compile("[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}");
|
||||
private static final Pattern Class_pattern = Pattern.compile(".*\\.");
|
||||
private static final Pattern NoDolarSign_pattern = Pattern.compile("\\$\\d*");
|
||||
|
||||
/** Hidden constructor. Do not instantiate UTILS classes! :) */
|
||||
private 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.</br>
|
||||
* If you want to, you can set a message that will be logged to console. Set to null to not log anything.</br>
|
||||
* 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.</br>
|
||||
* 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).
|
||||
* @return the amount of people that received the message. */
|
||||
public static int broadcast(String prefix, String message, BroadcastFilter filter)
|
||||
{
|
||||
if (prefix == null)
|
||||
prefix = "§8[§2" + getCaller() + "§8]: ";
|
||||
if (filter == null)
|
||||
{
|
||||
for (Player p : Bukkit.getOnlinePlayers())
|
||||
p.sendMessage(prefix + message);
|
||||
Bukkit.getConsoleSender().sendMessage(prefix + message);
|
||||
return Bukkit.getOnlinePlayers().size() + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = 0;
|
||||
for (Player p : Bukkit.getOnlinePlayers())
|
||||
if (filter.sendTo(p))
|
||||
{
|
||||
p.sendMessage(prefix + message);
|
||||
count++;
|
||||
}
|
||||
if (filter.sendTo(Bukkit.getConsoleSender()))
|
||||
{
|
||||
Bukkit.getConsoleSender().sendMessage(prefix + message);
|
||||
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. */
|
||||
private static final String getCaller()
|
||||
{
|
||||
StackTraceElement[] stackTrace = (new Exception()).getStackTrace();
|
||||
String classname = "Utils";
|
||||
for (int i = 0; classname.equals("Utils"); i++)
|
||||
{
|
||||
classname = Class_pattern.matcher(stackTrace[i].getClassName()).replaceAll("");
|
||||
}
|
||||
return classname;
|
||||
}
|
||||
|
||||
/** This method will find the next parent caller and return their class name, omitting package names.
|
||||
*
|
||||
* @param directCaller used to prevent this method from returning the caller itself. Null if supposed to be ignored.
|
||||
* @return the name of the calling class. */
|
||||
public static final String getCaller(String... directCaller)
|
||||
{
|
||||
if (directCaller == null || directCaller.length == 0)
|
||||
return getCaller();
|
||||
StackTraceElement[] stackTrace = (new Exception()).getStackTrace();
|
||||
String classname = "Utils";
|
||||
List<String> callers = Arrays.asList(directCaller);
|
||||
for (int i = 0; callers.contains(classname) || classname.equals("Utils"); i++)
|
||||
{
|
||||
classname = Class_pattern.matcher(stackTrace[i].getClassName()).replaceAll("");
|
||||
}
|
||||
classname = NoDolarSign_pattern.matcher(classname).replaceAll("");
|
||||
return classname;
|
||||
}
|
||||
|
||||
/** Provides a uniform way of getting the date for all modules.
|
||||
*
|
||||
* @return The current date in the format "[dd-mm-yyyy hh:mm:ss]" */
|
||||
public static String getDate()
|
||||
{
|
||||
Date date = new Date(System.currentTimeMillis());
|
||||
return dateFormat.format(date);
|
||||
}
|
||||
|
||||
/** Provides a uniform way of getting the (display)name of a @CommandSender.
|
||||
*
|
||||
* @param sender The @CommandSender to get the name of.
|
||||
* @return The DisplayName of the @CommandSender or if not a @Player, the name in blue. */
|
||||
public static String getName(CommandSender sender)
|
||||
{
|
||||
if (sender instanceof Player)
|
||||
return ((Player) sender).getDisplayName();
|
||||
else
|
||||
return "§9" + sender.getName();
|
||||
}
|
||||
|
||||
/** Provides a uniform way of getting the UUID of a @CommandSender.
|
||||
*
|
||||
* @param sender The @CommandSender to get the UUID of.
|
||||
* @return The UUID of the @CommandSender or if not a player, "CONSOLE" in blue. */
|
||||
public static String getID(CommandSender sender)
|
||||
{
|
||||
String id;
|
||||
if (sender instanceof Player)
|
||||
id = ((Player) sender).getUniqueId().toString();
|
||||
else
|
||||
id = "CONSOLE";
|
||||
return id;
|
||||
}
|
||||
|
||||
/** Checks if the string is a UUID.
|
||||
*
|
||||
* @param toCheck String to check.
|
||||
* @return if the string is a UUID.
|
||||
*/
|
||||
public static boolean isUUID(String toCheck)
|
||||
{
|
||||
return UUID_pattern.matcher(toCheck).matches();
|
||||
}
|
||||
}
|
||||
151
src/main/java/com/redstoner/misc/VersionHelper.java
Normal file
151
src/main/java/com/redstoner/misc/VersionHelper.java
Normal file
@@ -0,0 +1,151 @@
|
||||
package com.redstoner.misc;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
import com.redstoner.annotations.Version;
|
||||
import com.redstoner.exceptions.MissingVersionException;
|
||||
|
||||
/** This class can be used to compare modules against the loader version or against each other to prevent dependency issues.
|
||||
*
|
||||
* @author Pepich */
|
||||
@Version(major = 2, minor = 1, revision = 3, compatible = 0)
|
||||
public final class VersionHelper
|
||||
{
|
||||
private VersionHelper()
|
||||
{}
|
||||
|
||||
/** Checks two classes versions for compatibility.
|
||||
*
|
||||
* @param base The API to compare to.
|
||||
* @param module The module to compare.
|
||||
* @return true, when the module is up to date with the API, or the API supports outdated modules.
|
||||
* @throws MissingVersionException When one of the parameters is not annotated with a @Version annotation. */
|
||||
public static boolean isCompatible(Class<?> api, Class<?> module) throws MissingVersionException
|
||||
{
|
||||
if (!api.isAnnotationPresent(Version.class))
|
||||
throw new MissingVersionException("The API is not annotated with a version.");
|
||||
if (!module.isAnnotationPresent(Version.class))
|
||||
throw new MissingVersionException("The module is not annotated with a version.");
|
||||
Version apiVersion = api.getAnnotation(Version.class);
|
||||
Version moduleVersion = module.getAnnotation(Version.class);
|
||||
return isCompatible(apiVersion, moduleVersion);
|
||||
}
|
||||
|
||||
/** Checks two classes versions for compatibility.
|
||||
*
|
||||
* @param base The API to compare to.
|
||||
* @param module The module to compare.
|
||||
* @return true, when the module is up to date with the API, or the API supports outdated modules.
|
||||
* @throws MissingVersionException When one of the parameters is not annotated with a @Version annotation. */
|
||||
public static boolean isCompatible(Version apiVersion, Class<?> module) throws MissingVersionException
|
||||
{
|
||||
if (!module.isAnnotationPresent(Version.class))
|
||||
throw new MissingVersionException("The module is not annotated with a version.");
|
||||
Version moduleVersion = module.getAnnotation(Version.class);
|
||||
return isCompatible(apiVersion, moduleVersion);
|
||||
}
|
||||
|
||||
/** Checks two classes versions for compatibility.
|
||||
*
|
||||
* @param base The API to compare to.
|
||||
* @param module The module to compare.
|
||||
* @return true, when the module is up to date with the API, or the API supports outdated modules.
|
||||
* @throws MissingVersionException When one of the parameters is not annotated with a @Version annotation. */
|
||||
public static boolean isCompatible(Class<?> api, Version moduleVersion) throws MissingVersionException
|
||||
{
|
||||
if (!api.isAnnotationPresent(Version.class))
|
||||
throw new MissingVersionException("The API is not annotated with a version.");
|
||||
Version apiVersion = api.getAnnotation(Version.class);
|
||||
return isCompatible(apiVersion, moduleVersion);
|
||||
}
|
||||
|
||||
/** Checks two versions for compatibility.
|
||||
*
|
||||
* @param base The API version to compare to.
|
||||
* @param module The module version to compare.
|
||||
* @return true, when the module is up to date with the API, or the API supports outdated modules. */
|
||||
public static boolean isCompatible(Version apiVersion, Version moduleVersion)
|
||||
{
|
||||
if (apiVersion.major() >= moduleVersion.compatible())
|
||||
return true;
|
||||
if (apiVersion.compatible() == -1)
|
||||
return false;
|
||||
if (apiVersion.compatible() <= moduleVersion.major())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns the version of a given class as a String.
|
||||
*
|
||||
* @param clazz The class to grab the version number from.
|
||||
* @return The version number of the class in format major.minor.revision.compatible.
|
||||
* @throws MissingVersionException If the class is not annotated with @Version. */
|
||||
public static String getVersion(Class<?> clazz) throws MissingVersionException
|
||||
{
|
||||
if (!clazz.isAnnotationPresent(Version.class))
|
||||
throw new MissingVersionException("The given class is not associated with a version.");
|
||||
Version ver = clazz.getAnnotation(Version.class);
|
||||
return getString(ver);
|
||||
}
|
||||
|
||||
/** Returns the String representation of a version.
|
||||
*
|
||||
* @param ver The version to be represented.
|
||||
* @return The String representation. */
|
||||
public static String getString(Version ver)
|
||||
{
|
||||
return ver.major() + "." + ver.minor() + "." + ver.revision() + "." + ver.compatible();
|
||||
}
|
||||
|
||||
public static Version getVersion(String ver)
|
||||
{
|
||||
String[] raw = ver.split("\\.");
|
||||
if (raw.length != 4)
|
||||
return null;
|
||||
return VersionHelper.create(Integer.parseInt(raw[0]), Integer.parseInt(raw[1]), Integer.parseInt(raw[2]),
|
||||
Integer.parseInt(raw[3]));
|
||||
}
|
||||
|
||||
/** This method creates a new Version to use for compatibility checks.
|
||||
*
|
||||
* @param major The major version
|
||||
* @param minor The minor version
|
||||
* @param revision The revision
|
||||
* @param compatible The compatibility tag
|
||||
* @return */
|
||||
public static Version create(int major, int minor, int revision, int compatible)
|
||||
{
|
||||
return new Version()
|
||||
{
|
||||
@Override
|
||||
public Class<? extends Annotation> annotationType()
|
||||
{
|
||||
return Version.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int revision()
|
||||
{
|
||||
return revision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int minor()
|
||||
{
|
||||
return minor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int major()
|
||||
{
|
||||
return major;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compatible()
|
||||
{
|
||||
return compatible;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
278
src/main/java/com/redstoner/misc/mysql/Config.java
Normal file
278
src/main/java/com/redstoner/misc/mysql/Config.java
Normal file
@@ -0,0 +1,278 @@
|
||||
package com.redstoner.misc.mysql;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.redstoner.exceptions.NonSaveableConfigException;
|
||||
import com.redstoner.misc.Main;
|
||||
|
||||
public class Config
|
||||
{
|
||||
private File file;
|
||||
private JSONObject config;
|
||||
private JSONParser parser;
|
||||
|
||||
public Config()
|
||||
{
|
||||
file = null;
|
||||
parser = new JSONParser();
|
||||
config = new JSONObject();
|
||||
}
|
||||
|
||||
public Config(JSONObject config)
|
||||
{
|
||||
this.file = null;
|
||||
this.parser = new JSONParser();
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
private Config(File file) throws IOException, ParseException
|
||||
{
|
||||
this.file = file;
|
||||
parser = new JSONParser();
|
||||
if (file.exists())
|
||||
{
|
||||
config = loadConfig(file);
|
||||
}
|
||||
else
|
||||
{
|
||||
config = new JSONObject();
|
||||
}
|
||||
}
|
||||
|
||||
public static final Config getConfig(String fileName) throws IOException, ParseException
|
||||
{
|
||||
return new Config(new File(Main.plugin.getDataFolder(), fileName));
|
||||
}
|
||||
|
||||
public static final Config getConfig(File file) throws IOException, ParseException
|
||||
{
|
||||
return new Config(file);
|
||||
}
|
||||
|
||||
private JSONObject loadConfig(File file) throws IOException, ParseException
|
||||
{
|
||||
FileReader reader = new FileReader(file);
|
||||
return (JSONObject) parser.parse(reader);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return config.toJSONString();
|
||||
}
|
||||
|
||||
public JSONObject asObject()
|
||||
{
|
||||
return config;
|
||||
}
|
||||
|
||||
public void save() throws IOException, NonSaveableConfigException
|
||||
{
|
||||
if (file == null)
|
||||
{
|
||||
throw new NonSaveableConfigException();
|
||||
}
|
||||
PrintWriter writer = new PrintWriter(file);
|
||||
writer.write(config.toJSONString());
|
||||
writer.close();
|
||||
}
|
||||
|
||||
public void refresh() throws IOException, ParseException, NonSaveableConfigException
|
||||
{
|
||||
if (file == null)
|
||||
{
|
||||
throw new NonSaveableConfigException();
|
||||
}
|
||||
loadConfig(file);
|
||||
}
|
||||
|
||||
public void setFile(String fileName)
|
||||
{
|
||||
file = new File(Main.plugin.getDataFolder(), fileName);
|
||||
}
|
||||
|
||||
public void setFile(File file)
|
||||
{
|
||||
this.file = file;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void put(String key, String value)
|
||||
{
|
||||
config.put(key, value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void put(String key, List<String> value)
|
||||
{
|
||||
JSONArray array = new JSONArray();
|
||||
for (String entry : value)
|
||||
{
|
||||
array.add(entry);
|
||||
}
|
||||
config.put(key, array);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void putArray(String key, JSONArray value)
|
||||
{
|
||||
config.put(key, value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void put(String key, Map<String, String> value)
|
||||
{
|
||||
JSONObject object = new JSONObject();
|
||||
for (String valKey : value.keySet())
|
||||
{
|
||||
String valVal = value.get(valKey);
|
||||
object.put(valKey, valVal);
|
||||
}
|
||||
config.put(key, object);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void put(String key, JSONObject value)
|
||||
{
|
||||
config.put(key, value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void putAll(Map<String, String> entry)
|
||||
{
|
||||
for (String key : entry.keySet())
|
||||
{
|
||||
String value = entry.get(key);
|
||||
config.put(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsKey(String key)
|
||||
{
|
||||
return config.containsKey(key);
|
||||
}
|
||||
|
||||
public String get(String key)
|
||||
{
|
||||
if (containsKey(key))
|
||||
{
|
||||
Object value = config.get(key);
|
||||
if (value instanceof String)
|
||||
{
|
||||
return (String) value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getOrDefault(String key, String defaultValue)
|
||||
{
|
||||
if (containsKey(key))
|
||||
{
|
||||
Object value = config.get(key);
|
||||
if (value instanceof String)
|
||||
{
|
||||
return (String) value;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<String> getList(String key)
|
||||
{
|
||||
if (containsKey(key))
|
||||
{
|
||||
Object value = config.get(key);
|
||||
if (value instanceof JSONArray)
|
||||
{
|
||||
JSONArray array = (JSONArray) value;
|
||||
List<String> output = new ArrayList<String>();
|
||||
for (String entry : (String[]) array.toArray(new String[0]))
|
||||
{
|
||||
output.add(entry);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public JSONArray getArray(String key)
|
||||
{
|
||||
if (containsKey(key))
|
||||
{
|
||||
Object value = config.get(key);
|
||||
if (value instanceof JSONArray)
|
||||
{
|
||||
JSONArray array = (JSONArray) value;
|
||||
return array;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Map<String, String> getMap(String key)
|
||||
{
|
||||
if (containsKey(key))
|
||||
{
|
||||
Object value = config.get(key);
|
||||
if (value instanceof JSONObject)
|
||||
{
|
||||
JSONObject object = (JSONObject) value;
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<Map.Entry<String, String>> entrySet = object.entrySet();
|
||||
Map<String, String> output = new HashMap<String, String>();
|
||||
for (Map.Entry<String, String> entry : entrySet)
|
||||
{
|
||||
output.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public JSONObject getObject(String key)
|
||||
{
|
||||
if (containsKey(key))
|
||||
{
|
||||
Object value = config.get(key);
|
||||
if (value instanceof JSONObject)
|
||||
{
|
||||
JSONObject object = (JSONObject) value;
|
||||
return object;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void remove(String key)
|
||||
{
|
||||
config.remove(key);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<Entry<String, String>> getAll()
|
||||
{
|
||||
return config.entrySet();
|
||||
}
|
||||
}
|
||||
107
src/main/java/com/redstoner/misc/mysql/JSONManager.java
Normal file
107
src/main/java/com/redstoner/misc/mysql/JSONManager.java
Normal file
@@ -0,0 +1,107 @@
|
||||
package com.redstoner.misc.mysql;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import org.json.simple.parser.JSONParser;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.redstoner.misc.Main;
|
||||
|
||||
public class JSONManager
|
||||
{
|
||||
public static Map<Serializable, Serializable> getConfiguration(String fileName)
|
||||
{
|
||||
File file = new File(Main.plugin.getDataFolder(), fileName);
|
||||
if (!file.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
PrintWriter writer = new PrintWriter(file.getAbsolutePath(), "UTF-8");
|
||||
writer.println("{}");
|
||||
writer.close();
|
||||
}
|
||||
catch (FileNotFoundException | UnsupportedEncodingException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
return loadMap(file);
|
||||
}
|
||||
catch (IOException | ParseException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void saveConfiguration(Map<Serializable, Serializable> config, String fileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
saveMap(new File(Main.plugin.getDataFolder(), fileName), config);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void saveList(File file, List<Serializable> entries) throws IOException
|
||||
{
|
||||
JSONArray array = new JSONArray();
|
||||
array.addAll(entries);
|
||||
FileWriter writer = new FileWriter(file);
|
||||
writer.write(array.toJSONString());
|
||||
writer.close();
|
||||
}
|
||||
|
||||
public static List<Serializable> loadList(File file) throws IOException, ParseException
|
||||
{
|
||||
FileReader read = new FileReader(file);
|
||||
List<Serializable> entries = new ArrayList<>();
|
||||
JSONArray array = (JSONArray) new JSONParser().parse(read);
|
||||
for (Object o : array)
|
||||
{
|
||||
entries.add((Serializable) o);
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void saveMap(File file, Map<Serializable, Serializable> entries) throws IOException
|
||||
{
|
||||
JSONObject map = new JSONObject();
|
||||
map.putAll(entries);
|
||||
FileWriter writer = new FileWriter(file);
|
||||
writer.write(map.toJSONString());
|
||||
writer.close();
|
||||
}
|
||||
|
||||
public static Map<Serializable, Serializable> loadMap(File file) throws IOException, ParseException
|
||||
{
|
||||
FileReader reader = new FileReader(file);
|
||||
JSONObject map = (JSONObject) new JSONParser().parse(reader);
|
||||
Map<Serializable, Serializable> entries = new HashMap<>();
|
||||
for (Object o : map.keySet())
|
||||
{
|
||||
entries.put((Serializable) o, (Serializable) map.get(o));
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
115
src/main/java/com/redstoner/misc/mysql/MysqlHandler.java
Normal file
115
src/main/java/com/redstoner/misc/mysql/MysqlHandler.java
Normal file
@@ -0,0 +1,115 @@
|
||||
package com.redstoner.misc.mysql;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.json.simple.parser.ParseException;
|
||||
|
||||
import com.redstoner.misc.Main;
|
||||
import com.redstoner.misc.mysql.elements.MysqlDatabase;
|
||||
|
||||
public class MysqlHandler
|
||||
{
|
||||
public static MysqlHandler INSTANCE;
|
||||
private String url, username, password;
|
||||
|
||||
public MysqlHandler(String hostname, int port, String username, String password)
|
||||
{
|
||||
this.url = "jdbc:mysql://" + hostname + ":" + port + "/";
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public static void init()
|
||||
{
|
||||
Map<Serializable, Serializable> mysqlCredentials = new HashMap<>();
|
||||
File mysqlCredentialsFile = new File(Main.plugin.getDataFolder(), "mysqlCredentials.json");
|
||||
if (mysqlCredentialsFile.exists())
|
||||
{
|
||||
try
|
||||
{
|
||||
mysqlCredentials = JSONManager.loadMap(mysqlCredentialsFile);
|
||||
}
|
||||
catch (IOException | ParseException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Bukkit.getConsoleSender().sendMessage(
|
||||
ChatColor.RED + "MySQL config does not exist, creating an example one, things might (will) break!");
|
||||
mysqlCredentials.put("hostname", "localhost");
|
||||
mysqlCredentials.put("port", "3306");
|
||||
mysqlCredentials.put("username", "your username here");
|
||||
mysqlCredentials.put("password", "your password here");
|
||||
try
|
||||
{
|
||||
JSONManager.saveMap(mysqlCredentialsFile, mysqlCredentials);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
String hostname = (String) mysqlCredentials.get("hostname");
|
||||
int port = Integer.valueOf((String) mysqlCredentials.get("port"));
|
||||
String username = (String) mysqlCredentials.get("username");
|
||||
String password = (String) mysqlCredentials.get("password");
|
||||
INSTANCE = new MysqlHandler(hostname, port, username, password);
|
||||
}
|
||||
|
||||
private Connection getConnection(String databaseName) throws IllegalStateException
|
||||
{
|
||||
Connection connection = null;
|
||||
try
|
||||
{
|
||||
connection = DriverManager.getConnection(url + databaseName, username, password);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
throw new IllegalStateException("Cannot connect to the database!", e);
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
public MysqlDatabase getDatabase(String databaseName)
|
||||
{
|
||||
return new MysqlDatabase(getConnection(databaseName));
|
||||
}
|
||||
|
||||
public List<MysqlDatabase> getDatabases()
|
||||
{
|
||||
try
|
||||
{
|
||||
List<MysqlDatabase> databases = new ArrayList<>();
|
||||
Connection connection = DriverManager.getConnection(url.substring(0, url.length()), username, password);
|
||||
DatabaseMetaData metadata = connection.getMetaData();
|
||||
ResultSet queryResults = metadata.getCatalogs();
|
||||
while (queryResults.next())
|
||||
{
|
||||
String databaseName = queryResults.getString("TABLE_CAT");
|
||||
databases.add(new MysqlDatabase(getConnection(databaseName)));
|
||||
}
|
||||
connection.close();
|
||||
return databases;
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.redstoner.misc.mysql;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
|
||||
public class MysqlQueryHandler {
|
||||
public static ResultSet queryResult(Connection connection, String query) {
|
||||
try {
|
||||
Statement statement = connection.createStatement();
|
||||
ResultSet results = statement.executeQuery(query);
|
||||
|
||||
return results;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean queryNoResult(Connection connection, String query) {
|
||||
try {
|
||||
CallableStatement statement = connection.prepareCall(query);
|
||||
statement.execute();
|
||||
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.redstoner.misc.mysql.elements;
|
||||
|
||||
public enum ConstraintOperator {
|
||||
LESS_THAN, GREATER_THAN, EQUAL, NOT_EQUAL, LESS_THAN_OR_EQUAL, GREATER_THAN_OR_EQUAL;
|
||||
|
||||
public String toString() {
|
||||
switch (this) {
|
||||
case LESS_THAN:
|
||||
return "<";
|
||||
case GREATER_THAN:
|
||||
return ">";
|
||||
case EQUAL:
|
||||
return "=";
|
||||
case NOT_EQUAL:
|
||||
return "!=";
|
||||
case LESS_THAN_OR_EQUAL:
|
||||
return "<=";
|
||||
case GREATER_THAN_OR_EQUAL:
|
||||
return ">=";
|
||||
default:
|
||||
return "=";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.redstoner.misc.mysql.elements;
|
||||
|
||||
public class MysqlConstraint {
|
||||
private String fieldName, value;
|
||||
private ConstraintOperator operator;
|
||||
|
||||
public MysqlConstraint(String fieldName, ConstraintOperator operator, String value) {
|
||||
this.fieldName = fieldName;
|
||||
this.operator = operator;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getFieldName() {
|
||||
return fieldName;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public ConstraintOperator getOperator() {
|
||||
return operator;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.redstoner.misc.mysql.elements;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.redstoner.misc.mysql.MysqlQueryHandler;
|
||||
|
||||
public class MysqlDatabase {
|
||||
private Connection connection;
|
||||
|
||||
public MysqlDatabase(Connection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
try {
|
||||
return connection.getCatalog();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public MysqlTable getTable(String name) {
|
||||
return new MysqlTable(this, name);
|
||||
}
|
||||
|
||||
public boolean createTable(String name, MysqlField... description) {
|
||||
return MysqlQueryHandler.queryNoResult(connection, "CREATE TABLE `" + name + "` " + getDescription(description) + ";");
|
||||
}
|
||||
|
||||
public boolean createTableIfNotExists(String name, MysqlField... description) {
|
||||
return MysqlQueryHandler.queryNoResult(connection, "CREATE TABLE IF NOT EXISTS `" + name + "` " + getDescription(description) + ";");
|
||||
}
|
||||
|
||||
public boolean dropTable(String name) {
|
||||
return MysqlQueryHandler.queryNoResult(connection, "DROP TABLE `" + name + "`;");
|
||||
}
|
||||
|
||||
public boolean drop() {
|
||||
return MysqlQueryHandler.queryNoResult(connection, "DROP DATABASE `" + getName() + "`;");
|
||||
}
|
||||
|
||||
public List<MysqlTable> getTables() {
|
||||
try {
|
||||
List<MysqlTable> tables = new ArrayList<>();
|
||||
DatabaseMetaData metadata = connection.getMetaData();
|
||||
ResultSet queryResults = metadata.getTables(null, null, "%", null);
|
||||
|
||||
while (queryResults.next()) {
|
||||
tables.add(new MysqlTable(this, queryResults.getString(3)));
|
||||
}
|
||||
|
||||
return tables;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected Connection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
||||
private String getDescription(MysqlField... description) {
|
||||
String desc = "(";
|
||||
|
||||
for (int i = 0; i < description.length; i++) {
|
||||
String nil = "";
|
||||
|
||||
if (description[i].canBeNull()) {
|
||||
nil = " NOT NULL";
|
||||
}
|
||||
|
||||
desc += "`" + description[i].getName() + "` " + description[i].getType().getName() + nil;
|
||||
|
||||
if (i < description.length - 1) {
|
||||
desc += ",";
|
||||
}
|
||||
}
|
||||
|
||||
desc += ")";
|
||||
|
||||
return desc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.redstoner.misc.mysql.elements;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class MysqlField {
|
||||
private String name;
|
||||
private MysqlType type;
|
||||
private boolean canBeNull;
|
||||
|
||||
public MysqlField(String name, MysqlType type, boolean canBeNull) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.canBeNull = canBeNull;
|
||||
}
|
||||
|
||||
public MysqlField(String name, String type, boolean canBeNull) {
|
||||
this.name = name;
|
||||
this.type = MysqlType.getTypeFromString(type);
|
||||
this.canBeNull = canBeNull;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public MysqlType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public boolean canBeNull() {
|
||||
return canBeNull;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.redstoner.misc.mysql.elements;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class MysqlResult {
|
||||
private ResultSet results;
|
||||
|
||||
public MysqlResult(ResultSet results) {
|
||||
this.results = results;
|
||||
}
|
||||
|
||||
public Object getObject(int columnIndex, Class<?> type) throws SQLException {
|
||||
return results.getObject(columnIndex, type);
|
||||
}
|
||||
}
|
||||
133
src/main/java/com/redstoner/misc/mysql/elements/MysqlTable.java
Normal file
133
src/main/java/com/redstoner/misc/mysql/elements/MysqlTable.java
Normal file
@@ -0,0 +1,133 @@
|
||||
package com.redstoner.misc.mysql.elements;
|
||||
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.redstoner.misc.mysql.MysqlQueryHandler;
|
||||
|
||||
public class MysqlTable
|
||||
{
|
||||
private MysqlDatabase database;
|
||||
private String name;
|
||||
|
||||
public MysqlTable(MysqlDatabase database, String name)
|
||||
{
|
||||
this.database = database;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public MysqlField[] describe()
|
||||
{
|
||||
try
|
||||
{
|
||||
List<MysqlField> description = new ArrayList<>();
|
||||
DatabaseMetaData metadata = database.getConnection().getMetaData();
|
||||
ResultSet queryResults = metadata.getColumns(null, null, name, null);
|
||||
while (queryResults.next())
|
||||
{
|
||||
description.add(new MysqlField(queryResults.getString(4),
|
||||
queryResults.getString(6).split(" ")[0] + "(" + queryResults.getString(7) + ")",
|
||||
queryResults.getBoolean(11)));
|
||||
}
|
||||
return description.toArray(new MysqlField[0]);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean insert(String... values)
|
||||
{
|
||||
MysqlField[] description = describe();
|
||||
if (values.length > 0 && values.length == description.length)
|
||||
{
|
||||
String val = "(\"" + String.join("\",\"", values) + "\")";
|
||||
return MysqlQueryHandler.queryNoResult(database.getConnection(),
|
||||
"INSERT INTO `" + name + "` VALUES " + val + ";");
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Object[] get(String fieldName, MysqlConstraint... constraints)
|
||||
{
|
||||
ResultSet results = MysqlQueryHandler.queryResult(database.getConnection(),
|
||||
"SELECT " + fieldName + " FROM `" + name + "`" + getConstraints(constraints) + ";");
|
||||
List<Object> resObj = new ArrayList<>();
|
||||
try
|
||||
{
|
||||
while (results.next())
|
||||
{
|
||||
resObj.add(results.getObject(1));
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return new Object[0];
|
||||
}
|
||||
return resObj.toArray(new Object[0]);
|
||||
}
|
||||
|
||||
public Object[] get(String statement)
|
||||
{
|
||||
ResultSet results = MysqlQueryHandler.queryResult(database.getConnection(), statement);
|
||||
List<Object> resObj = new ArrayList<>();
|
||||
try
|
||||
{
|
||||
while (results.next())
|
||||
{
|
||||
resObj.add(results.getObject(1));
|
||||
}
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
return new Object[0];
|
||||
}
|
||||
return resObj.toArray(new Object[0]);
|
||||
}
|
||||
|
||||
public boolean delete(MysqlConstraint... constraints)
|
||||
{
|
||||
return MysqlQueryHandler.queryNoResult(database.getConnection(),
|
||||
"DELETE FROM `" + name + "`" + getConstraints(constraints) + ";");
|
||||
}
|
||||
|
||||
public boolean drop()
|
||||
{
|
||||
return MysqlQueryHandler.queryNoResult(database.getConnection(), "DROP TABLE `" + name + "`;");
|
||||
}
|
||||
|
||||
private String getConstraints(MysqlConstraint... constraints)
|
||||
{
|
||||
String cons = "";
|
||||
if (constraints.length > 0)
|
||||
{
|
||||
cons += " WHERE ";
|
||||
for (int i = 0; i < constraints.length; i++)
|
||||
{
|
||||
MysqlConstraint constraint = constraints[i];
|
||||
cons += constraint.getFieldName() + constraint.getOperator().toString() + "\"" + constraint.getValue()
|
||||
+ "\"";
|
||||
if (i < constraints.length - 1)
|
||||
{
|
||||
cons += " AND ";
|
||||
}
|
||||
}
|
||||
}
|
||||
return cons;
|
||||
}
|
||||
}
|
||||
96
src/main/java/com/redstoner/misc/mysql/types/MysqlType.java
Normal file
96
src/main/java/com/redstoner/misc/mysql/types/MysqlType.java
Normal file
@@ -0,0 +1,96 @@
|
||||
package com.redstoner.misc.mysql.types;
|
||||
|
||||
import com.redstoner.misc.mysql.types.date.Date;
|
||||
import com.redstoner.misc.mysql.types.date.DateTime;
|
||||
import com.redstoner.misc.mysql.types.date.Time;
|
||||
import com.redstoner.misc.mysql.types.date.TimeStamp;
|
||||
import com.redstoner.misc.mysql.types.date.Year;
|
||||
import com.redstoner.misc.mysql.types.number.BigInt;
|
||||
import com.redstoner.misc.mysql.types.number.Decimal;
|
||||
import com.redstoner.misc.mysql.types.number.Double;
|
||||
import com.redstoner.misc.mysql.types.number.Float;
|
||||
import com.redstoner.misc.mysql.types.number.Int;
|
||||
import com.redstoner.misc.mysql.types.number.MediumInt;
|
||||
import com.redstoner.misc.mysql.types.number.SmallInt;
|
||||
import com.redstoner.misc.mysql.types.number.TinyInt;
|
||||
import com.redstoner.misc.mysql.types.text.Blob;
|
||||
import com.redstoner.misc.mysql.types.text.Char;
|
||||
import com.redstoner.misc.mysql.types.text.Enum;
|
||||
import com.redstoner.misc.mysql.types.text.LongBlob;
|
||||
import com.redstoner.misc.mysql.types.text.LongText;
|
||||
import com.redstoner.misc.mysql.types.text.MediumBlob;
|
||||
import com.redstoner.misc.mysql.types.text.MediumText;
|
||||
import com.redstoner.misc.mysql.types.text.Set;
|
||||
import com.redstoner.misc.mysql.types.text.Text;
|
||||
import com.redstoner.misc.mysql.types.text.TinyText;
|
||||
import com.redstoner.misc.mysql.types.text.VarChar;
|
||||
|
||||
public abstract class MysqlType
|
||||
{
|
||||
public abstract String getName();
|
||||
|
||||
public static MysqlType getTypeFromString(String type)
|
||||
{
|
||||
String[] splitType = type.split("\\(");
|
||||
String toSwitch = splitType[0].toUpperCase();
|
||||
String value = "";
|
||||
if (type.contains("(") && type.endsWith(")"))
|
||||
{
|
||||
value = splitType[1].substring(0, splitType[1].length() - 1);
|
||||
}
|
||||
switch (toSwitch)
|
||||
{
|
||||
case "CHAR":
|
||||
return new Char(Integer.valueOf(value));
|
||||
case "ENUM":
|
||||
return new Enum(value.replaceAll("'", "").split(","));
|
||||
case "VARCHAR":
|
||||
return new VarChar(Integer.valueOf(value));
|
||||
case "SET":
|
||||
return new Set(value.replaceAll("'", "").split(","));
|
||||
case "BLOB":
|
||||
return new Blob();
|
||||
case "TEXT":
|
||||
return new Text();
|
||||
case "MEDIUMBLOB":
|
||||
return new MediumBlob();
|
||||
case "LONGBLOB":
|
||||
return new LongBlob();
|
||||
case "TINYTEXT":
|
||||
return new TinyText();
|
||||
case "MEDIUMTEXT":
|
||||
return new MediumText();
|
||||
case "LONGTEXT":
|
||||
return new LongText();
|
||||
case "INT":
|
||||
return new Int(Integer.valueOf(value));
|
||||
case "TINYINT":
|
||||
return new TinyInt(Integer.valueOf(value));
|
||||
case "SMALLINT":
|
||||
return new SmallInt(Integer.valueOf(value));
|
||||
case "MEDIUMINT":
|
||||
return new MediumInt(Integer.valueOf(value));
|
||||
case "BIGINT":
|
||||
return new BigInt(Integer.valueOf(value));
|
||||
case "BIT":
|
||||
return new TinyInt(1);
|
||||
case "FLOAT":
|
||||
return new Float();
|
||||
case "DOUBLE":
|
||||
return new Double();
|
||||
case "DECIMAL":
|
||||
return new Decimal();
|
||||
case "DATE":
|
||||
return new Date();
|
||||
case "DATETIME":
|
||||
return new DateTime();
|
||||
case "TIME":
|
||||
return new Time();
|
||||
case "TIMESTAMP":
|
||||
return new TimeStamp();
|
||||
case "YEAR":
|
||||
return new Year();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
10
src/main/java/com/redstoner/misc/mysql/types/date/Date.java
Normal file
10
src/main/java/com/redstoner/misc/mysql/types/date/Date.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package com.redstoner.misc.mysql.types.date;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class Date extends MysqlType {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "DATE";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.redstoner.misc.mysql.types.date;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class DateTime extends MysqlType {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "DATETIME";
|
||||
}
|
||||
}
|
||||
10
src/main/java/com/redstoner/misc/mysql/types/date/Time.java
Normal file
10
src/main/java/com/redstoner/misc/mysql/types/date/Time.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package com.redstoner.misc.mysql.types.date;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class Time extends MysqlType {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "TIME";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.redstoner.misc.mysql.types.date;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class TimeStamp extends MysqlType {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "TIMESTAMP";
|
||||
}
|
||||
}
|
||||
10
src/main/java/com/redstoner/misc/mysql/types/date/Year.java
Normal file
10
src/main/java/com/redstoner/misc/mysql/types/date/Year.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package com.redstoner.misc.mysql.types.date;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class Year extends MysqlType {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "YEAR";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.redstoner.misc.mysql.types.number;
|
||||
|
||||
public class BigInt extends Int {
|
||||
public BigInt(int maxSize) {
|
||||
super(maxSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "BIG" + super.getName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.redstoner.misc.mysql.types.number;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class Decimal extends MysqlType {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "DECIMAL";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.redstoner.misc.mysql.types.number;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class Double extends MysqlType {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "DOUBLE";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.redstoner.misc.mysql.types.number;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class Float extends MysqlType {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "FLOAT";
|
||||
}
|
||||
}
|
||||
16
src/main/java/com/redstoner/misc/mysql/types/number/Int.java
Normal file
16
src/main/java/com/redstoner/misc/mysql/types/number/Int.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.redstoner.misc.mysql.types.number;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class Int extends MysqlType {
|
||||
private int maxSize;
|
||||
|
||||
public Int(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "INT(" + maxSize + ")";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.redstoner.misc.mysql.types.number;
|
||||
|
||||
public class MediumInt extends Int {
|
||||
public MediumInt(int maxSize) {
|
||||
super(maxSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "MEDIUM" + super.getName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.redstoner.misc.mysql.types.number;
|
||||
|
||||
public class SmallInt extends Int {
|
||||
public SmallInt(int maxSize) {
|
||||
super(maxSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "SMALL" + super.getName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.redstoner.misc.mysql.types.number;
|
||||
|
||||
public class TinyInt extends Int {
|
||||
public TinyInt(int maxSize) {
|
||||
super(maxSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "TINY" + super.getName();
|
||||
}
|
||||
}
|
||||
10
src/main/java/com/redstoner/misc/mysql/types/text/Blob.java
Normal file
10
src/main/java/com/redstoner/misc/mysql/types/text/Blob.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package com.redstoner.misc.mysql.types.text;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class Blob extends MysqlType {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "BLOB";
|
||||
}
|
||||
}
|
||||
16
src/main/java/com/redstoner/misc/mysql/types/text/Char.java
Normal file
16
src/main/java/com/redstoner/misc/mysql/types/text/Char.java
Normal file
@@ -0,0 +1,16 @@
|
||||
package com.redstoner.misc.mysql.types.text;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class Char extends MysqlType {
|
||||
private int size;
|
||||
|
||||
public Char(int size) {
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "CHAR(" + size + ")";
|
||||
}
|
||||
}
|
||||
27
src/main/java/com/redstoner/misc/mysql/types/text/Enum.java
Normal file
27
src/main/java/com/redstoner/misc/mysql/types/text/Enum.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.redstoner.misc.mysql.types.text;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class Enum extends MysqlType {
|
||||
private String[] possibleValues;
|
||||
|
||||
public Enum(String... possibleValues) {
|
||||
this.possibleValues = possibleValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
String name = "ENUM(";
|
||||
|
||||
for (int i = 0; i < possibleValues.length; i++) {
|
||||
name += "'" + possibleValues[i] + "'";
|
||||
|
||||
if (i != possibleValues.length - 1) {
|
||||
name += ",";
|
||||
}
|
||||
}
|
||||
|
||||
return name + ")";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.redstoner.misc.mysql.types.text;
|
||||
|
||||
public class LongBlob extends Blob {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "LONG" + super.getName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.redstoner.misc.mysql.types.text;
|
||||
|
||||
public class LongText extends Text {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "LONG" + super.getName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.redstoner.misc.mysql.types.text;
|
||||
|
||||
public class MediumBlob extends Blob {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "MEDIUM" + super.getName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.redstoner.misc.mysql.types.text;
|
||||
|
||||
public class MediumText extends Text {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "MEDIUM" + super.getName();
|
||||
}
|
||||
}
|
||||
27
src/main/java/com/redstoner/misc/mysql/types/text/Set.java
Normal file
27
src/main/java/com/redstoner/misc/mysql/types/text/Set.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.redstoner.misc.mysql.types.text;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class Set extends MysqlType {
|
||||
private String[] possibleValues;
|
||||
|
||||
public Set(String... possibleValues) {
|
||||
this.possibleValues = possibleValues;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
String name = "SET(";
|
||||
|
||||
for (int i = 0; i < possibleValues.length; i++) {
|
||||
name += "'" + possibleValues[i] + "'";
|
||||
|
||||
if (i != possibleValues.length - 1) {
|
||||
name += ",";
|
||||
}
|
||||
}
|
||||
|
||||
return name + ")";
|
||||
}
|
||||
|
||||
}
|
||||
10
src/main/java/com/redstoner/misc/mysql/types/text/Text.java
Normal file
10
src/main/java/com/redstoner/misc/mysql/types/text/Text.java
Normal file
@@ -0,0 +1,10 @@
|
||||
package com.redstoner.misc.mysql.types.text;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class Text extends MysqlType {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "TEXT";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package com.redstoner.misc.mysql.types.text;
|
||||
|
||||
public class TinyText extends Text {
|
||||
@Override
|
||||
public String getName() {
|
||||
return "TINY" + super.getName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.redstoner.misc.mysql.types.text;
|
||||
|
||||
import com.redstoner.misc.mysql.types.MysqlType;
|
||||
|
||||
public class VarChar extends MysqlType {
|
||||
private int maxSize;
|
||||
|
||||
public VarChar(int maxSize) {
|
||||
this.maxSize = maxSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "VARCHAR(" + maxSize + ")";
|
||||
}
|
||||
}
|
||||
24
src/main/java/com/redstoner/modules/CoreModule.java
Normal file
24
src/main/java/com/redstoner/modules/CoreModule.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package com.redstoner.modules;
|
||||
|
||||
import com.redstoner.annotations.Version;
|
||||
|
||||
/** This class shall be used for "CoreModules", which are acting on a lower level than modules and are also exempted from being disabled or reloaded on the go.</br>
|
||||
* Please note that CoreModules will not be known to the ModuleLoader itself!</br>
|
||||
* Examples are the ModuleLoader and the Debugger.
|
||||
*
|
||||
* @author Pepich */
|
||||
@Version(major = 2, minor = 0, revision = 0, compatible = -1)
|
||||
public interface CoreModule extends Module
|
||||
{
|
||||
/** Core modules don't need to be enabled. */
|
||||
@Override
|
||||
public default boolean onEnable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Core modules don't need to be disabled. */
|
||||
@Override
|
||||
public default void onDisable()
|
||||
{}
|
||||
}
|
||||
54
src/main/java/com/redstoner/modules/Module.java
Normal file
54
src/main/java/com/redstoner/modules/Module.java
Normal file
@@ -0,0 +1,54 @@
|
||||
package com.redstoner.modules;
|
||||
|
||||
import com.redstoner.annotations.Version;
|
||||
import com.redstoner.coremods.moduleLoader.ModuleLoader;
|
||||
|
||||
/** Interface for the Module class. Modules must always have an empty constructor to be invoked by the ModuleLoader.
|
||||
*
|
||||
* @author Pepich */
|
||||
@Version(major = 4, minor = 0, revision = 0, compatible = 0)
|
||||
public interface Module
|
||||
{
|
||||
/** Will be called when the module gets enabled. */
|
||||
public default boolean onEnable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/** This methods gets called after all modules were enabled, please use this method to register commands and similar. <br/>
|
||||
* It will only get called if and only if the module was successfully enabled. */
|
||||
public default void postEnable()
|
||||
{}
|
||||
|
||||
/** Will be called when the module gets disabled. */
|
||||
public default void onDisable()
|
||||
{}
|
||||
|
||||
/** Gets called on registration of the module, when this option is selected for command registration
|
||||
*
|
||||
* @return The String used for the CommandManager to register the commands. */
|
||||
public default String getCommandString()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public default ModuleLogger getLogger()
|
||||
{
|
||||
return ModuleLoader.getModuleLogger(this);
|
||||
}
|
||||
|
||||
/** This method gets run the very first time a module gets loaded. You can use this to set up file structures or background data. */
|
||||
public default void firstLoad()
|
||||
{}
|
||||
|
||||
/** This method gets run every time a module gets loaded and its version has changed.
|
||||
*
|
||||
* @param old The version of the previous module. */
|
||||
public default void migrate(Version old)
|
||||
{}
|
||||
|
||||
default void setPrefix(final String name)
|
||||
{
|
||||
getLogger().setName(name);
|
||||
}
|
||||
}
|
||||
76
src/main/java/com/redstoner/modules/ModuleLogger.java
Normal file
76
src/main/java/com/redstoner/modules/ModuleLogger.java
Normal file
@@ -0,0 +1,76 @@
|
||||
package com.redstoner.modules;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import com.redstoner.annotations.Version;
|
||||
|
||||
import net.nemez.chatapi.ChatAPI;
|
||||
import net.nemez.chatapi.click.Message;
|
||||
|
||||
@Version(major = 4, minor = 0, revision = 0, compatible = -1)
|
||||
public class ModuleLogger
|
||||
{
|
||||
public static final String PREFIX_WARN = "§8[§eWARN§8]:§7 ";
|
||||
public static final String PREFIX_ERROR = "§8[§cERROR§8]:§7 ";
|
||||
|
||||
private String name;
|
||||
|
||||
public ModuleLogger(final String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void info(final String message)
|
||||
{
|
||||
Bukkit.getConsoleSender().sendMessage(getPrefix() + ChatAPI.colorify(null, message));
|
||||
}
|
||||
|
||||
public void warn(final String message)
|
||||
{
|
||||
Bukkit.getConsoleSender().sendMessage(PREFIX_WARN + getPrefix() + ChatAPI.colorify(null, message));
|
||||
}
|
||||
|
||||
public void error(final String message)
|
||||
{
|
||||
Bukkit.getConsoleSender().sendMessage(PREFIX_ERROR + getPrefix() + ChatAPI.colorify(null, message));
|
||||
}
|
||||
|
||||
public void message(final CommandSender recipient, final String... message)
|
||||
{
|
||||
message(recipient, false, message);
|
||||
}
|
||||
|
||||
public void message(final CommandSender recipient, final boolean error, final String... message)
|
||||
{
|
||||
Message m = new Message(recipient, null);
|
||||
if (message.length == 1)
|
||||
m.appendText(getPrefix(error) + message[0]);
|
||||
else
|
||||
{
|
||||
m.appendText(getHeader());
|
||||
m.appendText("&7" + String.join("\n&7", message));
|
||||
}
|
||||
m.send();
|
||||
}
|
||||
|
||||
public String getPrefix()
|
||||
{
|
||||
return getPrefix(false);
|
||||
}
|
||||
|
||||
public String getPrefix(final boolean error)
|
||||
{
|
||||
return "§8[§" + (error ? 'c' : '2') + name + "§8]§7 ";
|
||||
}
|
||||
|
||||
public String getHeader()
|
||||
{
|
||||
return "§2--=[ " + name + " ]=--\n";
|
||||
}
|
||||
|
||||
protected final void setName(final String name)
|
||||
{
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user