mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 00:37:15 +01:00
Allow external native plug-ins to interact wit the script.
Very primitive mechanism but better than nothing.
This commit is contained in:
parent
2a069f3040
commit
bc1fc1d245
@ -1,5 +1,7 @@
|
|||||||
# Create the Squirrel module
|
# Create the Squirrel module
|
||||||
add_library(SqModule MODULE SqBase.hpp Main.cpp
|
add_library(SqModule MODULE SqBase.hpp Main.cpp
|
||||||
|
# SDK
|
||||||
|
SDK/sqmod.h
|
||||||
# VCMP
|
# VCMP
|
||||||
VCMP/vcmp.h
|
VCMP/vcmp.h
|
||||||
VCMP/vcmp20.h
|
VCMP/vcmp20.h
|
||||||
@ -114,6 +116,7 @@ add_library(SqModule MODULE SqBase.hpp Main.cpp
|
|||||||
Core.cpp Core.hpp
|
Core.cpp Core.hpp
|
||||||
Logger.cpp Logger.hpp
|
Logger.cpp Logger.hpp
|
||||||
Register.cpp
|
Register.cpp
|
||||||
|
Exports.cpp
|
||||||
)
|
)
|
||||||
# Various definitions required by the plug-in
|
# Various definitions required by the plug-in
|
||||||
target_compile_definitions(SqModule PRIVATE SCRAT_USE_EXCEPTIONS=1)
|
target_compile_definitions(SqModule PRIVATE SCRAT_USE_EXCEPTIONS=1)
|
||||||
@ -201,6 +204,7 @@ else(WIN32)
|
|||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
# Include current directory in the search path
|
# Include current directory in the search path
|
||||||
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR}/SDK)
|
||||||
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR}/VCMP)
|
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR}/VCMP)
|
||||||
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR}/Sqrat)
|
target_include_directories(SqModule PRIVATE ${CMAKE_CURRENT_LIST_DIR}/Sqrat)
|
||||||
# Include PCRE directory in the header search path
|
# Include PCRE directory in the header search path
|
||||||
@ -222,7 +226,7 @@ if(WIN32 AND MINGW AND COPY_DEPENDENCIES)
|
|||||||
endif()
|
endif()
|
||||||
# Make sure the deps folder exists
|
# Make sure the deps folder exists
|
||||||
file(MAKE_DIRECTORY "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(MAKE_DIRECTORY "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
# Copy dependencies into the plug-ins folder (only so it can be distributed with the DLL)
|
# Copy dependencies into the deps folder (only so it can be distributed with the DLL)
|
||||||
file(COPY "${MINGW_BIN_PATH}/zlib1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/zlib1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libpq.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libpq.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libzstd.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libzstd.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
@ -245,17 +249,17 @@ if(WIN32 AND MINGW AND COPY_DEPENDENCIES)
|
|||||||
file(COPY "${MINGW_BIN_PATH}/libp11-kit-0.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libp11-kit-0.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libbrotlidec.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libbrotlidec.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libbrotlicommon.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libbrotlicommon.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libunistring-2.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libunistring-5.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libnghttp2-14.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libnghttp2-14.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libwinpthread-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libwinpthread-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libstdc++-6.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libstdc++-6.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT FORCE_32BIT_BIN)
|
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT FORCE_32BIT_BIN)
|
||||||
file(COPY "${MINGW_BIN_PATH}/libgcc_s_seh-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libgcc_s_seh-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libssl-1_1-x64.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libssl-3-x64.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libcrypto-1_1-x64.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libcrypto-3-x64.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
else()
|
else()
|
||||||
file(COPY "${MINGW_BIN_PATH}/libssl-1_1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libssl-3.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
file(COPY "${MINGW_BIN_PATH}/libcrypto-1_1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libcrypto-3.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
endif()
|
endif()
|
||||||
if(POCO_UNBUNDLED)
|
if(POCO_UNBUNDLED)
|
||||||
file(COPY "${MINGW_BIN_PATH}/libexpat-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
file(COPY "${MINGW_BIN_PATH}/libexpat-1.dll" DESTINATION "${PROJECT_SOURCE_DIR}/bin/deps")
|
||||||
|
123
module/Core.cpp
123
module/Core.cpp
@ -161,6 +161,7 @@ Core::Core() noexcept
|
|||||||
, m_Scripts()
|
, m_Scripts()
|
||||||
, m_PendingScripts()
|
, m_PendingScripts()
|
||||||
, m_Options()
|
, m_Options()
|
||||||
|
, m_ExtCommands{nullptr, nullptr, nullptr, nullptr}
|
||||||
, m_Blips()
|
, m_Blips()
|
||||||
, m_Checkpoints()
|
, m_Checkpoints()
|
||||||
, m_KeyBinds()
|
, m_KeyBinds()
|
||||||
@ -441,9 +442,9 @@ bool Core::Execute()
|
|||||||
m_LockPostLoadSignal = false;
|
m_LockPostLoadSignal = false;
|
||||||
m_LockUnloadSignal = false;
|
m_LockUnloadSignal = false;
|
||||||
|
|
||||||
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to register their API");
|
cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins that the API is being registered");
|
||||||
// Tell modules to do their monkey business
|
// Tell modules to do their monkey business
|
||||||
//_Func->SendPluginCommand(0xDEADBABE, "");
|
_Func->SendPluginCommand(0xDEADBABE, "");
|
||||||
|
|
||||||
// Load pending scripts while we're in the bounds of the allowed recursiveness
|
// Load pending scripts while we're in the bounds of the allowed recursiveness
|
||||||
for (unsigned levels = 0; !m_PendingScripts.empty() && (levels < 8); ++levels)
|
for (unsigned levels = 0; !m_PendingScripts.empty() && (levels < 8); ++levels)
|
||||||
@ -511,9 +512,9 @@ void Core::Terminate(bool shutdown)
|
|||||||
// Clear the callbacks
|
// Clear the callbacks
|
||||||
ResetSignalPair(mOnUnload);
|
ResetSignalPair(mOnUnload);
|
||||||
|
|
||||||
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to release their resources");
|
cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to release their resources");
|
||||||
// Tell modules to do their monkey business
|
// Tell modules to do their monkey business
|
||||||
//_Func->SendPluginCommand(0xDEADC0DE, "");
|
_Func->SendPluginCommand(0xDEADC0DE, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
cLogDbg(m_Verbosity >= 1, "Clearing the entity containers");
|
cLogDbg(m_Verbosity >= 1, "Clearing the entity containers");
|
||||||
@ -596,9 +597,9 @@ void Core::Terminate(bool shutdown)
|
|||||||
HSQUIRRELVM sq_vm = m_VM;
|
HSQUIRRELVM sq_vm = m_VM;
|
||||||
m_VM = nullptr;
|
m_VM = nullptr;
|
||||||
|
|
||||||
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins the virtual machine is closing");
|
cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins the virtual machine is closing");
|
||||||
// Tell modules to do their monkey business
|
// Tell modules to do their monkey business
|
||||||
//_Func->SendPluginCommand(0xBAAAAAAD, "");
|
_Func->SendPluginCommand(0xBAAAAAAD, "");
|
||||||
// Release any callbacks from the logger
|
// Release any callbacks from the logger
|
||||||
Logger::Get().Release();
|
Logger::Get().Release();
|
||||||
cLogDbg(m_Verbosity >= 2, "Closing Virtual Machine");
|
cLogDbg(m_Verbosity >= 2, "Closing Virtual Machine");
|
||||||
@ -629,9 +630,9 @@ void Core::Terminate(bool shutdown)
|
|||||||
// Destroy the VM context, if any
|
// Destroy the VM context, if any
|
||||||
delete ctx;
|
delete ctx;
|
||||||
|
|
||||||
//cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins to release the virtual machine");
|
cLogDbg(m_Verbosity >= 1, "Signaling outside plug-ins the virtual machine was closed");
|
||||||
// Tell modules to do their monkey business
|
// Tell modules to do their monkey business
|
||||||
//_Func->SendPluginCommand(0xDEADBEAF, "");
|
_Func->SendPluginCommand(0xDEADBEAF, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
OutputMessage("Squirrel plug-in was successfully terminated");
|
OutputMessage("Squirrel plug-in was successfully terminated");
|
||||||
@ -904,6 +905,81 @@ String Core::FetchCodeLine(const SQChar * src, SQInteger line, bool trim)
|
|||||||
return script->FetchLine(line, trim);
|
return script->FetchLine(line, trim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
int32_t Core::RegisterExtCommand(ExtPluginCommand_t fn)
|
||||||
|
{
|
||||||
|
ExtPluginCommand_t * slot = nullptr;
|
||||||
|
// Find a free slot or matching function pointer in the pool
|
||||||
|
for (size_t i = 0; i < m_ExtCommands.max_size(); ++i)
|
||||||
|
{
|
||||||
|
// Is this slot available and are we still looking for a slot?
|
||||||
|
if (m_ExtCommands[i] == nullptr && slot == nullptr)
|
||||||
|
{
|
||||||
|
slot = &m_ExtCommands[i]; // Found a slot
|
||||||
|
}
|
||||||
|
// We keep looking for duplicates even if we found the slot
|
||||||
|
else if (m_ExtCommands[i] == fn)
|
||||||
|
{
|
||||||
|
return 0; // Already registered
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Do we have a free slot?
|
||||||
|
if (slot != nullptr)
|
||||||
|
{
|
||||||
|
*slot = fn; // Use this slot
|
||||||
|
return 1; // Successfully registered
|
||||||
|
}
|
||||||
|
// No space in the pool
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
int32_t Core::UnregisterExtCommand(ExtPluginCommand_t fn)
|
||||||
|
{
|
||||||
|
// Find the matching function pointer
|
||||||
|
for (size_t i = 0; i < m_ExtCommands.max_size(); ++i)
|
||||||
|
{
|
||||||
|
// Is this the same pointer?
|
||||||
|
if (m_ExtCommands[i] != nullptr && m_ExtCommands[i] == fn)
|
||||||
|
{
|
||||||
|
// Forget about it
|
||||||
|
m_ExtCommands[i] = nullptr;
|
||||||
|
return 1; // Successfully unregistered
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No space
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
int32_t Core::SendExtCommand(int32_t target, int32_t req, int32_t tag, const uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
int32_t count = 0;
|
||||||
|
// Send the command to all registered function pointers
|
||||||
|
for (size_t i = 0; i < m_ExtCommands.max_size(); ++i)
|
||||||
|
{
|
||||||
|
if (m_ExtCommands[i] != nullptr)
|
||||||
|
{
|
||||||
|
const int32_t r = m_ExtCommands[i](target, req, tag, data, size);
|
||||||
|
// Command processed
|
||||||
|
++count;
|
||||||
|
// Command failed?
|
||||||
|
if (r < 0)
|
||||||
|
{
|
||||||
|
LogErr("External command failed (%i): target(%i), req(%i), tag(%i), data(%p), size (%zu)",
|
||||||
|
r, target, req, tag, data, size);
|
||||||
|
}
|
||||||
|
// Command consumed?
|
||||||
|
else if (r > 0)
|
||||||
|
{
|
||||||
|
break; // This function pointer requested exclusive access over this command
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Return how many function pointers received this command
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
bool Core::DoScripts(Scripts::iterator itr, Scripts::iterator end)
|
bool Core::DoScripts(Scripts::iterator itr, Scripts::iterator end)
|
||||||
{
|
{
|
||||||
@ -2371,6 +2447,8 @@ void Core::InitEvents()
|
|||||||
InitSignalPair(mOnServerOption, m_Events, "ServerOption");
|
InitSignalPair(mOnServerOption, m_Events, "ServerOption");
|
||||||
InitSignalPair(mOnScriptReload, m_Events, "ScriptReload");
|
InitSignalPair(mOnScriptReload, m_Events, "ScriptReload");
|
||||||
InitSignalPair(mOnScriptLoaded, m_Events, "ScriptLoaded");
|
InitSignalPair(mOnScriptLoaded, m_Events, "ScriptLoaded");
|
||||||
|
InitSignalPair(mOnExtCommandReply, m_Events, "ExtCommandReply");
|
||||||
|
InitSignalPair(mOnExtCommandEvent, m_Events, "ExtCommandEvent");
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void Core::DropEvents()
|
void Core::DropEvents()
|
||||||
@ -2516,6 +2594,8 @@ void Core::DropEvents()
|
|||||||
ResetSignalPair(mOnServerOption);
|
ResetSignalPair(mOnServerOption);
|
||||||
ResetSignalPair(mOnScriptReload);
|
ResetSignalPair(mOnScriptReload);
|
||||||
ResetSignalPair(mOnScriptLoaded);
|
ResetSignalPair(mOnScriptLoaded);
|
||||||
|
ResetSignalPair(mOnExtCommandReply);
|
||||||
|
ResetSignalPair(mOnExtCommandEvent);
|
||||||
m_Events.Release();
|
m_Events.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2861,6 +2941,31 @@ static LightObj & SqGetClientDataBuffer()
|
|||||||
return Core::Get().GetClientDataBuffer();
|
return Core::Get().GetClientDataBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static SQInteger SqSendExtCommand(int32_t target, int32_t req, int32_t tag, SqBuffer & buffer)
|
||||||
|
{
|
||||||
|
// Default to an empty/null buffer
|
||||||
|
const uint8_t * data = nullptr;
|
||||||
|
size_t size = 0;
|
||||||
|
// Does the buffer actually point to anything?
|
||||||
|
if (buffer.GetRef())
|
||||||
|
{
|
||||||
|
data = buffer.GetRef()->Begin< uint8_t >();
|
||||||
|
size = buffer.GetRef()->PositionAs< size_t >();
|
||||||
|
}
|
||||||
|
// Forward the request
|
||||||
|
return Core::Get().SendExtCommand(target, req, tag, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static SQInteger SqSendExtCommandStr(int32_t target, int32_t req, int32_t tag, StackStrF & str)
|
||||||
|
{
|
||||||
|
// Forward the request
|
||||||
|
return Core::Get().SendExtCommand(target, req, tag,
|
||||||
|
reinterpret_cast< const uint8_t * >(str.mPtr),
|
||||||
|
str.mLen <= 0 ? 0 : static_cast< size_t >(str.mLen));
|
||||||
|
}
|
||||||
|
|
||||||
// ================================================================================================
|
// ================================================================================================
|
||||||
void Register_Core(HSQUIRRELVM vm)
|
void Register_Core(HSQUIRRELVM vm)
|
||||||
{
|
{
|
||||||
@ -2910,6 +3015,8 @@ void Register_Core(HSQUIRRELVM vm)
|
|||||||
.Func(_SC("DestroyPickup"), &SqDelPickup)
|
.Func(_SC("DestroyPickup"), &SqDelPickup)
|
||||||
.Func(_SC("DestroyVehicle"), &SqDelVehicle)
|
.Func(_SC("DestroyVehicle"), &SqDelVehicle)
|
||||||
.Func(_SC("ClientDataBuffer"), &SqGetClientDataBuffer)
|
.Func(_SC("ClientDataBuffer"), &SqGetClientDataBuffer)
|
||||||
|
.Func(_SC("SendExtCommand"), &SqSendExtCommand)
|
||||||
|
.FmtFunc(_SC("SendExtCommandStr"), &SqSendExtCommandStr)
|
||||||
.Func(_SC("OnPreLoad"), &SqGetPreLoadEvent)
|
.Func(_SC("OnPreLoad"), &SqGetPreLoadEvent)
|
||||||
.Func(_SC("OnPostLoad"), &SqGetPostLoadEvent)
|
.Func(_SC("OnPostLoad"), &SqGetPostLoadEvent)
|
||||||
.Func(_SC("OnUnload"), &SqGetUnloadEvent)
|
.Func(_SC("OnUnload"), &SqGetUnloadEvent)
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include "SDK/sqmod.h"
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
namespace SqMod {
|
namespace SqMod {
|
||||||
|
|
||||||
@ -56,6 +59,8 @@ public:
|
|||||||
typedef std::vector< ScriptSrc > Scripts; // List of loaded scripts.
|
typedef std::vector< ScriptSrc > Scripts; // List of loaded scripts.
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
typedef std::unordered_map< String, String > Options; // List of custom options.
|
typedef std::unordered_map< String, String > Options; // List of custom options.
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
typedef std::array< ExtPluginCommand_t, 4 > ExtCommands; // 4 external command parsers should be enough.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -68,6 +73,7 @@ private:
|
|||||||
Scripts m_Scripts; // Loaded scripts objects.
|
Scripts m_Scripts; // Loaded scripts objects.
|
||||||
Scripts m_PendingScripts; // Pending scripts objects.
|
Scripts m_PendingScripts; // Pending scripts objects.
|
||||||
Options m_Options; // Custom configuration options.
|
Options m_Options; // Custom configuration options.
|
||||||
|
ExtCommands m_ExtCommands; // External command parsers pointers.
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
Blips m_Blips; // Blips pool.
|
Blips m_Blips; // Blips pool.
|
||||||
@ -399,6 +405,23 @@ public:
|
|||||||
*/
|
*/
|
||||||
SQMOD_NODISCARD String FetchCodeLine(const SQChar * src, SQInteger line, bool trim = true);
|
SQMOD_NODISCARD String FetchCodeLine(const SQChar * src, SQInteger line, bool trim = true);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Register a pointer to a function used to processes commands from script.
|
||||||
|
* Returns -1 it failed (no free slot), 0 if it was already registered and 1 if it succeeded.
|
||||||
|
*/
|
||||||
|
int32_t RegisterExtCommand(ExtPluginCommand_t fn);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Remove a pointer to a function used to processes commands from script.
|
||||||
|
* Returns -1 it failed (no free slot) and 1 if it succeeded.
|
||||||
|
*/
|
||||||
|
int32_t UnregisterExtCommand(ExtPluginCommand_t fn);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Send a command to all functions currently registered to receive them.
|
||||||
|
*/
|
||||||
|
int32_t SendExtCommand(int32_t target, int32_t req, int32_t tag, const uint8_t * data, size_t size);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -710,6 +733,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
void EmitClientScriptData(int32_t player_id, const uint8_t * data, size_t size);
|
void EmitClientScriptData(int32_t player_id, const uint8_t * data, size_t size);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Send a response to the script that may have resulted from a previous command.
|
||||||
|
*/
|
||||||
|
void EmitExtCommandReply(int32_t sender, int32_t tag, const uint8_t * data, size_t size);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* Forward an event to the script from an external plug-in.
|
||||||
|
*/
|
||||||
|
void EmitExtCommandEvent(int32_t sender, int32_t tag, const uint8_t * data, size_t size);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------------------------
|
||||||
@ -864,6 +897,8 @@ public:
|
|||||||
SignalPair mOnServerOption{};
|
SignalPair mOnServerOption{};
|
||||||
SignalPair mOnScriptReload{};
|
SignalPair mOnScriptReload{};
|
||||||
SignalPair mOnScriptLoaded{};
|
SignalPair mOnScriptLoaded{};
|
||||||
|
SignalPair mOnExtCommandReply{};
|
||||||
|
SignalPair mOnExtCommandEvent{};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------------------------------
|
||||||
|
@ -347,7 +347,7 @@ void Core::EmitIncomingConnection(char * player_name, size_t name_buffer_size, c
|
|||||||
// Release any stored buffer information
|
// Release any stored buffer information
|
||||||
m_IncomingNameBuffer = nullptr;
|
m_IncomingNameBuffer = nullptr;
|
||||||
m_IncomingNameCapacity = 0;
|
m_IncomingNameCapacity = 0;
|
||||||
// We catched the exception so we can release the assigned buffer
|
// We caught the exception so we can release the assigned buffer
|
||||||
throw; // re-throw it
|
throw; // re-throw it
|
||||||
}
|
}
|
||||||
// Release any stored buffer information
|
// Release any stored buffer information
|
||||||
@ -2246,6 +2246,44 @@ void Core::EmitClientScriptData(int32_t player_id, const uint8_t * data, size_t
|
|||||||
m_ClientData.Release();
|
m_ClientData.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Core::EmitExtCommandReply(int32_t sender, int32_t tag, const uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
SQMOD_CO_EV_TRACEBACK("[TRACE<] Core::ExtCommandReply(%i, %i, %p, %zu)", sender, tag, data, size)
|
||||||
|
// Don't even bother if there's no one listening
|
||||||
|
if (!(mOnExtCommandReply.first->IsEmpty()))
|
||||||
|
{
|
||||||
|
// Allocate a buffer with the received size
|
||||||
|
Buffer b(static_cast< Buffer::SzType >(size));
|
||||||
|
// Replicate the data to the allocated buffer
|
||||||
|
b.Write(0, reinterpret_cast< Buffer::ConstPtr >(data), static_cast< Buffer::SzType >(size));
|
||||||
|
// Prepare an object for the obtained buffer
|
||||||
|
LightObj obj(SqTypeIdentity< SqBuffer >{}, m_VM, std::move(b));
|
||||||
|
// Forward the event call
|
||||||
|
(*mOnExtCommandReply.first)(sender, tag, obj, size);
|
||||||
|
}
|
||||||
|
SQMOD_CO_EV_TRACEBACK("[TRACE>] Core::ExtCommandReply")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void Core::EmitExtCommandEvent(int32_t sender, int32_t tag, const uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
SQMOD_CO_EV_TRACEBACK("[TRACE<] Core::ExtCommandEvent(%i, %i, %p, %zu)", sender, tag, data, size)
|
||||||
|
// Don't even bother if there's no one listening
|
||||||
|
if (!(mOnExtCommandEvent.first->IsEmpty()))
|
||||||
|
{
|
||||||
|
// Allocate a buffer with the received size
|
||||||
|
Buffer b(static_cast< Buffer::SzType >(size));
|
||||||
|
// Replicate the data to the allocated buffer
|
||||||
|
b.Write(0, reinterpret_cast< Buffer::ConstPtr >(data), static_cast< Buffer::SzType >(size));
|
||||||
|
// Prepare an object for the obtained buffer
|
||||||
|
LightObj obj(SqTypeIdentity< SqBuffer >{}, m_VM, std::move(b));
|
||||||
|
// Forward the event call
|
||||||
|
(*mOnExtCommandEvent.first)(sender, tag, obj, size);
|
||||||
|
}
|
||||||
|
SQMOD_CO_EV_TRACEBACK("[TRACE>] Core::ExtCommandEvent")
|
||||||
|
}
|
||||||
|
|
||||||
#undef NULL_SQOBJ_ // don't need this anymore
|
#undef NULL_SQOBJ_ // don't need this anymore
|
||||||
|
|
||||||
} // Namespace:: SqMod
|
} // Namespace:: SqMod
|
||||||
|
73
module/Exports.cpp
Normal file
73
module/Exports.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include "Core.hpp"
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
#include <sqmod.h>
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
namespace SqMod {
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static int32_t RegisterCommandFn(ExtPluginCommand_t fn)
|
||||||
|
{
|
||||||
|
return Core::Get().RegisterExtCommand(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static int32_t UnregisterCommandFn(ExtPluginCommand_t fn)
|
||||||
|
{
|
||||||
|
return Core::Get().UnregisterExtCommand(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static int32_t SendCommandFn(int32_t target, int32_t req, int32_t tag, const uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
return Core::Get().SendExtCommand(target, req, tag, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static int32_t SendCommandReplyFn(int32_t sender, int32_t tag, const uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
// Mark the initialization as successful by default
|
||||||
|
const CoreState cs(SQMOD_SUCCESS);
|
||||||
|
// Forward the call to the script callbacks
|
||||||
|
Core::Get().EmitExtCommandReply(sender, tag, data, size);
|
||||||
|
// Return the last known plug-in state
|
||||||
|
return Core::Get().GetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static int32_t SendCommandEventFn(int32_t sender, int32_t tag, const uint8_t * data, size_t size)
|
||||||
|
{
|
||||||
|
// Mark the initialization as successful by default
|
||||||
|
const CoreState cs(SQMOD_SUCCESS);
|
||||||
|
// Forward the call to the script callbacks
|
||||||
|
Core::Get().EmitExtCommandEvent(sender, tag, data, size);
|
||||||
|
// Return the last known plug-in state
|
||||||
|
return Core::Get().GetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
static const SQ_MOD_EXPORTS g_SqModExports{
|
||||||
|
sizeof(SQ_MOD_EXPORTS),
|
||||||
|
&RegisterCommandFn,
|
||||||
|
&UnregisterCommandFn,
|
||||||
|
&SendCommandFn,
|
||||||
|
&SendCommandReplyFn,
|
||||||
|
&SendCommandEventFn
|
||||||
|
};
|
||||||
|
|
||||||
|
// The server needs a pointer to a pointer, and a persistent one
|
||||||
|
static const SQ_MOD_EXPORTS * g_SqModExportsPtr = &g_SqModExports;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
void InitExports()
|
||||||
|
{
|
||||||
|
// Tell the server about the pointer to the exports structure
|
||||||
|
_Func->ExportFunctions(_Info->pluginId, reinterpret_cast< const void ** >(&g_SqModExportsPtr), sizeof(HSQ_MOD_EXPORTS));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Namespace:: SqMod
|
@ -17,7 +17,7 @@ namespace SqMod {
|
|||||||
static bool g_Reload = false;
|
static bool g_Reload = false;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
//extern void InitExports();
|
extern void InitExports();
|
||||||
extern void InitializeNet();
|
extern void InitializeNet();
|
||||||
extern void InitializePocoDataConnectors();
|
extern void InitializePocoDataConnectors();
|
||||||
extern void ProcessRoutines();
|
extern void ProcessRoutines();
|
||||||
@ -1083,7 +1083,7 @@ SQMOD_API_EXPORT unsigned int VcmpPluginInit(PluginFuncs * funcs, PluginCallback
|
|||||||
_Clbk->OnEntityStreamingChange = OnEntityStreamingChange;
|
_Clbk->OnEntityStreamingChange = OnEntityStreamingChange;
|
||||||
#endif
|
#endif
|
||||||
// Attempt to initialize the plug-in exports
|
// Attempt to initialize the plug-in exports
|
||||||
//InitExports();
|
InitExports();
|
||||||
// Dummy spacing
|
// Dummy spacing
|
||||||
puts("");
|
puts("");
|
||||||
// Initialization was successful
|
// Initialization was successful
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
#ifndef _REGISTER_HPP_
|
|
||||||
#define _REGISTER_HPP_
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
#include <squirrelex.h>
|
#include <squirrelex.h>
|
||||||
|
|
||||||
@ -144,5 +141,3 @@ bool RegisterAPI(HSQUIRRELVM vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
} // Namespace:: SqMod
|
} // Namespace:: SqMod
|
||||||
|
|
||||||
#endif // _REGISTER_HPP_
|
|
||||||
|
75
module/SDK/sqmod.h
Normal file
75
module/SDK/sqmod.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#if !defined(_SQ_MOD_API_H_)
|
||||||
|
#define _SQ_MOD_API_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#ifndef SQMOD_API_EXPORT
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define SQMOD_API_EXPORT extern "C" __declspec(dllexport)
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define SQMOD_API_EXPORT extern "C"
|
||||||
|
#else
|
||||||
|
#define SQMOD_API_EXPORT extern "C"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SQMOD_HOST_NAME "SqModHost"
|
||||||
|
#define SQMOD_INITIALIZE_CMD 0xDABBAD00
|
||||||
|
#define SQMOD_LOAD_CMD 0xDEADBABE // API is being registered
|
||||||
|
#define SQMOD_TERMINATE_CMD 0xDEADC0DE // release your resources
|
||||||
|
#define SQMOD_CLOSING_CMD 0xBAAAAAAD // virtual machine is closing
|
||||||
|
#define SQMOD_RELEASED_CMD 0xDEADBEAF // virtual machine was closed
|
||||||
|
#define SQMOD_API_VER 1
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------------------------
|
||||||
|
typedef int32_t(*ExtPluginCommand_t)(int32_t, int32_t, int32_t, const uint8_t *, size_t);
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------
|
||||||
|
* The structure exported by the host plug-in to import the module and squirrel API.
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint32_t StructSize;
|
||||||
|
/* Register a pointer to a function used to processes commands from script.
|
||||||
|
This is like the functionality offered by SendPluginCommand but offers interaction from
|
||||||
|
script side without interfering with other native plugins. And also offers a few extra
|
||||||
|
methods of identification to provide back and forth communication.
|
||||||
|
It offers a bare minimum, primitive way of interacting with the script from native plug-ins.
|
||||||
|
return : -1 it failed (no free slot), 0 if it was already registered and 1 if it succeeded.
|
||||||
|
*/
|
||||||
|
int32_t (*RegisterCommand) (ExtPluginCommand_t fn);
|
||||||
|
/* Remove a pointer to a function used to processes commands from script.
|
||||||
|
return : -1 it failed (no free slot) and 1 if it succeeded.
|
||||||
|
*/
|
||||||
|
int32_t (*UnregisterCommand) (ExtPluginCommand_t fn);
|
||||||
|
/* Send a command to all functions currently registered to receive them. This is mostly used by the script.
|
||||||
|
target - ideally a unique value that can be used to identify the intended audience for the command.
|
||||||
|
req : ideally a unique value that can be used to identify the requested information from the command.
|
||||||
|
tag : ideally a unique value that can be used to identify a later response if one is generated.
|
||||||
|
data : binary data that represents the command payload. the command is free to interpret it however it wants.
|
||||||
|
size : size of the binary data. most likely in bytes but the command is free to interpret it however it wants.
|
||||||
|
*/
|
||||||
|
int32_t (*SendCommand) (int32_t target, int32_t req, int32_t tag, const uint8_t * data, size_t size);
|
||||||
|
/* Send a response to the script that may have resulted from a previous command. This is mostly by the native plug-ins.
|
||||||
|
sender : ideally a unique value that can be used to identify the intended who generated the response.
|
||||||
|
tag : ideally a unique value that can be used to identify what the generated response might contain/provide.
|
||||||
|
data : binary data that represents the command payload. the command is free to interpret it however it wants.
|
||||||
|
size : size of the binary data. most likely in bytes but the command is free to interpret it however it wants.
|
||||||
|
*/
|
||||||
|
int32_t (*SendCommandReply) (int32_t sender, int32_t tag, const uint8_t * data, size_t size);
|
||||||
|
/* Forward an event to the script from an external plug-in. This is mostly by the native plug-ins.
|
||||||
|
Similar to SendCommandReply but may not have been the result of a previous command.
|
||||||
|
*/
|
||||||
|
int32_t (*SendCommandEvent) (int32_t sender, int32_t tag, const uint8_t * data, size_t size);
|
||||||
|
} sq_mod_exports, SQ_MOD_EXPORTS, *HSQ_MOD_EXPORTS;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /*extern "C"*/
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#endif /*_SQ_MOD_API_H_*/
|
Loading…
Reference in New Issue
Block a user