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

Implement the user tags feature in tasks.

This commit is contained in:
Sandu Liviu Catalin 2016-11-17 16:02:00 +02:00
parent 2e0b7b6c7f
commit ff8df39a13
2 changed files with 100 additions and 4 deletions

View File

@ -157,14 +157,16 @@ void Tasks::Register(HSQUIRRELVM vm)
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &Task::ToString)
// Properties
.Prop(_SC("Inst"), &Task::GetInst)
.Prop(_SC("Tag"), &Task::GetTag, &Task::SetTag)
.Prop(_SC("Entity"), &Task::GetInst)
.Prop(_SC("Func"), &Task::GetFunc, &Task::SetFunc)
.Prop(_SC("Data"), &Task::GetData, &Task::SetData)
.Prop(_SC("Interval"), &Task::GetInterval, &Task::SetInterval)
.Prop(_SC("Iterations"), &Task::GetIterations, &Task::SetIterations)
.Prop(_SC("Arguments"), &Task::GetArguments)
.Prop(_SC("Entity"), &Task::GetInst)
.Prop(_SC("Inst"), &Task::GetInst)
// Member Methods
.FmtFunc(_SC("SetTag"), &Task::SetTag)
.Func(_SC("Terminate"), &Task::Terminate)
.Func(_SC("GetArgument"), &Task::GetArgument)
);
@ -323,8 +325,10 @@ SQInteger Tasks::Create(Int32 id, Int32 type, HSQUIRRELVM vm)
s_Intervals[slot] = intrv;
// Increase the number of used slots
++s_Used;
// Specify that this function doesn't return anything
return 0;
// Push the tag instance on the stack
sq_pushobject(vm, task.mSelf);
// Specify that this function returns a value
return 1;
}
// ------------------------------------------------------------------------------------------------
@ -451,6 +455,23 @@ SQInteger Tasks::Exists(Int32 id, Int32 type, HSQUIRRELVM vm)
return 1;
}
// ------------------------------------------------------------------------------------------------
const Tasks::Task & Tasks::FindByTag(Int32 id, Int32 type, const StackStrF & tag)
{
// Attempt to find the requested task
for (const auto & t : s_Tasks)
{
if (t.mEntity == id && t.mType == type && t.mTag.compare(tag.mPtr) == 0)
{
return t; // Return this task instance
}
}
// Unable to find such task
STHROWF("Unable to find a task with tag (%s)", tag.mPtr);
// Should not reach this point but if it did, we have to return something
return s_Tasks[SQMOD_MAX_TASKS]; // Intentional Buffer overflow!
}
// ------------------------------------------------------------------------------------------------
void Tasks::Cleanup(Int32 id, Int32 type)
{

View File

@ -31,6 +31,7 @@ private:
{
// ----------------------------------------------------------------------------------------
SQHash mHash; // The hash of the referenced function object.
String mTag; // An arbitrary string which represents the tag.
LightObj mSelf; // A reference to `this`as a script object.
LightObj mFunc; // A reference to the managed function object.
LightObj mInst; // A reference to the associated entity object.
@ -47,6 +48,7 @@ private:
*/
Task()
: mHash(0)
, mTag()
, mSelf()
, mFunc()
, mInst()
@ -136,6 +138,22 @@ private:
*/
Interval Execute();
/* ----------------------------------------------------------------------------------------
* Retrieve the associated user tag.
*/
const String & GetTag() const
{
return mTag;
}
/* ----------------------------------------------------------------------------------------
* Modify the associated user tag.
*/
void SetTag(const StackStrF & tag)
{
mTag.assign(tag.mPtr, ClampMin(tag.mLen, 0));
}
/* ----------------------------------------------------------------------------------------
* Retrieve the instance to entity instance.
*/
@ -339,6 +357,11 @@ protected:
*/
static SQInteger Exists(Int32 id, Int32 type, HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Cleanup all tasks associated with the specified entity.
*/
static const Task & FindByTag(Int32 id, Int32 type, const StackStrF & tag);
public:
/* --------------------------------------------------------------------------------------------
@ -429,6 +452,58 @@ public:
// Forward the call and return the result
return Exists(inst->GetID(), Type, vm);
}
/* --------------------------------------------------------------------------------------------
* Forwards calls to find tasks.
*/
template < typename Entity, Int32 Type > static SQInteger FindTask(HSQUIRRELVM vm)
{
// Was the tag string specified?
if (sq_gettop(vm) <= 1)
{
return sq_throwerror(vm, "Missing tag string");
}
// The entity instance
const Entity * inst = nullptr;
// Attempt to extract the instance
try
{
// Fetch the instance from the stack
inst = Var< const Entity * >(vm, 1).value;
// Do we have a valid instance?
if (!inst)
{
STHROWF("Invalid entity instance");
}
// Validate the actual entity instance
inst->Validate();
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.what());
}
// Attempt to generate the string value
const StackStrF tag(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(tag.mRes))
{
return tag.mRes; // Propagate the error!
}
// Attempt to find the specified task
try
{
// Perform the search
const Task & task = FindByTag(inst->GetID(), Type, tag);
// Now push the instance on the stack
sq_pushobject(vm, task.mSelf.mObj);
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.what());
}
// Specify that this function returns a value
return 1;
}
};
} // Namespace:: SqMod