2020-02-20 04:28:05 +01:00
# include "de_mrbesen_cppplugins_CppPlugin.h"
# include "de_mrbesen_cppplugins_CppPlugin_CppListener.h"
# include <iostream>
# include <dlfcn.h> //dynamic linking
2020-02-21 09:57:24 +01:00
# include <libgen.h> //basename
2020-02-20 04:28:05 +01:00
2020-02-20 19:23:28 +01:00
# include <thread> //thread id
2020-02-20 04:28:05 +01:00
2020-02-20 19:23:28 +01:00
# include "libplugin.h"
# include "plugin.h"
2020-02-22 09:08:07 +01:00
namespace Plugin {
2020-02-20 19:23:28 +01:00
jclass CPPPLUGINCLASS ;
jclass EVENTCLASS ;
jclass MAPCLASS ;
jclass LISTENERCLASS ;
2020-02-22 02:37:07 +01:00
jclass CMDCLASS ;
jclass BUKKITCLASS ;
jclass CBSERVERCLASS ;
jclass CMDMAPCLASS ;
2020-02-22 08:54:09 +01:00
jclass CMDSENDERCLASS ;
2020-02-22 02:37:07 +01:00
2020-02-20 19:23:28 +01:00
jfieldID EVENTDATAF ;
jfieldID EVENTNAMEF ;
2020-02-21 09:57:24 +01:00
jfieldID PLUGINIDF ;
2020-02-22 02:37:07 +01:00
jfieldID BUKKITSERVER ;
jfieldID SERVERCMDMAP ;
2020-02-20 19:23:28 +01:00
jmethodID MAPGET ;
jmethodID MAPPUT ;
2020-02-20 20:17:00 +01:00
jmethodID MAPCLEAR ;
2020-02-20 19:23:28 +01:00
jmethodID LISTENERCONTR ;
jmethodID LISTENERSMALLCONTR ;
2020-02-22 02:37:07 +01:00
jmethodID CMDCONSTR ;
jmethodID CMDMAPREGISTER ;
2020-02-22 08:54:09 +01:00
jmethodID CMDSENDERSEND ;
2020-02-22 02:37:07 +01:00
2020-02-20 19:23:28 +01:00
2020-02-21 09:57:24 +01:00
std : : vector < CppPlugin * > plugins ;
/*
2020-02-20 19:23:28 +01:00
void fixcap ( JNIEnv * env ) {
DEB ( " ensure 1024 " ) ;
env - > EnsureLocalCapacity ( 1024 ) ;
DEB ( " push frame 1024 " ) ;
env - > PushLocalFrame ( 1024 ) ;
2020-02-21 09:57:24 +01:00
} */
CppPlugin * getPlugin ( JNIEnv * env , jobject thisobj , int id ) {
//get id
if ( id < 0 ) {
load ( env , JNI_PLUGINIDFIELD ) ;
id = env - > GetIntField ( thisobj , PLUGINIDF ) ;
}
return plugins . at ( id ) ;
2020-02-20 19:23:28 +01:00
}
void load ( JNIEnv * env , long data ) {
2020-02-22 02:37:07 +01:00
if ( data & ( JNI_PLUGINCLASS | JNI_PLUGINIDFIELD ) )
2020-02-20 19:23:28 +01:00
CPPPLUGINCLASS = env - > FindClass ( " de/mrbesen/cppplugins/CppPlugin " ) ;
2020-02-22 02:37:07 +01:00
if ( data & ( JNI_EVENTCLASS | JNI_EVENTDATAFIELD | JNI_EVENTNAMEFIELD ) )
2020-02-20 19:23:28 +01:00
EVENTCLASS = env - > FindClass ( " de/mrbesen/cppplugins/CppEvent " ) ;
2020-02-22 02:37:07 +01:00
if ( data & ( JNI_MAPCLASS | JNI_MAPCLEARMETH | JNI_MAPGETMETH | JNI_MAPPUTMETH ) )
2020-02-20 19:23:28 +01:00
MAPCLASS = env - > FindClass ( " java/util/Map " ) ;
2020-02-22 02:37:07 +01:00
if ( data & ( JNI_LISTENERCLASS | JNI_LISTENERCONSTR | JNI_LISTENERSMALLCONSTR ) )
2020-02-20 19:23:28 +01:00
LISTENERCLASS = env - > FindClass ( " de/mrbesen/cppplugins/CppPlugin$CppListener " ) ;
2020-02-22 02:37:07 +01:00
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 " ) ;
2020-02-22 08:54:09 +01:00
if ( data & ( JNI_CMDSENDERCLASS | JNI_CMDSENDERSENDMETH ) )
CMDSENDERCLASS = env - > FindClass ( " org/bukkit/command/CommandSender " ) ;
2020-02-20 19:23:28 +01:00
if ( data & JNI_EVENTDATAFIELD )
EVENTDATAF = env - > GetFieldID ( EVENTCLASS , " data " , " Ljava/util/Map; " ) ;
if ( data & JNI_EVENTNAMEFIELD )
EVENTNAMEF = env - > GetFieldID ( EVENTCLASS , " name " , " Ljava/lang/String; " ) ;
2020-02-21 09:57:24 +01:00
if ( data & JNI_PLUGINIDFIELD )
PLUGINIDF = env - > GetFieldID ( CPPPLUGINCLASS , " id " , " I " ) ;
2020-02-22 02:37:07 +01:00
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; " ) ;
2020-02-20 19:23:28 +01:00
if ( data & JNI_MAPGETMETH )
MAPGET = env - > GetMethodID ( MAPCLASS , " get " , " (Ljava/lang/Object;)Ljava/lang/Object; " ) ;
if ( data & JNI_MAPPUTMETH )
MAPPUT = env - > GetMethodID ( MAPCLASS , " put " , " (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; " ) ;
2020-02-20 20:17:00 +01:00
if ( data & JNI_MAPCLEARMETH )
MAPCLEAR = env - > GetMethodID ( MAPCLASS , " clear " , " ()V " ) ;
2020-02-20 19:23:28 +01:00
if ( data & JNI_LISTENERCONSTR )
LISTENERCONTR = env - > GetMethodID ( LISTENERCLASS , " <init> " , " (Ljava/lang/String;J)V " ) ;
if ( data & JNI_LISTENERSMALLCONSTR )
LISTENERSMALLCONTR = env - > GetMethodID ( LISTENERCLASS , " <init> " , " ()V " ) ;
2020-02-22 02:37:07 +01:00
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 " ) ;
2020-02-22 08:54:09 +01:00
if ( data & JNI_CMDSENDERSENDMETH )
CMDSENDERSEND = env - > GetMethodID ( CMDSENDERCLASS , " sendMessage " , " (Ljava/lang/String;)V " ) ;
2020-02-20 19:23:28 +01:00
2020-02-21 09:57:24 +01:00
2020-02-22 02:37:07 +01:00
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 ) {
2020-02-21 09:57:24 +01:00
2020-03-30 16:59:26 +02:00
DEB ( CRED < < " Error loading a Java Information: " ) ;
2020-02-22 02:37:07 +01:00
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 ) ) ;
2020-02-21 09:57:24 +01:00
}
2020-02-20 19:23:28 +01:00
}
2020-02-20 04:28:05 +01:00
2020-02-22 09:08:07 +01:00
bool registerCmd ( JNIEnv * env , CppPlugin * plugin , std : : string & cname , cmdfptr function ) {
2020-03-30 16:59:26 +02:00
DEB ( CYELLOW < < " Register Cmd " < < CGREEN < < cname < < CYELLOW < < " for " < < CGREEN < < plugin - > name ) ;
2020-02-22 09:08:07 +01:00
load ( env , JNI_BUKKITCLASS | JNI_SERVERCMDMAPFIELD | JNI_CMDCONSTR | JNI_CMDMAPREGISTERMETH ) ;
// create cnd
jstring name = env - > NewStringUTF ( cname . c_str ( ) ) ;
jobject cmd = env - > NewObject ( CMDCLASS , CMDCONSTR , name , reinterpret_cast < jlong > ( function ) , plugin - > id ) ;
env - > DeleteLocalRef ( name ) ;
//call register
// ((CraftServer) Bukkit.getServer()).getCommandMap().register(fallbackprefix, cmd);
jobject jserver = env - > GetStaticObjectField ( BUKKITCLASS , BUKKITSERVER ) ;
jobject cmdmap = env - > GetObjectField ( jserver , SERVERCMDMAP ) ;
jstring fallbackprefix = env - > NewStringUTF ( plugin - > name . c_str ( ) ) ;
return env - > CallBooleanMethod ( cmdmap , CMDMAPREGISTER , fallbackprefix , cmd ) ;
}
void send ( JNIEnv * env , jobject sender , const char * text ) {
load ( env , JNI_CMDSENDERSENDMETH ) ;
jstring jtext = env - > NewStringUTF ( text ) ;
env - > CallVoidMethod ( sender , CMDSENDERSEND , jtext ) ;
env - > DeleteLocalRef ( jtext ) ;
}
} //namespace
2020-02-22 02:37:07 +01:00
JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_init_1 ( JNIEnv * env , jclass pluginclass ) {
2020-02-22 09:08:07 +01:00
Plugin : : load ( env , Plugin : : JNI_ALL ) ;
2020-02-20 19:23:28 +01:00
return true ;
2020-02-20 04:28:05 +01:00
}
/**
* Class : de_mrbesen_cppplugins_CppPlugin
* Method : loadPlugin
* Signature : ( Ljava / lang / String ; ) Z
*/
JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_loadPlugin ( JNIEnv * env , jobject thisobj , jstring path ) {
const char * cpath = env - > GetStringUTFChars ( path , 0 ) ;
//open plugin
2020-03-30 16:59:26 +02:00
DEB ( CBLUE < < " open plugin " < < cpath ) ;
2020-02-20 04:28:05 +01:00
void * handle = dlopen ( cpath , RTLD_LAZY ) ;
2020-02-20 12:21:43 +01:00
if ( ! handle ) {
std : : cout < < " could not create handle of: " < < cpath < < " error: " < < dlerror ( ) < < std : : endl ;
2020-02-20 04:28:05 +01:00
return false ;
2020-02-20 12:21:43 +01:00
}
2020-02-20 04:28:05 +01:00
//throw std::string("Error: plugin could not be opend. ") + dlerror();
//load function pointer
2020-02-22 09:08:07 +01:00
Plugin : : initfptr initf = ( Plugin : : initfptr ) dlsym ( handle , " init " ) ;
2020-02-20 04:28:05 +01:00
if ( ! initf ) {
2020-02-20 12:21:43 +01:00
std : : cout < < " Could not find function init: " < < dlerror ( ) < < std : : endl ;
2020-02-20 04:28:05 +01:00
dlclose ( handle ) ;
return false ;
2020-02-20 12:21:43 +01:00
}
2020-02-20 04:28:05 +01:00
2020-02-22 09:08:07 +01:00
Plugin : : CppPlugin * plugin = initf ( ) ;
2020-03-30 16:59:26 +02:00
DEB ( CGREY < < " Initilized " ) ;
2020-02-22 02:37:07 +01:00
2020-02-20 12:21:43 +01:00
plugin - > handle = handle ;
2020-02-21 09:57:24 +01:00
//set name / handle id
plugin - > name = std : : string ( cpath ) ;
2020-02-22 02:37:07 +01:00
plugin - > name = plugin - > name . substr ( plugin - > name . rfind ( ' / ' ) + 1 ) ;
2020-03-30 16:59:26 +02:00
DEB ( CGREY < < " name set " ) ;
2020-02-21 09:57:24 +01:00
// add to vector
2020-02-22 09:08:07 +01:00
Plugin : : plugins . push_back ( plugin ) ;
int id = Plugin : : plugins . size ( ) - 1 ;
2020-02-22 02:37:07 +01:00
plugin - > id = id ;
2020-03-30 16:59:26 +02:00
DEB ( CGREY < < " plugin added to vector " ) ;
2020-02-21 09:57:24 +01:00
//store id
2020-02-22 09:08:07 +01:00
Plugin : : load ( env , Plugin : : JNI_ALL ) ;
env - > SetIntField ( thisobj , Plugin : : PLUGINIDF , id ) ;
2020-03-30 16:59:26 +02:00
DEB ( CGREY < < " Internal id set " ) ;
2020-02-21 09:57:24 +01:00
2020-02-20 12:21:43 +01:00
return ( bool ) plugin ; // converted to boolean here
2020-02-20 04:28:05 +01:00
}
/*
* Class : de_mrbesen_cppplugins_CppPlugin
* Method : onLoad
* Signature : ( ) V
*/
JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onLoad ( JNIEnv * env , jobject thisobj ) {
2020-03-30 16:59:26 +02:00
DEB ( CGREY < < " lib::onLoad() " ) ;
2020-02-22 09:08:07 +01:00
Plugin : : getPlugin ( env , thisobj ) - > onLoad ( env ) ;
2020-02-20 04:28:05 +01:00
}
/*
* Class : de_mrbesen_cppplugins_CppPlugin
* Method : onEnable_
* Signature : ( ) V
*/
JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onEnable_1 ( JNIEnv * env , jobject thisobj ) {
2020-03-30 16:59:26 +02:00
DEB ( CGREY < < " lib::onEnable() " ) ;
2020-02-22 09:08:07 +01:00
Plugin : : getPlugin ( env , thisobj ) - > onEnable ( env ) ;
2020-02-20 04:28:05 +01:00
}
/*
* Class : de_mrbesen_cppplugins_CppPlugin
* Method : onDisable_
* Signature : ( ) V
*/
JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onDisable_1 ( JNIEnv * env , jobject thisobj ) {
//TODO
2020-03-30 16:59:26 +02:00
DEB ( CGREY < < " lib::onDisable() " ) ;
2020-02-22 09:08:07 +01:00
Plugin : : CppPlugin * plugin = Plugin : : getPlugin ( env , thisobj ) ;
2020-02-22 02:37:07 +01:00
plugin - > onDisable ( env ) ;
2020-02-20 12:21:43 +01:00
dlclose ( plugin - > handle ) ;
2020-02-20 04:28:05 +01:00
}
/*
* Class : de_mrbesen_cppplugins_CppPlugin
* Method : fireEvent
* Signature : ( Lde / mrbesen / cppplugins / CppEvent ; I ) Lde / mrbesen / cppplugins / CppEvent ;
*/
2020-02-20 12:21:43 +01:00
JNIEXPORT jobject JNICALL Java_de_mrbesen_cppplugins_CppPlugin_fireEvent ( JNIEnv * env , jobject thisobj , jobject jevent , jlong functionid ) {
2020-03-30 16:59:26 +02:00
DEB ( CGREY < < " lib::fireEvent() " ) ;
2020-02-20 12:21:43 +01:00
if ( functionid = = 0 ) {
2020-03-30 16:59:26 +02:00
DEB ( CRED < < " invalid function id " ) ;
2020-02-20 12:21:43 +01:00
return jevent ;
}
2020-02-22 09:08:07 +01:00
Plugin : : load ( env , Plugin : : JNI_EVENT | Plugin : : JNI_MAP ) ;
2020-02-20 19:23:28 +01:00
2020-02-20 12:21:43 +01:00
//cast function
2020-02-22 09:08:07 +01:00
Plugin : : eventfptr f = reinterpret_cast < Plugin : : eventfptr > ( functionid ) ;
2020-02-20 12:21:43 +01:00
//cast event
2020-02-22 09:08:07 +01:00
Plugin : : Event event ( env , jevent ) ;
2020-02-20 12:21:43 +01:00
2020-03-30 16:59:26 +02:00
//get Plugin
Plugin : : CppPlugin * plugin = Plugin : : getPlugin ( env , thisobj ) ;
2020-02-20 12:21:43 +01:00
//call it
2020-03-30 16:59:26 +02:00
try {
f ( env , plugin , & event ) ;
} catch ( . . . ) {
std : : cout < < CRED < < " Error while processing Event " < < event . getName ( ) < < " in plugin: " < < plugin - > name < < CRESET < < std : : endl ;
return jevent ;
}
2020-02-20 12:21:43 +01:00
//put changed fields back in the jevent
event . reapply ( env , jevent ) ;
return jevent ;
2020-02-20 04:28:05 +01:00
}
/*
* Class : de_mrbesen_cppplugins_CppPlugin
* Method : onCmd
2020-02-22 02:37:07 +01:00
* Signature : ( Lorg / bukkit / command / CommandSender ; Lorg / bukkit / command / Command ; Ljava / lang / String ; [ Ljava / lang / String ; J ) Z
2020-02-20 04:28:05 +01:00
*/
2020-02-22 02:37:07 +01:00
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 ;
2020-02-22 09:08:07 +01:00
Plugin : : CppPlugin * plugin = Plugin : : getPlugin ( pluginid ) ;
2020-02-22 02:37:07 +01:00
//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
2020-02-22 09:08:07 +01:00
Plugin : : cmdfptr cmdf = reinterpret_cast < Plugin : : cmdfptr > ( fid ) ;
2020-02-22 02:37:07 +01:00
bool result = false ;
try {
result = cmdf ( env , plugin , sender , cmd , clabel , cargs ) ;
} catch ( . . . ) {
2020-03-30 16:59:26 +02:00
std : : cout < < CRED < < " Error while executing Command " < < clabel < < " in plugin: " < < plugin - > name < < CRESET < < std : : endl ;
2020-02-22 02:37:07 +01:00
return false ;
}
return result ;
2020-02-20 04:28:05 +01:00
}
/*
* Class : de_mrbesen_cppplugins_CppPlugin
* Method : getListener
* Signature : ( ) [ Lde / mrbesen / cppplugins / CppPlugin / CppListener ;
*/
JNIEXPORT jobjectArray JNICALL Java_de_mrbesen_cppplugins_CppPlugin_getListener ( JNIEnv * env , jobject thisobj ) {
2020-02-22 09:08:07 +01:00
Plugin : : load ( env , Plugin : : JNI_LISTENER ) ;
2020-02-20 19:23:28 +01:00
2020-02-20 12:21:43 +01:00
//call getEvents
2020-02-22 09:08:07 +01:00
std : : map < std : : string , Plugin : : eventfptr > events = Plugin : : getPlugin ( env , thisobj ) - > getEvents ( ) ;
2020-03-30 16:59:26 +02:00
DEB ( CYELLOW < < " found " < < events . size ( ) < < " Events " ) ;
2020-02-20 12:21:43 +01:00
//create array
2020-02-22 09:08:07 +01:00
jobject initial = env - > NewObject ( Plugin : : LISTENERCLASS , Plugin : : LISTENERSMALLCONTR ) ;
jobjectArray arr = env - > NewObjectArray ( events . size ( ) , Plugin : : LISTENERCLASS , initial ) ;
2020-02-20 12:21:43 +01:00
2020-03-30 16:59:26 +02:00
DEB ( CGREY < < " populate array " ) ;
2020-02-20 12:21:43 +01:00
//populate array
int i = 0 ;
for ( auto it : events ) {
//create object
jstring eventname = env - > NewStringUTF ( it . first . c_str ( ) ) ;
2020-02-22 09:08:07 +01:00
jobject listener = env - > NewObject ( Plugin : : LISTENERCLASS , Plugin : : LISTENERCONTR , eventname , it . second ) ;
2020-02-20 12:21:43 +01:00
env - > DeleteLocalRef ( eventname ) ;
//set array
env - > SetObjectArrayElement ( arr , i + + , listener ) ;
}
2020-03-30 16:59:26 +02:00
DEB ( CGREY < < " Array finished " ) ;
2020-02-20 12:21:43 +01:00
2020-02-20 19:23:28 +01:00
return arr ;
2020-03-30 16:59:26 +02:00
}