diff --git a/inc/libplugin.h b/inc/libplugin.h index 90c61c5..f72efe7 100644 --- a/inc/libplugin.h +++ b/inc/libplugin.h @@ -15,43 +15,64 @@ extern jclass CPPPLUGINCLASS; extern jclass EVENTCLASS; extern jclass MAPCLASS; extern jclass LISTENERCLASS; +extern jclass CMDCLASS; +extern jclass BUKKITCLASS; +extern jclass CBSERVERCLASS; +extern jclass CMDMAPCLASS; + extern jfieldID EVENTDATAF; extern jfieldID EVENTNAMEF; extern jfieldID PLUGINIDF; +extern jfieldID BUKKITSERVER; +extern jfieldID SERVERCMDMAP; + extern jmethodID MAPGET; extern jmethodID MAPPUT; extern jmethodID MAPCLEAR; extern jmethodID LISTENERCONTR; extern jmethodID LISTENERSMALLCONTR; +extern jmethodID CMDCONSTR; +extern jmethodID CMDMAPREGISTER; + void load(JNIEnv* env, long data); enum JNIDATA : long { - JNI_PLUGINCLASS = 1, - JNI_EVENTCLASS = 2, - JNI_MAPCLASS = 4, - JNI_LISTENERCLASS = 8, - JNI_EVENTDATAFIELD = 16 | JNI_EVENTCLASS, - JNI_EVENTNAMEFIELD = 32 | JNI_EVENTCLASS, - JNI_PLUGINIDFIELD = 64 | JNI_PLUGINCLASS, - JNI_MAPGETMETH = 128 | JNI_MAPCLASS, - JNI_MAPPUTMETH = 256 | JNI_MAPCLASS, - JNI_MAPCLEARMETH = 512 | JNI_MAPCLASS, - JNI_LISTENERCONSTR = 1024 | JNI_LISTENERCLASS, - JNI_LISTENERSMALLCONSTR = 2048 | JNI_LISTENERCLASS, + JNI_PLUGINCLASS = 1, + JNI_EVENTCLASS = JNI_PLUGINCLASS << 1, + JNI_MAPCLASS = JNI_EVENTCLASS << 1, + JNI_LISTENERCLASS = JNI_MAPCLASS << 1, + JNI_CMDCLASS = JNI_LISTENERCLASS << 1, + JNI_BUKKITCLASS = JNI_CMDCLASS << 1, + JNI_CBSERVERCLASS = JNI_BUKKITCLASS << 1, + JNI_CMDMAPCLASS = JNI_CBSERVERCLASS << 1, - JNI_EVENT = JNI_EVENTCLASS | JNI_EVENTDATAFIELD | JNI_EVENTNAMEFIELD, - JNI_MAP = JNI_MAPCLASS | JNI_MAPGETMETH | JNI_MAPPUTMETH, + JNI_EVENTDATAFIELD = JNI_CMDMAPCLASS << 1, + JNI_EVENTNAMEFIELD = JNI_EVENTDATAFIELD << 1, + JNI_PLUGINIDFIELD = JNI_EVENTNAMEFIELD << 1, + JNI_BUKKITSERVFIELD = JNI_PLUGINIDFIELD << 1, + JNI_SERVERCMDMAPFIELD = JNI_BUKKITSERVFIELD << 1, + + JNI_MAPGETMETH = JNI_SERVERCMDMAPFIELD << 1, + JNI_MAPPUTMETH = JNI_MAPGETMETH << 1, + JNI_MAPCLEARMETH = JNI_MAPPUTMETH << 1, + JNI_LISTENERCONSTR = JNI_MAPCLEARMETH << 1, + JNI_LISTENERSMALLCONSTR = JNI_LISTENERCONSTR << 1, + JNI_CMDCONSTR = JNI_LISTENERSMALLCONSTR << 1, + JNI_CMDMAPREGISTERMETH = JNI_CMDCONSTR << 1, + + JNI_EVENT = JNI_EVENTCLASS | JNI_EVENTDATAFIELD | JNI_EVENTNAMEFIELD, + JNI_MAP = JNI_MAPCLASS | JNI_MAPGETMETH | JNI_MAPPUTMETH, JNI_LISTENER = JNI_LISTENERCLASS | JNI_LISTENERCONSTR | JNI_LISTENERSMALLCONSTR, - JNI_ALL = 0xFFFF + JNI_ALL = 0xFFFFFFFFFFFFFF // current count: 20, max count:56 }; -/* -long operator|(JNIDATA a, JNIDATA b); -long operator|(long a, JNIDATA b); -long operator&(long a, JNIDATA b);*/ class CppPlugin; extern std::vector plugins; -CppPlugin* getPlugin(JNIEnv* env = 0, jobject thisobj = 0, int id = -1); \ No newline at end of file +CppPlugin* getPlugin(JNIEnv* env = 0, jobject thisobj = 0, int id = -1); +inline CppPlugin* getPlugin(int id) { + return getPlugin(0, 0, id); +} + diff --git a/inc/plugin.h b/inc/plugin.h index 03b9e70..413c026 100644 --- a/inc/plugin.h +++ b/inc/plugin.h @@ -3,6 +3,7 @@ #include #include +#include #include "event.h" @@ -10,17 +11,26 @@ class CppPlugin; //function pointer -typedef void (*eventfptr)(JNIEnv*, CppPlugin*, Event*); -typedef CppPlugin* (*initfptr)(); +typedef void (*eventfptr)(JNIEnv*, CppPlugin*, Event*); //event +typedef CppPlugin* (*initfptr)(); //init +// cmdsender cmd label args arglength +typedef bool (*cmdfptr)(JNIEnv*, CppPlugin*, jobject, jobject, std::string&, std::vector&); + class CppPlugin { public: void* handle; std::string name; - virtual void onLoad(); - virtual void onEnable(); - virtual void onDisable(); + int id; + virtual void onLoad(JNIEnv*); + virtual void onEnable(JNIEnv*); + virtual void onDisable(JNIEnv*); virtual std::map getEvents(); virtual ~CppPlugin(); }; +bool registerCmd(JNIEnv* env, CppPlugin* plugin, std::string& cname, cmdfptr function); +inline bool registerCmd(JNIEnv* env, CppPlugin* plugin, const char* cname, cmdfptr function) { + std::string n(cname); + return registerCmd( env, plugin, n, function); +} \ No newline at end of file diff --git a/src/main/cpp/src/libplugin.cpp b/src/main/cpp/src/libplugin.cpp index 8b3e920..94cdec9 100644 --- a/src/main/cpp/src/libplugin.cpp +++ b/src/main/cpp/src/libplugin.cpp @@ -14,14 +14,25 @@ jclass CPPPLUGINCLASS; jclass EVENTCLASS; jclass MAPCLASS; jclass LISTENERCLASS; +jclass CMDCLASS; +jclass BUKKITCLASS; +jclass CBSERVERCLASS; +jclass CMDMAPCLASS; + jfieldID EVENTDATAF; jfieldID EVENTNAMEF; jfieldID PLUGINIDF; +jfieldID BUKKITSERVER; +jfieldID SERVERCMDMAP; + jmethodID MAPGET; jmethodID MAPPUT; jmethodID MAPCLEAR; jmethodID LISTENERCONTR; jmethodID LISTENERSMALLCONTR; +jmethodID CMDCONSTR; +jmethodID CMDMAPREGISTER; + std::vector plugins; /* @@ -44,15 +55,22 @@ CppPlugin* getPlugin(JNIEnv* env, jobject thisobj, int id) { } void load(JNIEnv* env, long data) { - if(data & JNI_PLUGINCLASS) + if(data & (JNI_PLUGINCLASS | JNI_PLUGINIDFIELD)) CPPPLUGINCLASS = env->FindClass("de/mrbesen/cppplugins/CppPlugin"); - if(data & JNI_EVENTCLASS) + if(data & (JNI_EVENTCLASS | JNI_EVENTDATAFIELD | JNI_EVENTNAMEFIELD)) EVENTCLASS = env->FindClass("de/mrbesen/cppplugins/CppEvent"); - if(data & JNI_MAPCLASS) + if(data & (JNI_MAPCLASS | JNI_MAPCLEARMETH | JNI_MAPGETMETH | JNI_MAPPUTMETH)) MAPCLASS = env->FindClass("java/util/Map"); - if(data & JNI_LISTENERCLASS) + if(data & (JNI_LISTENERCLASS | JNI_LISTENERCONSTR | JNI_LISTENERSMALLCONSTR)) LISTENERCLASS = env->FindClass("de/mrbesen/cppplugins/CppPlugin$CppListener"); - + if(data & (JNI_CMDCLASS | JNI_CMDCONSTR)) + CMDCLASS = env->FindClass("de/mrbesen/cppplugins/CppPlugin$CppCommand"); + if(data & JNI_BUKKITCLASS) + BUKKITCLASS = env->FindClass("org/bukkit/Bukkit"); + if(data & (JNI_CBSERVERCLASS | JNI_SERVERCMDMAPFIELD)) + CBSERVERCLASS = env->FindClass("org/bukkit/craftbukkit/v1_12_R1/CraftServer"); + if(data & (JNI_CMDMAPCLASS | JNI_CMDMAPREGISTERMETH)) + CMDMAPCLASS = env->FindClass("org/bukkit/command/SimpleCommandMap"); if(data & JNI_EVENTDATAFIELD) EVENTDATAF = env->GetFieldID(EVENTCLASS, "data", "Ljava/util/Map;"); @@ -60,7 +78,10 @@ void load(JNIEnv* env, long data) { EVENTNAMEF = env->GetFieldID(EVENTCLASS, "name", "Ljava/lang/String;"); if(data & JNI_PLUGINIDFIELD) PLUGINIDF = env->GetFieldID(CPPPLUGINCLASS, "id", "I"); - + if(data & JNI_BUKKITSERVFIELD) + BUKKITSERVER = env->GetStaticFieldID(BUKKITCLASS, "server", "Lorg/bukkit/Server;"); + if(data & JNI_SERVERCMDMAPFIELD) + SERVERCMDMAP = env->GetFieldID(CBSERVERCLASS, "commandMap", "Lorg/bukkit/command/SimpleCommandMap;"); if(data & JNI_MAPGETMETH) MAPGET = env->GetMethodID(MAPCLASS, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"); @@ -72,20 +93,24 @@ void load(JNIEnv* env, long data) { LISTENERCONTR = env->GetMethodID(LISTENERCLASS, "", "(Ljava/lang/String;J)V"); if(data & JNI_LISTENERSMALLCONSTR) LISTENERSMALLCONTR = env->GetMethodID(LISTENERCLASS, "", "()V"); + if(data & JNI_CMDCONSTR) + CMDCONSTR = env->GetMethodID(CMDCLASS, "", "(Ljava/lang/String;JI)V"); + if(data & JNI_CMDMAPREGISTERMETH) + CMDMAPREGISTER = env->GetMethodID(CMDMAPCLASS, "register", "(Ljava/lang/String;Lorg/bukkit/command/Command;)Z"); - if(((!CPPPLUGINCLASS) + (!EVENTCLASS) + (!MAPCLASS) + (!LISTENERCLASS) //wenn eins == nullptr ist -> wird zu 1 -> endergebniss != 0 -> fehler - + (!EVENTDATAF) + (!EVENTNAMEF) + (!PLUGINIDF) - + (!MAPGET) + (!MAPPUT) + (!MAPCLEAR) + (!LISTENERCONTR) + (!LISTENERSMALLCONTR)) != 0) { + if(((!CPPPLUGINCLASS) + (!EVENTCLASS) + (!MAPCLASS) + (!LISTENERCLASS) + (!CMDCLASS) + (!BUKKITCLASS) + (!CBSERVERCLASS) + (!CMDMAPCLASS)//wenn eins == nullptr ist -> wird zu 1 -> endergebniss != 0 -> fehler + + (!EVENTDATAF) + (!EVENTNAMEF) + (!PLUGINIDF) + (!BUKKITSERVER) + (!SERVERCMDMAP) + + (!MAPGET) + (!MAPPUT) + (!MAPCLEAR) + (!LISTENERCONTR) + (!LISTENERSMALLCONTR) + (!CMDCONSTR) + (!CMDMAPREGISTER)) != 0) { - DEB("Error loading a information: "); - DEB("find classes: " << (!!CPPPLUGINCLASS) << (!!EVENTCLASS) << (!!MAPCLASS) << (!!LISTENERCLASS)); - DEB("findfields: " << (!!EVENTDATAF) << (!!EVENTNAMEF) << (!!PLUGINIDF)); - DEB("find methods: " << (!!MAPGET) << (!!MAPPUT) << (!!MAPCLEAR) << (!!LISTENERCONTR) << (!!LISTENERSMALLCONTR)); + DEB("Error loading a Java Information:"); + DEB("find classes: " << (!!CPPPLUGINCLASS) << (!!EVENTCLASS) << (!!MAPCLASS) << (!!LISTENERCLASS) << (!!CMDCLASS) << (!!BUKKITCLASS) << (!!CBSERVERCLASS) << (!!CMDMAPCLASS)); + DEB("find fields: " << (!!EVENTDATAF) << (!!EVENTNAMEF) << (!!PLUGINIDF) << (!!BUKKITSERVER) << (!!SERVERCMDMAP)); + DEB("find methods: " << (!!MAPGET) << (!!MAPPUT) << (!!MAPCLEAR) << (!!LISTENERCONTR) << (!!LISTENERSMALLCONTR) << (!!CMDCONSTR) << (!!CMDMAPREGISTER)); } } -JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_init_1(JNIEnv* env, jobject thisobj) { +JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_init_1(JNIEnv* env, jclass pluginclass) { load(env, JNI_ALL); return true; } @@ -117,18 +142,25 @@ JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_loadPlugin(JNIEn } CppPlugin* plugin = initf(); + DEB("Initilized"); + plugin->handle = handle; //set name / handle id plugin->name = std::string(cpath); - plugin->name = plugin->name.substr(plugin->name.rfind('/')); + plugin->name = plugin->name.substr(plugin->name.rfind('/')+1); + DEB("name set"); // add to vector plugins.push_back(plugin); + int id = plugins.size()-1; + plugin->id = id; + DEB("plugin added to vector"); //store id - load(env, JNI_PLUGINIDFIELD); - env->SetIntField(thisobj, PLUGINIDF, plugins.size()-1); + load(env, JNI_ALL); + env->SetIntField(thisobj, PLUGINIDF, id); + DEB("Internal id set"); return (bool) plugin; // converted to boolean here } @@ -140,7 +172,7 @@ JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_loadPlugin(JNIEn */ JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onLoad(JNIEnv* env, jobject thisobj) { DEB("lib::onLoad()"); - getPlugin(env, thisobj)->onLoad(); + getPlugin(env, thisobj)->onLoad(env); } /* @@ -150,7 +182,7 @@ JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onLoad(JNIEnv* env, */ JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onEnable_1(JNIEnv* env, jobject thisobj) { DEB("lib::onEnable()"); - getPlugin(env, thisobj)->onEnable(); + getPlugin(env, thisobj)->onEnable(env); } /* @@ -162,7 +194,7 @@ JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onDisable_1(JNIEnv* //TODO DEB("lib::onDisable()" ); CppPlugin* plugin = getPlugin(env, thisobj); - plugin->onDisable(); + plugin->onDisable(env); dlclose(plugin->handle); } @@ -198,11 +230,34 @@ JNIEXPORT jobject JNICALL Java_de_mrbesen_cppplugins_CppPlugin_fireEvent(JNIEnv* /* * Class: de_mrbesen_cppplugins_CppPlugin * Method: onCmd - * Signature: (Lorg/bukkit/command/CommandSender;Lorg/bukkit/command/Command;Ljava/lang/String;[Ljava/lang/String;)Z + * Signature: (Lorg/bukkit/command/CommandSender;Lorg/bukkit/command/Command;Ljava/lang/String;[Ljava/lang/String;J)Z */ -JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onCmd(JNIEnv* env, jobject thisobj, jobject sender, jobject cmd, jstring label, jobjectArray args) { - //TODO - return false; +JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onCmd(JNIEnv* env, jclass cppplugin, jobject sender, jobject cmd, jstring label, jobjectArray args, jlong fid, jint pluginid) { + if(fid == 0) return false; + CppPlugin* plugin = getPlugin(pluginid); + + //parse args + int argsize = env->GetArrayLength(args); + std::vector cargs(argsize); + for(int i = 0; i < argsize; i++) { + jstring ar = (jstring) env->GetObjectArrayElement(args, i); + cargs[i] = env->GetStringUTFChars(ar, 0); + } + + //parse label + std::string clabel = env->GetStringUTFChars(label, 0); + + //call function + cmdfptr cmdf = reinterpret_cast(fid); + bool result = false; + try { + result = cmdf(env, plugin, sender, cmd, clabel, cargs); + } catch(...) { + std::cout << "Error while executing Command " << clabel << " in plugin: " << plugin->name << std::endl; + return false; + } + + return result; } /* @@ -239,3 +294,25 @@ JNIEXPORT jobjectArray JNICALL Java_de_mrbesen_cppplugins_CppPlugin_getListener( return arr; } +bool registerCmd(JNIEnv* env, CppPlugin* plugin, std::string& cname, cmdfptr function) { + DEB("Register Cmd " + cname + " for " + plugin->name); + load(env, JNI_BUKKITCLASS | JNI_SERVERCMDMAPFIELD | JNI_CMDCONSTR | JNI_CMDMAPREGISTERMETH); + + // create cnd + jstring name = env->NewStringUTF(cname.c_str()); + DEB("name converted"); + jobject cmd = env->NewObject(CMDCLASS, CMDCONSTR, name, reinterpret_cast(function), plugin->id); + DEB("cmd created"); + + //call register + // ((CraftServer) Bukkit.getServer()).getCommandMap().register(fallbackprefix, cmd); + jobject jserver = env->GetStaticObjectField(BUKKITCLASS, BUKKITSERVER); + DEB("got server"); + jobject cmdmap = env->GetObjectField(jserver, SERVERCMDMAP); + DEB("cmdmap"); + + jstring fallbackprefix = env->NewStringUTF(plugin->name.c_str()); + DEB("prefix created"); + return env->CallBooleanMethod(cmdmap, CMDMAPREGISTER, fallbackprefix, cmd); +} + diff --git a/src/main/cpp/src/plugin.cpp b/src/main/cpp/src/plugin.cpp index 9ef165f..3024601 100644 --- a/src/main/cpp/src/plugin.cpp +++ b/src/main/cpp/src/plugin.cpp @@ -2,15 +2,15 @@ #include -void CppPlugin::onLoad() { +void CppPlugin::onLoad(JNIEnv*) { } -void CppPlugin::onEnable() { +void CppPlugin::onEnable(JNIEnv*) { } -void CppPlugin::onDisable() { +void CppPlugin::onDisable(JNIEnv*) { } diff --git a/src/main/java/de/mrbesen/cppplugins/CppLoader.java b/src/main/java/de/mrbesen/cppplugins/CppLoader.java index e0155e9..00acc84 100644 --- a/src/main/java/de/mrbesen/cppplugins/CppLoader.java +++ b/src/main/java/de/mrbesen/cppplugins/CppLoader.java @@ -39,7 +39,9 @@ public class CppLoader implements PluginLoader { "org.bukkit.event.server.", "org.bukkit.event.vehicle.", "org.bukkit.event.weather.", - "org.bukkit.event.world." + "org.bukkit.event.world.", + "spigotmc.event.player.", + "spigotmc.event.entity." }; @Override diff --git a/src/main/java/de/mrbesen/cppplugins/CppPlugin.java b/src/main/java/de/mrbesen/cppplugins/CppPlugin.java index cf932f0..3650799 100644 --- a/src/main/java/de/mrbesen/cppplugins/CppPlugin.java +++ b/src/main/java/de/mrbesen/cppplugins/CppPlugin.java @@ -27,7 +27,7 @@ public class CppPlugin implements Plugin { private int id; //for JNI, do not remove //library operations - protected native boolean init_(); //false: failed, true: success + protected static native boolean init_(); //false: failed, true: success protected native boolean loadPlugin(String path); //false = failed, true: success //plugin operations @@ -35,7 +35,7 @@ public class CppPlugin implements Plugin { public native void onEnable_(); public native void onDisable_(); protected native CppEvent fireEvent(CppEvent e, long functionid); - protected native boolean onCmd(CommandSender sender, Command cmd, String label, String[] args); + protected static native boolean onCmd(CommandSender sender, Command cmd, String label, String[] args, long functionid, int plugind); native CppListener[] getListener(); @@ -65,6 +65,7 @@ public class CppPlugin implements Plugin { @Override public void onEnable() { + getLogger().info("Enabling " + getName()); onEnable_(); enabled = true; } @@ -151,7 +152,7 @@ public class CppPlugin implements Plugin { @Override public boolean onCommand(CommandSender commandSender, Command command, String s, String[] strings) { - return onCmd(commandSender, command, s, strings); + return false; } @Override @@ -173,4 +174,20 @@ public class CppPlugin implements Plugin { functionid = 0; } } + + static class CppCommand extends Command { + private long functionid; + private int pluginid; + + protected CppCommand(String name, long functionid, int pluginid) { + super(name); + this.functionid = functionid; + this.pluginid = pluginid; + } + + @Override + public boolean execute(CommandSender sender, String label, String[] args) { + return onCmd(sender, this, label, args, functionid, pluginid); + } + } } diff --git a/testplugins/03simpleCmd/Makefile b/testplugins/03simpleCmd/Makefile new file mode 100644 index 0000000..dd0f49c --- /dev/null +++ b/testplugins/03simpleCmd/Makefile @@ -0,0 +1,11 @@ + +CFLAGS = -Wall -pedantic-errors -std=c++17 -g +SRCDIR = src/ +INCDIR = ../../inc +LDFLAGS = -I/usr/lib/jvm/java-8-openjdk-amd64/include/ -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux/ -I$(INCDIR) +NAME = simpleCmd.so + +all: + g++ -fPIC -shared $(CFLAGS) $(SRCDIR)*.cpp $(LDFLAGS) -o $(NAME) -lplugin + + #/home/yannis/git/Cppplugin/testserver/plugins/CppPlugins/libplugin.so diff --git a/testplugins/03simpleCmd/src/plugin.cpp b/testplugins/03simpleCmd/src/plugin.cpp new file mode 100644 index 0000000..c328ccc --- /dev/null +++ b/testplugins/03simpleCmd/src/plugin.cpp @@ -0,0 +1,45 @@ +#include "plugin.h" + +#include +#include +#include +#include + +extern "C" { + + +bool hicmd(JNIEnv* env, CppPlugin* plugin, jobject sender, jobject cmd, std::string& label, std::vector& args) { + std::cout << "HICMD::hi " << label << " argsize: " << args.size() << std::endl; + for(std::string& arg : args) { + std::cout << arg << std::endl; + } + return true; +} + + +class CmdPlugin : public CppPlugin { +public: + virtual void onLoad(JNIEnv*); + virtual void onEnable(JNIEnv*); + virtual void onDisable(JNIEnv*); + //virtual std::map getEvents(); +}; + +void CmdPlugin::onLoad(JNIEnv*) { + std::cout << "CmdPlugin::onLoad();" << std::endl; +} + +void CmdPlugin::onEnable(JNIEnv* env) { + std::cout << "CmdPlugin::onEnable();" << std::endl; + registerCmd(env, this, "hi", hicmd); +} + +void CmdPlugin::onDisable(JNIEnv*) { + std::cout << "CmdPlugin::onDisable();" << std::endl; +} + +CppPlugin* init() { + return new CmdPlugin(); +} + +}//extern "C" \ No newline at end of file