diff --git a/lib/FormAPI-JS.js b/lib/FormAPI-JS.js new file mode 100644 index 0000000..d51bfbe --- /dev/null +++ b/lib/FormAPI-JS.js @@ -0,0 +1,129 @@ +const getNextCallbackId = ll.import("GMLIB_FormAPI", "getNextFormCallbackId"); + +class ServerSettingForm { + static getDefaultPriority() { + return ll.import("GMLIB_ServerSettingForm", "getDefaultPriority")(); + } + + static hasTitle() { + return ll.import("GMLIB_ServerSettingForm", "hasTitle")(); + } + + static getTitle() { + return ll.import("GMLIB_ServerSettingForm", "getTitle")(); + } + + static setTitle(title, forceModify = false) { + return ll.import("GMLIB_ServerSettingForm", "setTitle")(title, forceModify); + } + + static hasIcon() { + return ll.import("GMLIB_ServerSettingForm", "hasIcon")(); + } + + static getIconData() { + return hasIcon() ? ll.import("GMLIB_ServerSettingForm", "getIconData")() : null; + } + + static getIconType() { + return ll.import("GMLIB_ServerSettingForm", "getIconType")(); + } + + static setIcon(data, type = 0, forceModify = false) { + return ll.import("GMLIB_ServerSettingForm", "setIcon")(data, type, forceModify); + } + + static addLabel( + text, + playerDetector = (pl) => { return true; }, + priority = this.getDefaultPriority() + ) { + let detectorId = getNextCallbackId(); + ll.export(playerDetector, "GMLIB_FORM_CALLBACK", detectorId); + return ll.import("GMLIB_ServerSettingForm", "addLabel")(text, detectorId, priority); + } + + + static addInput( + text, + placeholder, + defaultVal, + callback = (pl, input) => { }, + playerDetector = (pl) => { return true; }, + priority = this.getDefaultPriority() + ) { + let callbackId = getNextCallbackId(); + ll.export(callback, "GMLIB_FORM_CALLBACK", callbackId); + let detectorId = getNextCallbackId(); + ll.export(playerDetector, "GMLIB_FORM_CALLBACK", detectorId); + return ll.import("GMLIB_ServerSettingForm", "addInput")(text, placeholder, defaultVal, callbackId, detectorId, priority); + } + + static addToggle( + text, + defaultVal = false, + callback = (pl, input) => { }, + playerDetector = (pl) => { return true; }, + priority = this.getDefaultPriority() + ) { + let callbackId = getNextCallbackId(); + ll.export(callback, "GMLIB_FORM_CALLBACK", callbackId); + let detectorId = getNextCallbackId(); + ll.export(playerDetector, "GMLIB_FORM_CALLBACK", detectorId); + return ll.import("GMLIB_ServerSettingForm", "addToggle")(text, defaultVal, callbackId, detectorId, priority); + } + + static addDropdown( + text, + options, + defaultVal = 0, + callback = (pl, input) => { }, + playerDetector = (pl) => { return true; }, + priority = this.getDefaultPriority() + ) { + let callbackId = getNextCallbackId(); + ll.export(callback, "GMLIB_FORM_CALLBACK", callbackId); + let detectorId = getNextCallbackId(); + ll.export(playerDetector, "GMLIB_FORM_CALLBACK", detectorId); + return ll.import("GMLIB_ServerSettingForm", "addDropdown")(text, options, defaultVal, callbackId, detectorId, priority); + } + + static addSlider( + text, + min, + max, + step = 0.0, + defaultVal = 0.0, + callback = (pl, input) => { }, + playerDetector = (pl) => { return true; }, + priority = this.getDefaultPriority() + ) { + let callbackId = getNextCallbackId(); + ll.export(callback, "GMLIB_FORM_CALLBACK", callbackId); + let detectorId = getNextCallbackId(); + ll.export(playerDetector, "GMLIB_FORM_CALLBACK", detectorId); + return ll.import("GMLIB_ServerSettingForm", "addSlider")(text, min, max, step, defaultVal, callbackId, detectorId, priority); + } + + static addStepSlider( + text, + steps, + defaultVal = 0, + callback = (pl, input) => { }, + playerDetector = (pl) => { return true; }, + priority = this.getDefaultPriority() + ) { + let callbackId = getNextCallbackId(); + ll.export(callback, "GMLIB_FORM_CALLBACK", callbackId); + let detectorId = getNextCallbackId(); + ll.export(playerDetector, "GMLIB_FORM_CALLBACK", detectorId); + return ll.import("GMLIB_ServerSettingForm", "addStepSlider")(text, steps, defaultVal, callbackId, detectorId, priority); + } + + static removeElement(id) { + return ll.import("GMLIB_ServerSettingForm", "removeElement")(id); + } + +} + +module.exports = { ServerSettingForm }; \ No newline at end of file diff --git a/src/Entry.cpp b/src/Entry.cpp index 4fc8301..c997918 100644 --- a/src/Entry.cpp +++ b/src/Entry.cpp @@ -17,6 +17,7 @@ bool LegacyRemoteCallApi::load() { ExportPAPI(); Export_Event_API(); Export_BinaryStream_API(); + Export_Form_API(); logger.info("GMLIB-LegacyRemoteCallApi Loaded!"); logger.info( "Loaded Version: {} with {}", diff --git a/src/EventAPI.cpp b/src/EventAPI.cpp index d30fab7..2a57bf1 100644 --- a/src/EventAPI.cpp +++ b/src/EventAPI.cpp @@ -3,7 +3,7 @@ using namespace ll::hash_utils; class LegacyScriptEventManager { private: - int64 mNextEventId = 0; + int64 mNextEventId = 0; std::unordered_map mEventListeners; public: diff --git a/src/FormAPI.cpp b/src/FormAPI.cpp new file mode 100644 index 0000000..90da1c3 --- /dev/null +++ b/src/FormAPI.cpp @@ -0,0 +1,232 @@ +#include "Global.h" + +using namespace GMLIB::Server::Form; +using namespace ll::hash_utils; + +class LegacyScriptFormManager { +private: + int64 mNextFormCallbackId = 0; + // std::unordered_map mEventListeners; + +public: + std::string getNextFormCallbackId() { + mNextFormCallbackId++; + return "GMLIB_EVENT_" + std::to_string(mNextFormCallbackId); + } + +public: + static LegacyScriptFormManager& getInstance() { + static std::unique_ptr instance; + if (!instance) { + instance = std::make_unique(); + } + return *instance; + } +}; + +#define PLAYER_DETECROR \ + [detectorId, result](Player& pl) -> bool { \ + try { \ + if (RemoteCall::hasFunc("GMLIB_FORM_CALLBACK", detectorId)) { \ + auto const& detector = RemoteCall::importAs("GMLIB_FORM_CALLBACK", detectorId); \ + return detector(&pl); \ + } else { \ + ServerSettingForm::removeElement(result); \ + } \ + } catch (...) {} \ + return false; \ + } + +#define CALLBACK_TYPE_STRING \ + [callbackId, result](Player& pl, std::string const& data) { \ + try { \ + if (RemoteCall::hasFunc("GMLIB_FORM_CALLBACK", callbackId)) { \ + auto const& callback = \ + RemoteCall::importAs("GMLIB_FORM_CALLBACK", callbackId); \ + callback(&pl, data); \ + } else { \ + ServerSettingForm::removeElement(result); \ + } \ + } catch (...) {} \ + } + +#define CALLBACK_TYPE_BOOL \ + [callbackId, result](Player& pl, bool data) { \ + try { \ + if (RemoteCall::hasFunc("GMLIB_FORM_CALLBACK", callbackId)) { \ + auto const& callback = RemoteCall::importAs("GMLIB_FORM_CALLBACK", callbackId); \ + callback(&pl, data); \ + } else { \ + ServerSettingForm::removeElement(result); \ + } \ + } catch (...) {} \ + } + +#define CALLBACK_TYPE_DOUBLE \ + [callbackId, result](Player& pl, double data) { \ + try { \ + if (RemoteCall::hasFunc("GMLIB_FORM_CALLBACK", callbackId)) { \ + auto const& callback = RemoteCall::importAs("GMLIB_FORM_CALLBACK", callbackId); \ + callback(&pl, data); \ + } else { \ + ServerSettingForm::removeElement(result); \ + } \ + } catch (...) {} \ + } + + +#define CALLBACK_TYPE_LONG \ + [callbackId, result](Player& pl, int64 data) { \ + try { \ + if (RemoteCall::hasFunc("GMLIB_FORM_CALLBACK", callbackId)) { \ + auto const& callback = RemoteCall::importAs("GMLIB_FORM_CALLBACK", callbackId); \ + callback(&pl, data); \ + } else { \ + ServerSettingForm::removeElement(result); \ + } \ + } catch (...) {} \ + } + + +void Export_Form_API() { + RemoteCall::exportAs("GMLIB_ServerSettingForm", "getDefaultPriority", []() -> int { + return ServerSettingForm::getDefaultPriority(); + }); + RemoteCall::exportAs("GMLIB_FormAPI", "getNextFormCallbackId", []() -> std::string { + return LegacyScriptFormManager::getInstance().getNextFormCallbackId(); + }); + RemoteCall::exportAs("GMLIB_ServerSettingForm", "hasTitle", []() -> bool { return ServerSettingForm::hasTitle(); }); + RemoteCall::exportAs("GMLIB_ServerSettingForm", "getTitle", []() -> std::string { + return ServerSettingForm::getTitle(); + }); + RemoteCall::exportAs("GMLIB_ServerSettingForm", "setTitle", [](std::string const& title, bool forceModify) -> bool { + return ServerSettingForm::setTitle(title, forceModify); + }); + RemoteCall::exportAs("GMLIB_ServerSettingForm", "hasIcon", []() -> bool { return ServerSettingForm::hasIcon(); }); + RemoteCall::exportAs("GMLIB_ServerSettingForm", "getIconData", []() -> std::string { + if (auto data = ServerSettingForm::getIconData()) { + return data.value(); + } + return ""; + }); + RemoteCall::exportAs("GMLIB_ServerSettingForm", "getIconType", []() -> int { + if (auto type = ServerSettingForm::getIconType()) { + return (int)type.value(); + } + return -1; + }); + RemoteCall::exportAs( + "GMLIB_ServerSettingForm", + "setIcon", + [](std::string const& title, uchar type, bool forceModify) -> bool { + return ServerSettingForm::setIcon(title, IconType(type), forceModify); + } + ); + RemoteCall::exportAs( + "GMLIB_ServerSettingForm", + "addLabel", + [](std::string const& text, std::string const& detectorId, int priority) -> uint { + uint result = ServerSettingForm::addLabel(text, PLAYER_DETECROR, priority); + return result; + } + ); + RemoteCall::exportAs( + "GMLIB_ServerSettingForm", + "addInput", + [](std::string const& text, + std::string const& placeholder, + std::string const& defaultVal, + std::string const& callbackId, + std::string const& detectorId, + int priority) -> uint { + uint result = ServerSettingForm::addInput( + text, + placeholder, + defaultVal, + CALLBACK_TYPE_STRING, + PLAYER_DETECROR, + priority + ); + return result; + } + ); + RemoteCall::exportAs( + "GMLIB_ServerSettingForm", + "addToggle", + [](std::string const& text, + bool defaultVal, + std::string const& callbackId, + std::string const& detectorId, + int priority) -> uint { + uint result = ServerSettingForm::addToggle(text, defaultVal, CALLBACK_TYPE_BOOL, PLAYER_DETECROR, priority); + return result; + } + ); + RemoteCall::exportAs( + "GMLIB_ServerSettingForm", + "addDropdown", + [](std::string const& text, + std::vector options, + int64 defaultVal, + std::string const& callbackId, + std::string const& detectorId, + int priority) -> uint { + uint result = ServerSettingForm::addDropdown( + text, + options, + defaultVal, + CALLBACK_TYPE_LONG, + PLAYER_DETECROR, + priority + ); + return result; + } + ); + RemoteCall::exportAs( + "GMLIB_ServerSettingForm", + "addSlider", + [](std::string const& text, + double min, + double max, + double step, + double defaultVal, + std::string const& callbackId, + std::string const& detectorId, + int priority) -> uint { + uint result = ServerSettingForm::addSlider( + text, + min, + max, + step, + defaultVal, + CALLBACK_TYPE_DOUBLE, + PLAYER_DETECROR, + priority + ); + return result; + } + ); + RemoteCall::exportAs( + "GMLIB_ServerSettingForm", + "addStepSlider", + [](std::string const& text, + std::vector steps, + int64 defaultVal, + std::string const& callbackId, + std::string const& detectorId, + int priority) -> uint { + uint result = ServerSettingForm::addStepSlider( + text, + steps, + defaultVal, + CALLBACK_TYPE_LONG, + PLAYER_DETECROR, + priority + ); + return result; + } + ); + RemoteCall::exportAs("GMLIB_ServerSettingForm", "removeElement", [](uint id) -> bool { + return ServerSettingForm::removeElement(id); + }); +} \ No newline at end of file diff --git a/src/Global.h b/src/Global.h index 5428fee..60a2bd8 100644 --- a/src/Global.h +++ b/src/Global.h @@ -22,4 +22,5 @@ extern void Export_Legacy_GMLib_ServerAPI(); extern void Export_Compatibility_API(); extern void ExportPAPI(); extern void Export_Event_API(); -extern void Export_BinaryStream_API(); \ No newline at end of file +extern void Export_BinaryStream_API(); +extern void Export_Form_API();