mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 00:37:15 +01:00
Changes to command manager.
Add a new callback to audit command parameters. Include extra arguments to fail and post callbacks. Refactor code to simplify some cases.
This commit is contained in:
parent
d5bfeced1c
commit
47ff628a46
@ -363,47 +363,57 @@ int32_t Controller::Exec(Context & ctx)
|
||||
ctx.mBuffer.At(0) = '\0';
|
||||
// Whether the command execution failed
|
||||
bool failed = false;
|
||||
// Object with the command arguments
|
||||
LightObj args;
|
||||
// Do we have to call the command with an associative container?
|
||||
if (ctx.mInstance->m_Associate)
|
||||
{
|
||||
// Create the associative container
|
||||
Table args(SqVM());
|
||||
Table tbl(SqVM());
|
||||
// Copy the arguments into the table
|
||||
for (uint32_t arg = 0; arg < ctx.mArgc; ++arg)
|
||||
{
|
||||
// Do we have use the argument index as the key?
|
||||
if (ctx.mInstance->m_ArgTags[arg].empty())
|
||||
{
|
||||
args.SetValue(SQInteger(arg), ctx.mArgv[arg].second);
|
||||
tbl.SetValue(SQInteger(arg), ctx.mArgv[arg].second);
|
||||
}
|
||||
// Nope, we have a name for this argument!
|
||||
else
|
||||
{
|
||||
args.SetValue(ctx.mInstance->m_ArgTags[arg].c_str(), ctx.mArgv[arg].second);
|
||||
tbl.SetValue(ctx.mInstance->m_ArgTags[arg].c_str(), ctx.mArgv[arg].second);
|
||||
}
|
||||
}
|
||||
// Attempt to execute the command with the specified arguments
|
||||
try
|
||||
{
|
||||
result = ctx.mInstance->Execute(ctx.mInvoker, args);
|
||||
}
|
||||
catch (const std::exception & e)
|
||||
{
|
||||
// Let's store the exception message
|
||||
ctx.mBuffer.WriteS(0, e.what());
|
||||
// Specify that the command execution failed
|
||||
failed = true;
|
||||
}
|
||||
// Store the table object into an abstract script object
|
||||
args = LightObj(tbl.GetObj());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reserve an array for the extracted arguments
|
||||
Array args(SqVM(), ctx.mArgc);
|
||||
Array arr(SqVM(), ctx.mArgc);
|
||||
// Copy the arguments into the array
|
||||
for (uint32_t arg = 0; arg < ctx.mArgc; ++arg)
|
||||
{
|
||||
args.Bind(SQInteger(arg), ctx.mArgv[arg].second);
|
||||
arr.Bind(SQInteger(arg), ctx.mArgv[arg].second);
|
||||
}
|
||||
// Store the table object into an abstract script object
|
||||
args = LightObj(arr.GetObj());
|
||||
}
|
||||
// Allow the user to audit the command parameters
|
||||
try
|
||||
{
|
||||
result = ctx.mInstance->Audit(ctx.mInvoker, args);
|
||||
}
|
||||
catch (const std::exception & e)
|
||||
{
|
||||
// Let's store the exception message
|
||||
ctx.mBuffer.WriteS(0, e.what());
|
||||
// Specify that the command execution failed
|
||||
failed = true;
|
||||
}
|
||||
// Did parameter audit succeeded?
|
||||
if (result && !failed)
|
||||
{
|
||||
// Attempt to execute the command with the specified arguments
|
||||
try
|
||||
{
|
||||
@ -447,15 +457,13 @@ int32_t Controller::Exec(Context & ctx)
|
||||
// Was the command aborted explicitly?
|
||||
else if (!result)
|
||||
{
|
||||
// Tell the script callback to deal with the error
|
||||
SqError(CMDERR_EXECUTION_ABORTED, _SC("Command execution aborted"), result);
|
||||
// Is there a script callback that handles failures?
|
||||
if (!ctx.mInstance->m_OnFail.IsNull())
|
||||
{
|
||||
// Then attempt to relay the result to that function
|
||||
try
|
||||
{
|
||||
ctx.mInstance->m_OnFail.Execute(ctx.mInvoker, result);
|
||||
ctx.mInstance->m_OnFail.Execute(ctx.mInvoker, args, result);
|
||||
}
|
||||
catch (const Poco::Exception& e)
|
||||
{
|
||||
@ -468,6 +476,11 @@ int32_t Controller::Exec(Context & ctx)
|
||||
SqError(CMDERR_UNRESOLVED_FAILURE, _SC("Unable to resolve command failure"), e.what());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tell the script callback to deal with the error
|
||||
SqError(CMDERR_EXECUTION_ABORTED, _SC("Command execution aborted"), result);
|
||||
}
|
||||
}
|
||||
// Is there a callback that must be executed after a successful execution?
|
||||
else if (!ctx.mInstance->m_OnPost.IsNull())
|
||||
@ -475,7 +488,7 @@ int32_t Controller::Exec(Context & ctx)
|
||||
// Then attempt to relay the result to that function
|
||||
try
|
||||
{
|
||||
ctx.mInstance->m_OnPost.Execute(ctx.mInvoker, result);
|
||||
ctx.mInstance->m_OnPost.Execute(ctx.mInvoker, args, result);
|
||||
}
|
||||
catch (const Poco::Exception& e)
|
||||
{
|
||||
@ -1118,6 +1131,7 @@ void Register(HSQUIRRELVM vm)
|
||||
.Prop(_SC("MaxArgs"), &Listener::GetMaxArgC, &Listener::SetMaxArgC)
|
||||
.Prop(_SC("OnExec"), &Listener::GetOnExec)
|
||||
.Prop(_SC("OnAuth"), &Listener::GetOnAuth)
|
||||
.Prop(_SC("OnAudit"), &Listener::GetOnAudit)
|
||||
.Prop(_SC("OnPost"), &Listener::GetOnPost)
|
||||
.Prop(_SC("OnFail"), &Listener::GetOnFail)
|
||||
// Member Methods
|
||||
@ -1129,6 +1143,7 @@ void Register(HSQUIRRELVM vm)
|
||||
.FmtFunc(_SC("SetInfo"), &Listener::SetInfo)
|
||||
.CbFunc(_SC("BindExec"), &Listener::SetOnExec)
|
||||
.CbFunc(_SC("BindAuth"), &Listener::SetOnAuth)
|
||||
.CbFunc(_SC("BindAudit"), &Listener::SetOnAudit)
|
||||
.CbFunc(_SC("BindPost"), &Listener::SetOnPost)
|
||||
.CbFunc(_SC("BindFail"), &Listener::SetOnFail)
|
||||
.Func(_SC("GetArgTag"), &Listener::GetArgTag)
|
||||
|
@ -1109,6 +1109,7 @@ public:
|
||||
node->m_Data.Release();
|
||||
node->m_OnExec.Release();
|
||||
node->m_OnAuth.Release();
|
||||
node->m_OnAudit.Release();
|
||||
node->m_OnPost.Release();
|
||||
node->m_OnFail.Release();
|
||||
}
|
||||
@ -1118,6 +1119,7 @@ public:
|
||||
node->m_Data.Release();
|
||||
node->m_OnExec.Release();
|
||||
node->m_OnAuth.Release();
|
||||
node->m_OnAudit.Release();
|
||||
node->m_OnPost.Release();
|
||||
node->m_OnFail.Release();
|
||||
}
|
||||
@ -1203,6 +1205,7 @@ public:
|
||||
, m_Info()
|
||||
, m_OnExec()
|
||||
, m_OnAuth()
|
||||
, m_OnAudit()
|
||||
, m_OnPost()
|
||||
, m_OnFail()
|
||||
, m_Authority(ConvTo< int32_t >::From(auth))
|
||||
@ -1274,6 +1277,7 @@ public:
|
||||
// Release callbacks
|
||||
m_OnExec.Release();
|
||||
m_OnAuth.Release();
|
||||
m_OnAudit.Release();
|
||||
m_OnPost.Release();
|
||||
m_OnFail.Release();
|
||||
// Is there an element behind us?
|
||||
@ -1744,6 +1748,22 @@ public:
|
||||
m_OnAuth = std::move(func);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the function that must be called when this command listener needs to validate invocation.
|
||||
*/
|
||||
Function & GetOnAudit()
|
||||
{
|
||||
return m_OnAudit;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the function that must be called when this command listener needs to validate invocation.
|
||||
*/
|
||||
void SetOnAudit(Function & func)
|
||||
{
|
||||
m_OnAudit = std::move(func);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the function that must be called when this command listener finished execution.
|
||||
*/
|
||||
@ -1890,23 +1910,23 @@ protected:
|
||||
typedef String ArgTags[SQMOD_MAX_CMD_ARGS];
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Execute the designated callback by passing the arguments in their specified order.
|
||||
* Execute the designated audit callback by passing the arguments in their specified order.
|
||||
*/
|
||||
SQInteger Execute(const Object & invoker, const Array & args)
|
||||
SQInteger Audit(const Object & invoker, const LightObj & args)
|
||||
{
|
||||
// Attempt to evaluate the specified executer knowing the manager did the validations
|
||||
SharedPtr< SQInteger > ret = m_OnExec.Evaluate< SQInteger, const Object &, const Array & >(invoker, args);
|
||||
SharedPtr< SQInteger > ret = m_OnAudit.Evaluate< SQInteger, const Object &, const LightObj & >(invoker, args);
|
||||
// See if the executer succeeded and return the result or default to failed
|
||||
return (!ret ? 0 : *ret);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Execute the designated callback by passing the arguments using an associative container.
|
||||
* Execute the designated callback by passing the arguments in their specified order.
|
||||
*/
|
||||
SQInteger Execute(const Object & invoker, const Table & args)
|
||||
SQInteger Execute(const Object & invoker, const LightObj & args)
|
||||
{
|
||||
// Attempt to evaluate the specified executer knowing the manager did the validations
|
||||
SharedPtr< SQInteger > ret = m_OnExec.Evaluate< SQInteger, const Object &, const Table & >(invoker, args);
|
||||
SharedPtr< SQInteger > ret = m_OnExec.Evaluate< SQInteger, const Object &, const LightObj & >(invoker, args);
|
||||
// See if the executer succeeded and return the result or default to failed
|
||||
return (!ret ? 0 : *ret);
|
||||
}
|
||||
@ -1930,8 +1950,8 @@ private:
|
||||
ArgTags m_ArgTags; // List of argument tags/names.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
uint8_t m_MinArgc; // Minimum number of arguments supported by this listener.
|
||||
uint8_t m_MaxArgc; // Maximum number of arguments supported by this listener.
|
||||
uint8_t m_MinArgc; // Minimum number of arguments supported by this listener.
|
||||
uint8_t m_MaxArgc; // Maximum number of arguments supported by this listener.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
String m_Spec; // String used to generate the argument type specification list.
|
||||
@ -1941,11 +1961,12 @@ private:
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Function m_OnExec; // Function to call when the command is executed.
|
||||
Function m_OnAuth; // Function to call when the invoker must be authenticated.
|
||||
Function m_OnAudit; // Function to call when the parameters must be validated.
|
||||
Function m_OnPost; // Function to call after the command was successfully executed.
|
||||
Function m_OnFail; // Function to call after the command execution failed.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
int32_t m_Authority; // Built-in authority level required to execute this command.
|
||||
int32_t m_Authority; // Built-in authority level required to execute this command.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
bool m_Protected; // Whether explicit authentication of the invoker is required.
|
||||
|
Loading…
Reference in New Issue
Block a user