// ------------------------------------------------------------------------------------------------ #include "Common.hpp" // ------------------------------------------------------------------------------------------------ #include #include // ------------------------------------------------------------------------------------------------ namespace SqMod { // ------------------------------------------------------------------------------------------------ extern void Register_Common(Table & jns); extern void Register_JArray(Table & jns); extern void Register_JObject(Table & jns); extern void Register_JValue(Table & jns); /* ------------------------------------------------------------------------------------------------ * Register the module API under the obtained virtual machine. */ static bool RegisterAPI(HSQUIRRELVM vm) { // Make sure there's a valid virtual machine before proceeding if (!vm) { OutputError("%s: Cannot register API without a valid virtual machine", SQJSON_NAME); // Registration failed return false; } Table jns(vm); Register_Common(jns); Register_JArray(jns); Register_JObject(jns); Register_JValue(jns); RootTable(vm).Bind(_SC("SqJSON"), jns); Sqrat::ConstTable(vm) .Const(_SC("JSON_OBJECT"), JSON_OBJECT) .Const(_SC("JSON_ARRAY"), JSON_ARRAY) .Const(_SC("JSON_STRING"), JSON_STRING) .Const(_SC("JSON_INTEGER"), JSON_INTEGER) .Const(_SC("JSON_REAL"), JSON_REAL) .Const(_SC("JSON_TRUE"), JSON_TRUE) .Const(_SC("JSON_FALSE"), JSON_FALSE) .Const(_SC("JSON_NULL"), JSON_NULL); // Registration was successful return true; } /* ------------------------------------------------------------------------------------------------ * Load the module on the virtual machine provided by the host module. */ static bool OnSquirrelLoad() { // Make sure that we have a valid module API if (!SqMod_GetSquirrelVM) { OutputError("%s: Cannot obtain the Squirrel virtual machine without the module API", SQJSON_NAME); // Unable to proceed! return false; } // Obtain the Squirrel virtual machine from the host plug-in DefaultVM::Set(SqMod_GetSquirrelVM()); // Make sure that a valid virtual machine exists if (!DefaultVM::Get()) { OutputError("%s: Squirrel virtual machine obtained from the host plug-in is invalid", SQJSON_NAME); // Unable to proceed! return false; } // Prevent common null objects from using dead virtual machines NullArray() = Array(); NullTable() = Table(); NullObject() = Object(); NullFunction() = Function(); // Register the module API if (RegisterAPI(DefaultVM::Get())) { OutputMessage("Registered: %s", SQJSON_NAME); } else { return false; } // At this point, the module was successfully loaded return true; } /* ------------------------------------------------------------------------------------------------ * The virtual machine is about to be terminated and script resources should be released. */ static void OnSquirrelTerminate() { OutputMessage("Terminating: %s", SQJSON_NAME); // Release null objects just in case NullObject().Release(); NullTable().Release(); NullArray().Release(); NullFunction().ReleaseGently(); } /* ------------------------------------------------------------------------------------------------ * The virtual machined is about to be closed. Last chance to release anything manually. */ static void OnSquirrelClosing() { // Nothing to release manually... } /* ------------------------------------------------------------------------------------------------ * The virtual machined was closed and all memory associated with it was released. */ static void OnSquirrelReleased() { // Release the current virtual machine, if any DefaultVM::Set(nullptr); } /* ------------------------------------------------------------------------------------------------ * React to command sent by other plug-ins. */ static uint8_t OnPluginCommand(uint32_t command_identifier, CCStr message) { switch(command_identifier) { case SQMOD_INITIALIZE_CMD: { if (CheckModuleAPIVer(message, SQJSON_NAME)) { try { ImportModuleAPI(_Func, SQJSON_NAME); } catch (const Sqrat::Exception & e) { OutputError("%s", e.what()); // Failed to initialize return 0; } } } break; case SQMOD_LOAD_CMD: { return OnSquirrelLoad(); } break; case SQMOD_TERMINATE_CMD: { OnSquirrelTerminate(); } break; case SQMOD_CLOSING_CMD: { OnSquirrelClosing(); } break; case SQMOD_RELEASED_CMD: { OnSquirrelReleased(); } break; default: break; } return 1; } /* ------------------------------------------------------------------------------------------------ * The server was initialized and this plug-in was loaded successfully. */ static uint8_t OnServerInitialise() { return 1; // Initialization was successful } /* ------------------------------------------------------------------------------------------------ * The server is about to shutdown gracefully. */ static void OnServerShutdown(void) { // The server may still send callbacks _Clbk->OnServerInitialise = nullptr; _Clbk->OnServerShutdown = nullptr; _Clbk->OnPluginCommand = nullptr; } } // Namespace:: SqMod // ------------------------------------------------------------------------------------------------ SQMOD_API_EXPORT unsigned int VcmpPluginInit(PluginFuncs * functions, PluginCallbacks * callbacks, PluginInfo * info) { using namespace SqMod; // Output plug-in header std::puts(""); OutputMessage("--------------------------------------------------------------------"); OutputMessage("Plug-in: %s", SQJSON_NAME); OutputMessage("Author: %s", SQJSON_AUTHOR); OutputMessage("Legal: %s", SQJSON_COPYRIGHT); OutputMessage("--------------------------------------------------------------------"); std::puts(""); // Make sure that the module was loaded after the host plug-in if (!CheckModuleOrder(functions, info->pluginId, SQJSON_NAME)) { return SQMOD_FAILURE; } // Store server proxies _Func = functions; _Clbk = callbacks; _Info = info; // Assign plug-in version _Info->pluginVersion = SQJSON_VERSION; _Info->apiMajorVersion = PLUGIN_API_MAJOR; _Info->apiMinorVersion = PLUGIN_API_MINOR; // Assign the plug-in name std::snprintf(_Info->name, sizeof(_Info->name), "%s", SQJSON_HOST_NAME); // Bind to the server callbacks _Clbk->OnServerInitialise = OnServerInitialise; _Clbk->OnServerShutdown = OnServerShutdown; _Clbk->OnPluginCommand = OnPluginCommand; // Notify that the plug-in was successfully loaded OutputMessage("Successfully loaded %s", SQJSON_NAME); // Dummy spacing std::puts(""); // Done! return SQMOD_SUCCESS; }