diff --git a/src/client/Minecraft.cpp b/src/client/Minecraft.cpp index 7ce53e5..91f3d5d 100755 --- a/src/client/Minecraft.cpp +++ b/src/client/Minecraft.cpp @@ -186,8 +186,7 @@ Minecraft::Minecraft() : commandPort(4711), reserved_d1(0),reserved_d2(0), reserved_f1(0),reserved_f2(0), options(this), - m_commandManager(), - m_pluginsManager(*level) + m_commandManager() { //#ifdef ANDROID @@ -1215,6 +1214,8 @@ void Minecraft::init() checkGlError("Init complete"); #endif + PluginsManager::get().init(*this); + options.load(); setIsCreativeMode(false); // false means it's Survival Mode diff --git a/src/client/Minecraft.h b/src/client/Minecraft.h index 7ffe0d5..ffd1973 100755 --- a/src/client/Minecraft.h +++ b/src/client/Minecraft.h @@ -245,8 +245,6 @@ private: CommandServer* _commandServer; CommandManager m_commandManager; - - PluginsManager m_pluginsManager; }; #endif /*NET_MINECRAFT_CLIENT__Minecraft_H__*/ diff --git a/src/main_dedicated.cpp b/src/main_dedicated.cpp index 03ce519..a9a90ca 100755 --- a/src/main_dedicated.cpp +++ b/src/main_dedicated.cpp @@ -15,16 +15,16 @@ #include "platform/time.h" #include "SharedConstants.h" #include "world/level/LevelConstants.h" -#include +#include #define MAIN_CLASS NinecraftApp static App* g_app = 0; static int g_exitCode = 0; void signal_callback_handler(int signum) { std::cout << "Signum caught: " << signum << std::endl; - if(signum == 2 || signum == 3){ // SIGINT || SIGQUIT - if(g_app != 0) { + if (signum == 2 || signum == 3) { // SIGINT || SIGQUIT + if (g_app != 0) { g_app->quit(); } else { exit(g_exitCode); @@ -162,6 +162,7 @@ int main(int numArguments, char* pszArgs[]) { float startTime = getTimeS(); ((MAIN_CLASS*)g_app)->selectLevel(levelDir, levelName, settings); ((MAIN_CLASS*)g_app)->hostMultiplayer(port); + PluginsManager::get().loadPlugins(); // Reading ops std::ifstream ops("ops.txt"); @@ -201,18 +202,10 @@ int main(int numArguments, char* pszArgs[]) { } } - std::string pluginsFolder = "plugins/"; - struct stat sb; - - if (stat(pluginsFolder.c_str(), &sb) == 0) { - - } else { - - } - std::cout << "Level has been generated in " << getTimeS() - startTime << std::endl; ((MAIN_CLASS*)g_app)->level->saveLevelData(); std::cout << "Level has been saved!" << std::endl; + PluginsManager::get().emit("ServerLoaded"); while(!app->wantToQuit()) { app->update(); diff --git a/src/network/ServerSideNetworkHandler.cpp b/src/network/ServerSideNetworkHandler.cpp index 66605e1..fa0625b 100755 --- a/src/network/ServerSideNetworkHandler.cpp +++ b/src/network/ServerSideNetworkHandler.cpp @@ -39,6 +39,7 @@ #endif #include "../server/ServerPlayer.h" #include "../world/entity/item/FallingTile.h" +#include #define TIMES(x) for(int itc ## __LINE__ = 0; itc ## __LINE__ < x; ++ itc ## __LINE__) @@ -163,12 +164,12 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, ChatPack if (packet->message[0] == '/') { // This is a command - ChatPacket resp(minecraft->commandManager().execute(*minecraft, *player, Util::stringTrim(packet->message.substr(1)))); return sendPrivate(resp, source); } displayGameMessage("<" + player->name + "> " + packet->message); + PluginsManager::get().emit("Message", LuaPlayer(source), packet->message); } void ServerSideNetworkHandler::onNewClient(const RakNet::RakNetGUID& clientGuid) @@ -193,6 +194,7 @@ void ServerSideNetworkHandler::onDisconnect(const RakNet::RakNetGUID& guid) std::string message = player->name; message += " disconnected from the game"; displayGameMessage(message); + PluginsManager::get().emit("PlayerDisconnect", LuaPlayer(guid)); //RemoveEntityPacket packet(player->entityId); //raknetInstance->send(packet); @@ -349,6 +351,7 @@ void ServerSideNetworkHandler::onReady_ClientGeneration(const RakNet::RakNetGUID #else LOGW("%s joined the game\n", newPlayer->name.c_str()); #endif + PluginsManager::get().emit("PlayerJoin", LuaPlayer(source)); // Send all Entities to the new player for (unsigned int i = 0; i < level->entities.size(); ++i) { @@ -458,7 +461,7 @@ void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, MovePlay } } -void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveBlockPacket* packet){ +void ServerSideNetworkHandler::handle(const RakNet::RakNetGUID& source, RemoveBlockPacket* packet) { if (!level) return; Player* player = getPlayer(source); diff --git a/src/network/ServerSideNetworkHandler.h b/src/network/ServerSideNetworkHandler.h index 1e9585d..5955e0b 100755 --- a/src/network/ServerSideNetworkHandler.h +++ b/src/network/ServerSideNetworkHandler.h @@ -66,7 +66,7 @@ public: Player* popPendingPlayer(const RakNet::RakNetGUID& source); void displayGameMessage(const std::string& message); -private: + /** * @brief Send packet to all players */ @@ -78,6 +78,8 @@ private: void sendPrivate(Packet& packet, const RakNet::RakNetGUID& source); Player* getPlayer(const RakNet::RakNetGUID& source); + +private: Minecraft* minecraft; Level* level; diff --git a/src/plugins/LuaPlayer.hpp b/src/plugins/LuaPlayer.hpp new file mode 100644 index 0000000..4f37397 --- /dev/null +++ b/src/plugins/LuaPlayer.hpp @@ -0,0 +1,54 @@ +#pragma once +#include +#include +#include +#include +#include +#include + +class LuaPlayer { +public: + LuaPlayer(const RakNet::RakNetGUID source) : m_source(source) {} + + std::string getNickname() { + auto mc = PluginsManager::get().getMinecraft(); + ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) mc->netCallback; + + auto plr = ss->getPlayer(m_source); + if (plr != nullptr) return plr->name; + + return ""; + } + + float getX() { + auto mc = PluginsManager::get().getMinecraft(); + ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) mc->netCallback; + + auto plr = ss->getPlayer(m_source); + if (plr != nullptr) return plr->x; + + return 0; + } + + float getY() { + auto mc = PluginsManager::get().getMinecraft(); + ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) mc->netCallback; + + auto plr = ss->getPlayer(m_source); + if (plr != nullptr) return plr->y; + + return 0; + } + + float getZ() { + auto mc = PluginsManager::get().getMinecraft(); + ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) mc->netCallback; + + auto plr = ss->getPlayer(m_source); + if (plr != nullptr) return plr->z; + + return 0; + } +private: + const RakNet::RakNetGUID m_source; +}; \ No newline at end of file diff --git a/src/plugins/LuaServer.cpp b/src/plugins/LuaServer.cpp new file mode 100644 index 0000000..5e189fd --- /dev/null +++ b/src/plugins/LuaServer.cpp @@ -0,0 +1,11 @@ +#include +#include +#include +#include + +void LuaServer::sendServerMessage(std::string msg) { + auto mc = PluginsManager::get().getMinecraft(); + ServerSideNetworkHandler* ss = (ServerSideNetworkHandler*) mc->netCallback; + + ss->displayGameMessage(msg); +} \ No newline at end of file diff --git a/src/plugins/LuaServer.hpp b/src/plugins/LuaServer.hpp new file mode 100644 index 0000000..47fd9d4 --- /dev/null +++ b/src/plugins/LuaServer.hpp @@ -0,0 +1,7 @@ +#pragma once +#include + +class LuaServer { +public: + void sendServerMessage(std::string msg); +}; \ No newline at end of file diff --git a/src/plugins/PluginsManager.cpp b/src/plugins/PluginsManager.cpp index 14ca9f2..69f2ee5 100644 --- a/src/plugins/PluginsManager.cpp +++ b/src/plugins/PluginsManager.cpp @@ -1,16 +1,48 @@ #include -#include +#include +#include -PluginsManager::PluginsManager(Level& level) : m_level(level) { +#include +#include + +namespace fs = std::filesystem; + +void PluginsManager::init(Minecraft& minecraft) { m_lua.open_libraries(sol::lib::base); - registerTypes(); + + m_minecraft = &minecraft; } void PluginsManager::registerTypes() { - m_lua.set_function("subscribe", &PluginsManager::subscribe); + // @note you cant just do that, because lua doesnt have access to the class in this case + // m_lua.set_function("subscribe", &PluginsManager::subscribe); + + m_lua.set_function("subscribe", [this](std::string event, sol::protected_function func) { + // @note: why the .at() not working? + m_callbacks[event].push_back(func); + }); + + m_lua.new_usertype( + "Server", + "sendMessage", &LuaServer::sendServerMessage + ); + + m_lua.new_usertype( + "Player", + "getNickname", &LuaPlayer::getNickname, + "getX", &LuaPlayer::getX, + "getY", &LuaPlayer::getY, + "getZ", &LuaPlayer::getZ + ); + + m_lua["Server"] = &m_srv; } -void PluginsManager::subscribe(std::string event, sol::function function) { - m_callbacks.at(event).push_back(function); +void PluginsManager::loadPlugins() { + std::string path = "plugins/"; + + for (const auto & entry : fs::directory_iterator(path)) { + m_lua.script_file(entry.path().string()); + } } \ No newline at end of file diff --git a/src/plugins/PluginsManager.hpp b/src/plugins/PluginsManager.hpp index f0418c9..1e744d9 100644 --- a/src/plugins/PluginsManager.hpp +++ b/src/plugins/PluginsManager.hpp @@ -2,19 +2,48 @@ #include #include #include +#include -class Level; +class Minecraft; class PluginsManager { public: - PluginsManager(Level& level); + static inline PluginsManager& get() { + static PluginsManager inst; + return inst; + } + + void init(Minecraft& minecraft); void registerTypes(); - void subscribe(std::string event, sol::function function); + void loadPlugins(); + + // @ai @note maybe we should rewrite it... + // problem that i dont know how to pass args in sol::function dynamically + // so i used ai + // sry :( + template + void emit(std::string event, Args&&... args) { + auto it = m_callbacks.find(event); + + if (it == m_callbacks.end()) return; + + for (auto& callback : it->second) { + sol::protected_function_result result = callback(std::forward(args)...); + + if (!result.valid()) { + sol::error err = result; + std::cout << err.what() << std::endl; + } + } + } + + Minecraft* getMinecraft() { return m_minecraft; } private: std::unordered_map> m_callbacks; + LuaServer m_srv; sol::state m_lua; - Level& m_level; + Minecraft* m_minecraft; }; \ No newline at end of file