cmd support

This commit is contained in:
mrbesen 2020-02-22 02:37:07 +01:00
parent 6be08c97a5
commit 43931a46c6
8 changed files with 239 additions and 56 deletions

View File

@ -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<CppPlugin*> plugins;
CppPlugin* getPlugin(JNIEnv* env = 0, jobject thisobj = 0, int id = -1);
CppPlugin* getPlugin(JNIEnv* env = 0, jobject thisobj = 0, int id = -1);
inline CppPlugin* getPlugin(int id) {
return getPlugin(0, 0, id);
}

View File

@ -3,6 +3,7 @@
#include <map>
#include <string>
#include <vector>
#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<std::string>&);
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<std::string, eventfptr> 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);
}

View File

@ -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<CppPlugin*> 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, "<init>", "(Ljava/lang/String;J)V");
if(data & JNI_LISTENERSMALLCONSTR)
LISTENERSMALLCONTR = env->GetMethodID(LISTENERCLASS, "<init>", "()V");
if(data & JNI_CMDCONSTR)
CMDCONSTR = env->GetMethodID(CMDCLASS, "<init>", "(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<std::string> 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<cmdfptr>(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<jlong>(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);
}

View File

@ -2,15 +2,15 @@
#include <iostream>
void CppPlugin::onLoad() {
void CppPlugin::onLoad(JNIEnv*) {
}
void CppPlugin::onEnable() {
void CppPlugin::onEnable(JNIEnv*) {
}
void CppPlugin::onDisable() {
void CppPlugin::onDisable(JNIEnv*) {
}

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -0,0 +1,45 @@
#include "plugin.h"
#include <iostream>
#include <string>
#include <map>
#include <vector>
extern "C" {
bool hicmd(JNIEnv* env, CppPlugin* plugin, jobject sender, jobject cmd, std::string& label, std::vector<std::string>& 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<std::string, eventfptr> 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"