Skip to content

Commit

Permalink
Better documentation, added outExecuted params for ExecuteScript*
Browse files Browse the repository at this point in the history
  • Loading branch information
CromFr committed Mar 9, 2024
1 parent 35db225 commit 851e3b7
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 23 deletions.
27 changes: 24 additions & 3 deletions include/nwnx_cplugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,41 @@ struct NWNXCPlugin_InitInfo {
const char* nwn2_module_path;
/// Path to the NWNX4 user directory, where nwnx4_controller.exe is located.
const char* nwnx_install_path;

/// Function pointers to interact with the nwn2server instance
const struct NWNXCPlugin_NWN2Hooks* nwn2_hooks;
};

typedef void(ExecuteScriptFn)(const char* sScript, uint32_t oTarget);
/// Bound to NWScript ExecuteScript function
/// @param outExecuted If not null, the bool will be set to true if the script
/// has been successfully executed.
typedef void(ExecuteScriptFn)(const char* sScript, uint32_t oTarget, bool* outExecuted);
/// Bound to NWScript ExecuteScriptEnhanced function
/// @param outExecuted If not null, the bool will be set to true if the script
/// has been successfully executed. This is used to differenciate between a
/// script returning the value -1 and a script not being executed.
typedef int32_t(ExecuteScriptEnhancedFn)(const char* sScriptName,
uint32_t oTarget,
bool bClearParams);
bool bClearParams,
bool* outExecuted);
/// Bound to NWScript AddScriptParameterInt function. Bound values are not
/// shared between the NWScript and CPlugin environments
typedef void(AddScriptParameterIntFn)(int32_t nParam);
/// Bound to NWScript AddScriptParameterString function. Bound values are not
/// shared between the NWScript and CPlugin environments.
/// @warning The string value is only borrowed and must live at least until
/// ExecuteScriptEnhanced is called
typedef void(AddScriptParameterStringFn)(const char* sParam);
/// Bound to NWScript AddScriptParameterFloat function. Bound values are not
/// shared between the NWScript and CPlugin environments
typedef void(AddScriptParameterFloatFn)(float fParam);
/// Bound to NWScript AddScriptParameterObject function. Bound values are not
/// shared between the NWScript and CPlugin environments
typedef void(AddScriptParameterObjectFn)(uint32_t oParam);
/// Bound to NWScript ClearScriptParams function. Only clears the bound values
/// from the CPlugin environment
typedef void(ClearScriptParamsFn)();

/// Function pointers to interact with the nwn2server instance
struct NWNXCPlugin_NWN2Hooks {
ExecuteScriptFn* ExecuteScript;
ExecuteScriptEnhancedFn* ExecuteScriptEnhanced;
Expand Down
38 changes: 24 additions & 14 deletions src/hook/scriptManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ static_assert(sizeof(NWN2ParamsList) == 8);
static struct NWN2ParamsList* nwn2_scriptparams = (struct NWN2ParamsList*)(0x0086F15C);
// static size_t scriptparams_count = 0;

struct CVirtualMachine { };
struct CVirtualMachine {
uint32_t _;
uint32_t execscript_ret_value;
};
static CVirtualMachine** nwn2_vm
= std::bit_cast<struct CVirtualMachine**>(NWN2_OFFSET_CVIRTUALMACHINE);

Expand All @@ -57,37 +60,41 @@ static CVirtualMachine_ExecuteScript_t CVirtualMachine_ExecuteScript
using CVirtualMachine_ExecuteScriptEnhanced_t
= int32_t(__thiscall*)(CVirtualMachine* thisVM,
const NWN::CExoString& scriptName,
// const NWN::CExoString& scriptName,
NWN::OBJECTID objectID,
void* ParamList,
uint32_t unknow1,
uint32_t unknow2);
static CVirtualMachine_ExecuteScriptEnhanced_t CVirtualMachine_ExecuteScriptEnhanced
= std::bit_cast<CVirtualMachine_ExecuteScriptEnhanced_t>(NWN2_OFFSET_EXECUTESCRIPT_ENH);

//
using CVirtualMachine_InitParam_t = void(__thiscall*)(void* paramLst, uint32_t iNb);
static CVirtualMachine_InitParam_t CVirtualMachine_InitParam
= std::bit_cast<CVirtualMachine_InitParam_t>(NWN2_OFFSET_InitParam);
// //
// using CVirtualMachine_InitParam_t = void(__thiscall*)(void* paramLst, uint32_t iNb);
// static CVirtualMachine_InitParam_t CVirtualMachine_InitParam
// = std::bit_cast<CVirtualMachine_InitParam_t>(NWN2_OFFSET_InitParam);

//
using CVirtualMachine_CleanParam_t = void(__thiscall*)(void* paramLst);
static CVirtualMachine_CleanParam_t CVirtualMachine_CleanParam
= std::bit_cast<CVirtualMachine_CleanParam_t>(NWN2_OFFSET_CleanParam);
// //
// using CVirtualMachine_CleanParam_t = void(__thiscall*)(void* paramLst);
// static CVirtualMachine_CleanParam_t CVirtualMachine_CleanParam
// = std::bit_cast<CVirtualMachine_CleanParam_t>(NWN2_OFFSET_CleanParam);

namespace NWScript {

void ExecuteScript(const char* sScript, NWN::OBJECTID oTarget)
void ExecuteScript(const char* sScript, NWN::OBJECTID oTarget, bool* outExecuted)
{
logger->Trace("ExecuteScript %s, %lu", sScript, oTarget);
CVirtualMachine_ExecuteScript(
auto executed = CVirtualMachine_ExecuteScript(
*nwn2_vm,
NWN::CExoString {.m_sString = (char*)sScript, // un-const cast, safe as param is read only
.m_nBufferLength = strlen(sScript)},
oTarget, 1, 1);
if (outExecuted != nullptr)
*outExecuted = executed;
}

int32_t ExecuteScriptEnhanced(const char* sScriptName, NWN::OBJECTID oTarget, bool bClearParams)
int32_t ExecuteScriptEnhanced(const char* sScriptName,
NWN::OBJECTID oTarget,
bool bClearParams,
bool* outExecuted)
{
logger->Trace("ExecuteScriptEnhanced %s, %lu", sScriptName, oTarget);

Expand All @@ -103,9 +110,12 @@ int32_t ExecuteScriptEnhanced(const char* sScriptName, NWN::OBJECTID oTarget, bo
int retValue
= CVirtualMachine_ExecuteScriptEnhanced(*nwn2_vm, script, oTarget, nwn2_scriptparams, 1, 1);

if (outExecuted != nullptr)
*outExecuted = retValue != 0;

// Is the script ok?
if (retValue != 0)
retValue = ((uint32_t*)*nwn2_vm)[1];
retValue = (*nwn2_vm)->execscript_ret_value;
else
retValue = -1;

Expand Down
7 changes: 5 additions & 2 deletions src/hook/scriptManagement.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@
namespace NWScript {

extern "C" {
void ExecuteScript(const char* sScript, NWN::OBJECTID oTarget);
int32_t ExecuteScriptEnhanced(const char* sScriptName, NWN::OBJECTID oTarget, bool bClearParams);
void ExecuteScript(const char* sScript, NWN::OBJECTID oTarget, bool* outExecuted = NULL);
int32_t ExecuteScriptEnhanced(const char* sScriptName,
NWN::OBJECTID oTarget,
bool bClearParams,
bool* outExecuted = NULL);
void AddScriptParameterInt(int32_t nParam);
void AddScriptParameterString(const char* sParam);
void AddScriptParameterFloat(float fParam);
Expand Down
24 changes: 20 additions & 4 deletions src/plugins/xp_example_cplugin/cplugin_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,19 +105,35 @@ NWNXCPlugin_GetInt(void* cplugin, const char* sFunction, const char* sParam1, in
return plugin->counter;
} else if (function == "TEST_EXECUTESCRIPT") {
constexpr uint32_t OBJID_MODULE = 0;
plugin->hooks.ExecuteScript("gui_test_executescript", OBJID_MODULE);
return 12;
bool executed = false;
plugin->hooks.ExecuteScript("gui_test_executescript", OBJID_MODULE, &executed);
return executed == true ? 12 : 0;
} else if (function == "TEST_EXECUTESCRIPTBAD") {
constexpr uint32_t OBJID_MODULE = 0;
bool executed = true;
plugin->hooks.ExecuteScript("euqsgdihohcqsc", OBJID_MODULE, &executed);
return executed == false ? 13 : 0;
} else if (function == "TEST_EXECUTESCRIPTENH") {
constexpr uint32_t OBJID_MODULE = 0;
plugin->hooks.ClearScriptParams();
plugin->hooks.AddScriptParameterString(sParam1);
plugin->hooks.AddScriptParameterFloat(13.37f);
plugin->hooks.AddScriptParameterInt(-1234);
plugin->hooks.AddScriptParameterObject(0x01020304);
return plugin->hooks.ExecuteScriptEnhanced("gui_test_executescriptenh", OBJID_MODULE, true);
bool executed = false;
auto res = plugin->hooks.ExecuteScriptEnhanced("gui_test_executescriptenh", OBJID_MODULE,
true, &executed);
if (!executed)
res -= 1000;
return res;
} else if (function == "TEST_EXECUTESCRIPTENHBAD") {
constexpr uint32_t OBJID_MODULE = 0;
return plugin->hooks.ExecuteScriptEnhanced("euqsgdihohcqsc", OBJID_MODULE, true);
bool executed = true;
auto res
= plugin->hooks.ExecuteScriptEnhanced("euqsgdihohcqsc", OBJID_MODULE, true, &executed);
if (executed)
res -= 1000;
return res;
} else {
plugin->logFile << " ERROR: NWNXCPlugin_GetInt: unknown function \"" << function << "\""
<< std::endl;
Expand Down
Binary file modified test/modules/NWNX4UnitTests/onmoduleload.ncs
Binary file not shown.
3 changes: 3 additions & 0 deletions test/modules/NWNX4UnitTests/onmoduleload.nss
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ void xp_example_cplugin(){
AssertEqS(GetLocalString(GetModule(), "testexescript"), "executed", __FUNCTION__, __LINE__);
DeleteLocalString(GetModule(), "testexescript");

// CPlugin call
AssertEqI(NWNXGetInt("CPluginExample", "TEST_EXECUTESCRIPTBAD", "", 0), 13, __FUNCTION__, __LINE__);

// CPlugin call
AssertEqI(NWNXGetInt("CPluginExample", "TEST_EXECUTESCRIPTENH", "hellow orld", 0), 20, __FUNCTION__, __LINE__);
AssertEqS(GetLocalString(GetModule(), "testexescriptenh_string"), "hellow orld", __FUNCTION__, __LINE__);
Expand Down

0 comments on commit 851e3b7

Please sign in to comment.