Compare commits
2 Commits
36fb80a714
...
c9f68fb734
Author | SHA1 | Date |
---|---|---|
mrbesen | c9f68fb734 | |
mrbesen | 0d52d3d5e6 |
|
@ -4,6 +4,8 @@
|
|||
#include <string>
|
||||
#include <map>
|
||||
|
||||
namespace Plugin {
|
||||
|
||||
class Event {
|
||||
private:
|
||||
std::string name; //name of the event
|
||||
|
@ -19,4 +21,6 @@ public:
|
|||
|
||||
Event(JNIEnv* env, jobject jevent);
|
||||
//virtual ~Event();
|
||||
};
|
||||
};
|
||||
|
||||
} //namespace Plugin
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#define DEB(A) ;
|
||||
#endif
|
||||
|
||||
namespace Plugin {
|
||||
|
||||
extern jclass CPPPLUGINCLASS;
|
||||
extern jclass EVENTCLASS;
|
||||
extern jclass MAPCLASS;
|
||||
|
@ -19,6 +21,7 @@ extern jclass CMDCLASS;
|
|||
extern jclass BUKKITCLASS;
|
||||
extern jclass CBSERVERCLASS;
|
||||
extern jclass CMDMAPCLASS;
|
||||
extern jclass CMDSENDERCLASS;
|
||||
|
||||
extern jfieldID EVENTDATAF;
|
||||
extern jfieldID EVENTNAMEF;
|
||||
|
@ -33,6 +36,7 @@ extern jmethodID LISTENERCONTR;
|
|||
extern jmethodID LISTENERSMALLCONTR;
|
||||
extern jmethodID CMDCONSTR;
|
||||
extern jmethodID CMDMAPREGISTER;
|
||||
extern jmethodID CMDSENDERSEND;
|
||||
|
||||
|
||||
void load(JNIEnv* env, long data);
|
||||
|
@ -46,8 +50,9 @@ enum JNIDATA : long {
|
|||
JNI_BUKKITCLASS = JNI_CMDCLASS << 1,
|
||||
JNI_CBSERVERCLASS = JNI_BUKKITCLASS << 1,
|
||||
JNI_CMDMAPCLASS = JNI_CBSERVERCLASS << 1,
|
||||
JNI_CMDSENDERCLASS = JNI_CMDMAPCLASS << 1,
|
||||
|
||||
JNI_EVENTDATAFIELD = JNI_CMDMAPCLASS << 1,
|
||||
JNI_EVENTDATAFIELD = JNI_CMDSENDERCLASS << 1,
|
||||
JNI_EVENTNAMEFIELD = JNI_EVENTDATAFIELD << 1,
|
||||
JNI_PLUGINIDFIELD = JNI_EVENTNAMEFIELD << 1,
|
||||
JNI_BUKKITSERVFIELD = JNI_PLUGINIDFIELD << 1,
|
||||
|
@ -60,12 +65,13 @@ enum JNIDATA : long {
|
|||
JNI_LISTENERSMALLCONSTR = JNI_LISTENERCONSTR << 1,
|
||||
JNI_CMDCONSTR = JNI_LISTENERSMALLCONSTR << 1,
|
||||
JNI_CMDMAPREGISTERMETH = JNI_CMDCONSTR << 1,
|
||||
JNI_CMDSENDERSENDMETH = JNI_CMDMAPREGISTERMETH << 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 = 0xFFFFFFFFFFFFFF // current count: 20, max count:56
|
||||
JNI_ALL = 0xFFFFFFFFFFFFFF // current count: 22, max count:56
|
||||
};
|
||||
|
||||
class CppPlugin;
|
||||
|
@ -76,3 +82,5 @@ inline CppPlugin* getPlugin(int id) {
|
|||
return getPlugin(0, 0, id);
|
||||
}
|
||||
|
||||
} //namespace Plugin
|
||||
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
#include "event.h"
|
||||
|
||||
namespace Plugin {
|
||||
|
||||
//fwd declr
|
||||
class CppPlugin;
|
||||
|
||||
|
@ -33,4 +35,56 @@ bool registerCmd(JNIEnv* env, CppPlugin* plugin, std::string& cname, cmdfptr fun
|
|||
inline bool registerCmd(JNIEnv* env, CppPlugin* plugin, const char* cname, cmdfptr function) {
|
||||
std::string n(cname);
|
||||
return registerCmd( env, plugin, n, function);
|
||||
}
|
||||
}
|
||||
|
||||
void send(JNIEnv* env, jobject sender, const char* text);
|
||||
|
||||
inline void send(JNIEnv* env, jobject sender, const std::string& text) {
|
||||
send(env, sender, text.c_str());
|
||||
}
|
||||
|
||||
enum Color : char {
|
||||
BLACK = '0',
|
||||
DARK_BLUE = '1',
|
||||
DARK_GREEN = '2',
|
||||
DARK_AQUA = '3',
|
||||
DARK_RED = '4',
|
||||
DARK_PURPLE = '5',
|
||||
GOLD = '6',
|
||||
GRAY = '7',
|
||||
DARK_GRAY = '8',
|
||||
BLUE = '9',
|
||||
GREEN = 'a',
|
||||
AQUA = 'b',
|
||||
RED = 'c',
|
||||
LIGHT_PURPLE = 'd',
|
||||
YELLOW = 'e',
|
||||
WHITE = 'f',
|
||||
MAGIC = 'k',
|
||||
BOLD = 'l',
|
||||
STRIKETHROUGH = 'm',
|
||||
UNDERLINE = 'n',
|
||||
ITALIC = 'o',
|
||||
RESET = 'r'
|
||||
};
|
||||
const char COLORCHAR = '\xA7'; // §
|
||||
inline std::string operator+(const Color c, const std::string& r) {
|
||||
std::string out(1, COLORCHAR);
|
||||
return out + ((char) c) + r;
|
||||
}
|
||||
|
||||
inline std::string operator+(const Color c, const char* r) {
|
||||
std::string out(1, COLORCHAR);
|
||||
return out + ((char) c) + r;
|
||||
}
|
||||
|
||||
inline std::string operator+(const std::string& r, const Color c) {
|
||||
return r + COLORCHAR + (char) c;
|
||||
}
|
||||
|
||||
inline std::string operator+(const char* r, const Color c) {
|
||||
return r + COLORCHAR + (char) c;
|
||||
}
|
||||
|
||||
} //namespace Plugin
|
||||
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
namespace Plugin {
|
||||
|
||||
jobject Event::getMap(JNIEnv* env) {
|
||||
return env->GetObjectField(input, EVENTDATAF);
|
||||
}
|
||||
|
@ -70,4 +72,7 @@ Event::Event(JNIEnv* env, jobject jevent) {
|
|||
jstring name = (jstring) env->GetObjectField(jevent, EVENTNAMEF);
|
||||
this->name = std::string(env->GetStringUTFChars(name, 0));
|
||||
input = jevent;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "libplugin.h"
|
||||
#include "plugin.h"
|
||||
|
||||
namespace Plugin {
|
||||
|
||||
jclass CPPPLUGINCLASS;
|
||||
jclass EVENTCLASS;
|
||||
jclass MAPCLASS;
|
||||
|
@ -18,6 +20,7 @@ jclass CMDCLASS;
|
|||
jclass BUKKITCLASS;
|
||||
jclass CBSERVERCLASS;
|
||||
jclass CMDMAPCLASS;
|
||||
jclass CMDSENDERCLASS;
|
||||
|
||||
jfieldID EVENTDATAF;
|
||||
jfieldID EVENTNAMEF;
|
||||
|
@ -32,6 +35,7 @@ jmethodID LISTENERCONTR;
|
|||
jmethodID LISTENERSMALLCONTR;
|
||||
jmethodID CMDCONSTR;
|
||||
jmethodID CMDMAPREGISTER;
|
||||
jmethodID CMDSENDERSEND;
|
||||
|
||||
|
||||
std::vector<CppPlugin*> plugins;
|
||||
|
@ -71,6 +75,8 @@ void load(JNIEnv* env, long data) {
|
|||
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_CMDSENDERCLASS | JNI_CMDSENDERSENDMETH))
|
||||
CMDSENDERCLASS = env->FindClass("org/bukkit/command/CommandSender");
|
||||
|
||||
if(data & JNI_EVENTDATAFIELD)
|
||||
EVENTDATAF = env->GetFieldID(EVENTCLASS, "data", "Ljava/util/Map;");
|
||||
|
@ -97,6 +103,8 @@ void load(JNIEnv* env, long data) {
|
|||
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(data & JNI_CMDSENDERSENDMETH)
|
||||
CMDSENDERSEND = env->GetMethodID(CMDSENDERCLASS, "sendMessage", "(Ljava/lang/String;)V");
|
||||
|
||||
|
||||
if(((!CPPPLUGINCLASS) + (!EVENTCLASS) + (!MAPCLASS) + (!LISTENERCLASS) + (!CMDCLASS) + (!BUKKITCLASS) + (!CBSERVERCLASS) + (!CMDMAPCLASS)//wenn eins == nullptr ist -> wird zu 1 -> endergebniss != 0 -> fehler
|
||||
|
@ -110,8 +118,38 @@ void load(JNIEnv* env, long data) {
|
|||
}
|
||||
}
|
||||
|
||||
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());
|
||||
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
|
||||
|
||||
|
||||
|
||||
JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_init_1(JNIEnv* env, jclass pluginclass) {
|
||||
load(env, JNI_ALL);
|
||||
Plugin::load(env, Plugin::JNI_ALL);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -134,14 +172,14 @@ JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_loadPlugin(JNIEn
|
|||
//throw std::string("Error: plugin could not be opend. ") + dlerror();
|
||||
|
||||
//load function pointer
|
||||
initfptr initf = (initfptr) dlsym(handle, "init");
|
||||
Plugin::initfptr initf = (Plugin::initfptr) dlsym(handle, "init");
|
||||
if(!initf) {
|
||||
std::cout << "Could not find function init: " << dlerror() << std::endl;
|
||||
dlclose(handle);
|
||||
return false;
|
||||
}
|
||||
|
||||
CppPlugin* plugin = initf();
|
||||
Plugin::CppPlugin* plugin = initf();
|
||||
DEB("Initilized");
|
||||
|
||||
plugin->handle = handle;
|
||||
|
@ -152,14 +190,14 @@ JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_loadPlugin(JNIEn
|
|||
DEB("name set");
|
||||
|
||||
// add to vector
|
||||
plugins.push_back(plugin);
|
||||
int id = plugins.size()-1;
|
||||
Plugin::plugins.push_back(plugin);
|
||||
int id = Plugin::plugins.size()-1;
|
||||
plugin->id = id;
|
||||
DEB("plugin added to vector");
|
||||
|
||||
//store id
|
||||
load(env, JNI_ALL);
|
||||
env->SetIntField(thisobj, PLUGINIDF, id);
|
||||
Plugin::load(env,Plugin:: JNI_ALL);
|
||||
env->SetIntField(thisobj,Plugin:: PLUGINIDF, id);
|
||||
DEB("Internal id set");
|
||||
|
||||
return (bool) plugin; // converted to boolean here
|
||||
|
@ -172,7 +210,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(env);
|
||||
Plugin::getPlugin(env, thisobj)->onLoad(env);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -182,7 +220,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(env);
|
||||
Plugin::getPlugin(env, thisobj)->onEnable(env);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -193,7 +231,7 @@ JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onEnable_1(JNIEnv* e
|
|||
JNIEXPORT void JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onDisable_1(JNIEnv* env, jobject thisobj) {
|
||||
//TODO
|
||||
DEB("lib::onDisable()" );
|
||||
CppPlugin* plugin = getPlugin(env, thisobj);
|
||||
Plugin::CppPlugin* plugin = Plugin::getPlugin(env, thisobj);
|
||||
plugin->onDisable(env);
|
||||
dlclose(plugin->handle);
|
||||
}
|
||||
|
@ -210,16 +248,16 @@ JNIEXPORT jobject JNICALL Java_de_mrbesen_cppplugins_CppPlugin_fireEvent(JNIEnv*
|
|||
return jevent;
|
||||
}
|
||||
|
||||
load(env, JNI_EVENT | JNI_MAP);
|
||||
Plugin::load(env, Plugin::JNI_EVENT | Plugin::JNI_MAP);
|
||||
|
||||
//cast function
|
||||
eventfptr f = reinterpret_cast<eventfptr>(functionid);
|
||||
Plugin::eventfptr f = reinterpret_cast<Plugin::eventfptr>(functionid);
|
||||
|
||||
//cast event
|
||||
Event event(env, jevent);
|
||||
Plugin::Event event(env, jevent);
|
||||
|
||||
//call it
|
||||
f(env, getPlugin(env, thisobj), &event);
|
||||
f(env, Plugin::getPlugin(env, thisobj), &event);
|
||||
|
||||
//put changed fields back in the jevent
|
||||
event.reapply(env, jevent);
|
||||
|
@ -234,7 +272,7 @@ JNIEXPORT jobject JNICALL Java_de_mrbesen_cppplugins_CppPlugin_fireEvent(JNIEnv*
|
|||
*/
|
||||
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);
|
||||
Plugin::CppPlugin* plugin = Plugin::getPlugin(pluginid);
|
||||
|
||||
//parse args
|
||||
int argsize = env->GetArrayLength(args);
|
||||
|
@ -248,7 +286,7 @@ JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onCmd(JNIEnv* en
|
|||
std::string clabel = env->GetStringUTFChars(label, 0);
|
||||
|
||||
//call function
|
||||
cmdfptr cmdf = reinterpret_cast<cmdfptr>(fid);
|
||||
Plugin::cmdfptr cmdf = reinterpret_cast<Plugin::cmdfptr>(fid);
|
||||
bool result = false;
|
||||
try {
|
||||
result = cmdf(env, plugin, sender, cmd, clabel, cargs);
|
||||
|
@ -266,15 +304,15 @@ JNIEXPORT jboolean JNICALL Java_de_mrbesen_cppplugins_CppPlugin_onCmd(JNIEnv* en
|
|||
* Signature: ()[Lde/mrbesen/cppplugins/CppPlugin/CppListener;
|
||||
*/
|
||||
JNIEXPORT jobjectArray JNICALL Java_de_mrbesen_cppplugins_CppPlugin_getListener(JNIEnv* env, jobject thisobj) {
|
||||
load(env, JNI_LISTENER);
|
||||
Plugin::load(env, Plugin::JNI_LISTENER);
|
||||
|
||||
//call getEvents
|
||||
std::map<std::string, eventfptr> events = getPlugin(env, thisobj)->getEvents();
|
||||
std::map<std::string, Plugin::eventfptr> events = Plugin::getPlugin(env, thisobj)->getEvents();
|
||||
DEB("found " << events.size() << " Events");
|
||||
|
||||
//create array
|
||||
jobject initial = env->NewObject(LISTENERCLASS, LISTENERSMALLCONTR);
|
||||
jobjectArray arr = env->NewObjectArray(events.size(), LISTENERCLASS, initial);
|
||||
jobject initial = env->NewObject(Plugin::LISTENERCLASS, Plugin::LISTENERSMALLCONTR);
|
||||
jobjectArray arr = env->NewObjectArray(events.size(), Plugin::LISTENERCLASS, initial);
|
||||
|
||||
DEB("populate array");
|
||||
//populate array
|
||||
|
@ -282,7 +320,7 @@ JNIEXPORT jobjectArray JNICALL Java_de_mrbesen_cppplugins_CppPlugin_getListener(
|
|||
for(auto it : events) {
|
||||
//create object
|
||||
jstring eventname = env->NewStringUTF(it.first.c_str());
|
||||
jobject listener = env->NewObject(LISTENERCLASS, LISTENERCONTR, eventname, it.second);
|
||||
jobject listener = env->NewObject(Plugin::LISTENERCLASS, Plugin::LISTENERCONTR, eventname, it.second);
|
||||
env->DeleteLocalRef(eventname);
|
||||
|
||||
//set array
|
||||
|
@ -292,27 +330,4 @@ JNIEXPORT jobjectArray JNICALL Java_de_mrbesen_cppplugins_CppPlugin_getListener(
|
|||
DEB("Array finished");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
namespace Plugin {
|
||||
|
||||
void CppPlugin::onLoad(JNIEnv*) {
|
||||
|
||||
}
|
||||
|
@ -21,4 +23,7 @@ std::map<std::string, eventfptr> CppPlugin::getEvents() {
|
|||
|
||||
CppPlugin::~CppPlugin() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} //namespace
|
||||
|
|
|
@ -2,6 +2,7 @@ package de.mrbesen.cppplugins;
|
|||
|
||||
import lombok.Getter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <string>
|
||||
#include <map>
|
||||
|
||||
using namespace Plugin;
|
||||
|
||||
extern "C" {
|
||||
|
||||
class SimplePlugin : public CppPlugin {
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <string>
|
||||
#include <map>
|
||||
|
||||
using namespace Plugin;
|
||||
|
||||
extern "C" {
|
||||
|
||||
class EventsPlugin : public CppPlugin {
|
||||
|
|
|
@ -5,14 +5,16 @@
|
|||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
using namespace Plugin;
|
||||
|
||||
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;
|
||||
}
|
||||
send(env, sender, Color::AQUA + "Hiiiiii\n" + Color::GREEN + "Nuttöööö");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue