1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 00:37:15 +01:00

Implement script loading with notification.

This commit is contained in:
Sandu Liviu Catalin 2021-07-03 19:46:39 +03:00
parent a710ceebff
commit f2c1f8afd7
6 changed files with 120 additions and 28 deletions

View File

@ -71,18 +71,17 @@ extern Buffer GetRealFilePath(const SQChar * path);
/* ------------------------------------------------------------------------------------------------
* Loader used to process a section from the configuration file and look for scripts to load.
*/
class ScriptLoader
struct ScriptLoader
{
// --------------------------------------------------------------------------------------------
CSimpleIniA & m_Config; // The processed configuration.
public:
CSimpleIniA & m_Config; // The processed configuration.
Function m_Callback{}; // Null callback.
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
explicit ScriptLoader(CSimpleIniA & conf)
: m_Config(conf)
: m_Config(conf), m_Callback()
{
/* ... */
}
@ -90,7 +89,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Function call operator.
*/
bool operator () (const char * key, const char * val) const
bool operator () (const char * key, const char * val)
{
// Validate the specified key
if (!key || *key == '\0')
@ -104,11 +103,11 @@ public:
}
else if (std::strcmp(key, "Compile") == 0)
{
return Core::Get().LoadScript(val, true);
return Core::Get().LoadScript(val, m_Callback, true);
}
else if (std::strcmp(key, "Execute") == 0)
{
return Core::Get().LoadScript(val, false);
return Core::Get().LoadScript(val, m_Callback, false);
}
// Move to the next element!
return true;
@ -717,7 +716,7 @@ Core::Scripts::iterator Core::FindPendingScript(const SQChar * src)
}
// ------------------------------------------------------------------------------------------------
bool Core::LoadScript(const SQChar * filepath, bool delay)
bool Core::LoadScript(const SQChar * filepath, Function & cb, bool delay)
{
// Is the specified path empty?
if (!filepath || *filepath == '\0')
@ -761,7 +760,7 @@ bool Core::LoadScript(const SQChar * filepath, bool delay)
else if (m_Executed)
{
// Create a new script container and insert it into the script pool
m_Scripts.emplace_back(path, delay, m_Debugging);
m_Scripts.emplace_back(path, cb, delay, m_Debugging);
// Attempt to load and compile the script file
try
@ -782,7 +781,14 @@ bool Core::LoadScript(const SQChar * filepath, bool delay)
// Attempt to execute the compiled script code
try
{
m_Scripts.back().mExec.Run();
auto & s = m_Scripts.back();
// Attempt to run the script
s.mExec.Run();
// Does someone need to be notified?
if (!s.mFunc.IsNull())
{
s.mFunc.Execute(s.mPath, s.mExec);
}
}
catch (const std::exception & e)
{
@ -803,7 +809,7 @@ bool Core::LoadScript(const SQChar * filepath, bool delay)
try
{
// Create a new script container and insert it into the pending script pool
m_PendingScripts.emplace_back(path, delay, m_Debugging);
m_PendingScripts.emplace_back(path, cb, delay, m_Debugging);
}
catch (const std::exception & e)
{
@ -900,7 +906,14 @@ bool Core::DoScripts(Scripts::iterator itr, Scripts::iterator end)
// Attempt to execute the compiled script code
try
{
(*itr).mExec.Run();
auto & s = *itr;
// Attempt to run the script
s.mExec.Run();
// Does someone need to be notified?
if (!s.mFunc.IsNull())
{
s.mFunc.Execute(s.mPath, s.mExec);
}
}
catch (const std::exception & e)
{
@ -925,11 +938,18 @@ bool Core::DoScripts(Scripts::iterator itr, Scripts::iterator end)
// Attempt to execute the compiled script code
try
{
(*itr).mExec.Run();
auto & s = *itr;
// Attempt to run the script
s.mExec.Run();
// Does someone need to be notified?
if (!s.mFunc.IsNull())
{
s.mFunc.Execute(s.mPath, s.mExec);
}
}
catch (const std::exception & e)
{
LogFtl("Unable to execute: %s", (*itr).mPath.c_str());
LogFtl("Unable to execute (%s) exception caught: %s", (*itr).mPath.c_str(), e.what());
// Failed to execute properly
return false;
}
@ -2477,12 +2497,19 @@ static SQInteger SqLoadScript(HSQUIRRELVM vm)
{
return sq_throwerror(vm, "Failed to retrieve the delay parameter");
}
Function cb;
// Forward the call to the actual implementation
sq_pushbool(vm, Core::Get().LoadScript(val.mPtr, static_cast< bool >(delay)));
sq_pushbool(vm, Core::Get().LoadScript(val.mPtr, cb, static_cast< bool >(delay)));
// We have an argument on the stack
return 1;
}
// ------------------------------------------------------------------------------------------------
static bool SqLoadScriptNotify(bool delay, StackStrF & path, Function & cb)
{
return Core::Get().LoadScript(path.mPtr, cb, delay);
}
// ------------------------------------------------------------------------------------------------
static SQInteger SqGetEvents(HSQUIRRELVM vm)
{
@ -2813,6 +2840,7 @@ void Register_Core(HSQUIRRELVM vm)
.Func(_SC("OnPreLoad"), &SqGetPreLoadEvent)
.Func(_SC("OnPostLoad"), &SqGetPostLoadEvent)
.Func(_SC("OnUnload"), &SqGetUnloadEvent)
.CbFunc(_SC("LoadScriptNotify"), &SqLoadScriptNotify)
.SquirrelFunc(_SC("ForceEnableNullEntities"), &SqForceEnableNullEntities)
.SquirrelFunc(_SC("LoadScript"), &SqLoadScript, -3, ".b.")
.SquirrelFunc(_SC("On"), &SqGetEvents);

View File

@ -368,7 +368,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Adds a script to the load queue.
*/
bool LoadScript(const SQChar * filepath, bool delay);
bool LoadScript(const SQChar * filepath, Function & cb, bool delay = false);
/* --------------------------------------------------------------------------------------------
* Modify the name for the currently assigned incoming connection.

View File

@ -148,8 +148,9 @@ void ScriptSrc::Process()
}
// ------------------------------------------------------------------------------------------------
ScriptSrc::ScriptSrc(const String & path, bool delay, bool info) // NOLINT(modernize-pass-by-value)
ScriptSrc::ScriptSrc(const String & path, Function & cb, bool delay, bool info) // NOLINT(modernize-pass-by-value)
: mExec()
, mFunc(std::move(cb))
, mPath(path)
, mData()
, mLine()

View File

@ -19,20 +19,19 @@ class Core;
/* ------------------------------------------------------------------------------------------------
* Hold a information about loaded scripts as it's contents and executable code.
*/
class ScriptSrc
struct ScriptSrc
{
public:
// --------------------------------------------------------------------------------------------
typedef std::vector< std::pair< uint32_t, uint32_t > > Line;
// --------------------------------------------------------------------------------------------
Script mExec; // Reference to the script object.
String mPath; // Path to the script file.
String mData; // The contents of the script file.
Line mLine; // List of lines of code in the data.
bool mInfo; // Whether this script contains line information.
bool mDelay; // Don't execute immediately after compilation.
Script mExec{}; // Reference to the script object.
Function mFunc{}; // Callback to invoke after script was executed.
String mPath{}; // Path to the script file.
String mData{}; // The contents of the script file.
Line mLine{}; // List of lines of code in the data.
bool mInfo{false}; // Whether this script contains line information.
bool mDelay{false}; // Don't execute immediately after compilation.
/* --------------------------------------------------------------------------------------------
* Read file contents and calculate information about the lines of code.
@ -42,7 +41,7 @@ public:
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
explicit ScriptSrc(const String & path, bool delay = false, bool info = false);
explicit ScriptSrc(const String & path, Function & cb, bool delay = false, bool info = false);
/* --------------------------------------------------------------------------------------------
* Copy constructor.

View File

@ -42,6 +42,8 @@ namespace Sqrat {
class Script : public Object {
public:
using Object::Object;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Default constructor
///
@ -245,4 +247,49 @@ public:
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Used to get and push Script instances to and from the stack as references (Script is always a reference)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
struct Var<Script> {
Script value; ///< The actual value of get operations
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Attempts to get the value off the stack at idx as an Script
///
/// \param vm Target VM
/// \param idx Index trying to be read
///
/// \remarks
/// This function MUST have its Error handled if it occurred.
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Var(HSQUIRRELVM vm, SQInteger idx) : value(idx, vm) {
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Called by Sqrat::PushVar to put an Script on the stack
///
/// \param vm Target VM
/// \param value Value to push on to the VM's stack
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static void push(HSQUIRRELVM vm, const Script& value) {
sq_pushobject(vm, value.GetObj());
}
};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Used to get and push Script instances to and from the stack as references (Script is always a reference)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
struct Var<Script&> : Var<Script> {Var(HSQUIRRELVM vm, SQInteger idx) : Var<Script>(vm, idx) {}};
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Used to get and push Script instances to and from the stack as references (Script is always a reference)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<>
struct Var<const Script&> : Var<Script> {Var(HSQUIRRELVM vm, SQInteger idx) : Var<Script>(vm, idx) {}};
}

View File

@ -328,6 +328,23 @@ public:
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Sets a key in the Table to a specific function with callback support
///
/// \param name The key in the table being assigned a value
/// \param method Function that is being placed in the Table
///
/// \tparam F Type of function (only define this if you need to choose a certain template specialization or overload)
///
/// \return The Table itself so the call can be chained
///
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<class F>
TableBase& CbFunc(const SQChar* name, F method) {
BindFunc(name, &method, sizeof(method), SqGlobalFunc(method));
return *this;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Sets a key in the Table to a specific function and allows the key to be overloaded with functions of a different amount of arguments
///