2016-11-16 23:23:59 +01:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-01-30 07:51:39 +01:00
|
|
|
#include "Core/Tasks.hpp"
|
2016-11-16 23:23:59 +01:00
|
|
|
#include "Core.hpp"
|
|
|
|
#include "Library/Chrono.hpp"
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#include <cstring>
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
namespace SqMod {
|
|
|
|
|
2016-11-17 10:27:07 +01:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-01-30 07:51:39 +01:00
|
|
|
SQMOD_DECL_TYPENAME(Typename, _SC("SqTask"))
|
2016-11-17 10:27:07 +01:00
|
|
|
|
2016-11-16 23:23:59 +01:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Tasks::Time Tasks::s_Last = 0;
|
|
|
|
Tasks::Time Tasks::s_Prev = 0;
|
|
|
|
Tasks::Interval Tasks::s_Intervals[SQMOD_MAX_TASKS];
|
|
|
|
Tasks::Task Tasks::s_Tasks[SQMOD_MAX_TASKS];
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-01-30 07:51:39 +01:00
|
|
|
void Tasks::Task::Init(HSQOBJECT & func, HSQOBJECT & inst, Interval intrv, Iterator itr, int32_t id, int32_t type)
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
|
|
|
// Initialize the callback hash
|
|
|
|
mHash = 0;
|
|
|
|
// Initialize the callback objects
|
2016-11-17 10:27:07 +01:00
|
|
|
mFunc = LightObj(func);
|
|
|
|
mInst = LightObj(inst);
|
2016-11-16 23:23:59 +01:00
|
|
|
// Initialize the task options
|
|
|
|
mIterations = itr;
|
|
|
|
mInterval = intrv;
|
|
|
|
// Initialize the entity information
|
2021-01-30 07:51:39 +01:00
|
|
|
mEntity = ConvTo< int16_t >::From(id);
|
|
|
|
mType = ConvTo< uint8_t >::From(type);
|
2016-11-16 23:23:59 +01:00
|
|
|
// Grab the virtual machine once
|
2020-04-27 12:10:54 +02:00
|
|
|
HSQUIRRELVM vm = SqVM();
|
2016-11-16 23:23:59 +01:00
|
|
|
// Remember the current stack size
|
|
|
|
const StackGuard sg(vm);
|
|
|
|
// Is there a valid function?
|
2016-11-17 10:27:07 +01:00
|
|
|
if (!mFunc.IsNull())
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
|
|
|
// Push the callback on the stack
|
|
|
|
sq_pushobject(vm, mFunc);
|
|
|
|
// Grab the hash of the callback object
|
|
|
|
mHash = sq_gethash(vm, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void Tasks::Task::Release()
|
|
|
|
{
|
|
|
|
mHash = 0;
|
2016-11-17 19:04:32 +01:00
|
|
|
mTag.clear();
|
2016-11-17 10:27:07 +01:00
|
|
|
mFunc.Release();
|
|
|
|
mInst.Release();
|
2016-11-17 11:29:58 +01:00
|
|
|
mData.Release();
|
2016-11-16 23:23:59 +01:00
|
|
|
mIterations = 0;
|
|
|
|
mInterval = 0;
|
|
|
|
mEntity = -1;
|
2020-03-22 05:53:04 +01:00
|
|
|
mType = 0;
|
2016-11-16 23:23:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
Tasks::Interval Tasks::Task::Execute()
|
|
|
|
{
|
|
|
|
// Are we even a valid task?
|
|
|
|
if (INVALID_ENTITY(mEntity))
|
|
|
|
{
|
|
|
|
return 0; // Dunno how we got here but it ends now
|
|
|
|
}
|
|
|
|
// Grab the virtual machine once
|
2020-04-27 12:10:54 +02:00
|
|
|
HSQUIRRELVM vm = SqVM();
|
2016-11-16 23:23:59 +01:00
|
|
|
// Push the function on the stack
|
|
|
|
sq_pushobject(vm, mFunc);
|
|
|
|
// Push the environment on the stack
|
2016-11-17 10:27:07 +01:00
|
|
|
sq_pushobject(vm, mSelf);
|
2016-11-16 23:23:59 +01:00
|
|
|
// Push function parameters, if any
|
2021-01-30 07:51:39 +01:00
|
|
|
for (uint32_t n = 0; n < mArgc; ++n)
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
|
|
|
sq_pushobject(vm, mArgv[n].mObj);
|
|
|
|
}
|
|
|
|
// Make the function call and store the result
|
2020-03-22 05:53:04 +01:00
|
|
|
const SQRESULT res = sq_call(vm, mArgc + 1, static_cast< SQBool >(false), static_cast< SQBool >(ErrorHandling::IsEnabled()));
|
2018-07-05 20:01:08 +02:00
|
|
|
// Pop the callback object from the stack
|
|
|
|
sq_pop(vm, 1);
|
2016-11-16 23:23:59 +01:00
|
|
|
// Validate the result
|
|
|
|
if (SQ_FAILED(res))
|
|
|
|
{
|
2016-11-17 22:09:35 +01:00
|
|
|
Terminate(); // Destroy ourself on error
|
2016-11-16 23:23:59 +01:00
|
|
|
}
|
|
|
|
// Decrease the number of iterations if necessary
|
|
|
|
if (mIterations && (--mIterations) == 0)
|
|
|
|
{
|
2016-11-17 22:09:35 +01:00
|
|
|
Terminate(); // This routine reached the end of it's life
|
2016-11-16 23:23:59 +01:00
|
|
|
}
|
|
|
|
// Return the current interval
|
|
|
|
return mInterval;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void Tasks::Process()
|
|
|
|
{
|
|
|
|
// Is this the first call?
|
|
|
|
if (s_Last == 0)
|
|
|
|
{
|
|
|
|
s_Last = Chrono::GetCurrentSysTime();
|
|
|
|
// We'll do it text time
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Backup the last known time-stamp
|
|
|
|
s_Prev = s_Last;
|
|
|
|
// Get the current time-stamp
|
|
|
|
s_Last = Chrono::GetCurrentSysTime();
|
|
|
|
// Calculate the elapsed time
|
2021-01-30 07:51:39 +01:00
|
|
|
const auto delta = int32_t((s_Last - s_Prev) / 1000L);
|
2016-11-16 23:23:59 +01:00
|
|
|
// Process all active tasks
|
|
|
|
for (Interval * itr = s_Intervals; itr != (s_Intervals + SQMOD_MAX_TASKS); ++itr)
|
|
|
|
{
|
|
|
|
// Is this task valid?
|
|
|
|
if (*itr)
|
|
|
|
{
|
|
|
|
// Decrease the elapsed time
|
|
|
|
(*itr) -= delta;
|
|
|
|
// Have we completed the routine interval?
|
|
|
|
if ((*itr) <= 0)
|
|
|
|
{
|
2016-11-17 22:09:35 +01:00
|
|
|
// Execute and reset the elapsed time
|
2016-11-16 23:23:59 +01:00
|
|
|
(*itr) = s_Tasks[itr - s_Intervals].Execute();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void Tasks::Initialize()
|
|
|
|
{
|
|
|
|
std::memset(s_Intervals, 0, sizeof(s_Intervals));
|
2016-11-17 10:27:07 +01:00
|
|
|
// Transform all task instances to script objects
|
|
|
|
for (auto & t : s_Tasks)
|
|
|
|
{
|
|
|
|
// This is fine because they'll always outlive the virtual machine
|
|
|
|
t.mSelf = LightObj(&t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void Tasks::Register(HSQUIRRELVM vm)
|
|
|
|
{
|
|
|
|
RootTable(vm).Bind(Typename::Str,
|
2016-11-17 10:47:07 +01:00
|
|
|
Class< Task, NoDestructor< Task > >(vm, Typename::Str)
|
2016-11-17 10:27:07 +01:00
|
|
|
// Meta-methods
|
|
|
|
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
|
2016-11-17 11:29:58 +01:00
|
|
|
.Func(_SC("_tostring"), &Task::ToString)
|
|
|
|
// Properties
|
2016-11-17 15:02:00 +01:00
|
|
|
.Prop(_SC("Tag"), &Task::GetTag, &Task::SetTag)
|
|
|
|
.Prop(_SC("Entity"), &Task::GetInst)
|
2016-11-17 11:29:58 +01:00
|
|
|
.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)
|
2016-11-17 15:02:00 +01:00
|
|
|
.Prop(_SC("Inst"), &Task::GetInst)
|
2016-11-17 11:29:58 +01:00
|
|
|
// Member Methods
|
2016-11-17 15:02:00 +01:00
|
|
|
.FmtFunc(_SC("SetTag"), &Task::SetTag)
|
2016-11-17 11:29:58 +01:00
|
|
|
.Func(_SC("Terminate"), &Task::Terminate)
|
|
|
|
.Func(_SC("GetArgument"), &Task::GetArgument)
|
2016-11-17 18:59:47 +01:00
|
|
|
// Static functions
|
|
|
|
.StaticFunc(_SC("Used"), &Tasks::GetUsed)
|
2016-11-17 10:27:07 +01:00
|
|
|
);
|
2016-11-16 23:23:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
void Tasks::Deinitialize()
|
|
|
|
{
|
|
|
|
// Release any script resources that the tasks might store
|
|
|
|
for (auto & t : s_Tasks)
|
|
|
|
{
|
2016-11-17 11:29:58 +01:00
|
|
|
t.Terminate();
|
2016-11-17 10:27:07 +01:00
|
|
|
t.mSelf.Release();
|
2016-11-16 23:23:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-01-30 07:51:39 +01:00
|
|
|
LightObj & Tasks::FindEntity(int32_t id, int32_t type)
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
|
|
|
switch (type)
|
|
|
|
{
|
|
|
|
case ENT_BLIP: return Core::Get().GetBlip(id).mObj;
|
|
|
|
case ENT_CHECKPOINT: return Core::Get().GetCheckpoint(id).mObj;
|
2021-01-30 07:51:39 +01:00
|
|
|
case ENT_KEYBIND: return Core::Get().GetKeyBind(id).mObj;
|
2020-04-17 16:42:09 +02:00
|
|
|
case ENT_OBJECT: return Core::Get().GetObj(id).mObj;
|
2016-11-16 23:23:59 +01:00
|
|
|
case ENT_PICKUP: return Core::Get().GetPickup(id).mObj;
|
|
|
|
case ENT_PLAYER: return Core::Get().GetPlayer(id).mObj;
|
|
|
|
case ENT_VEHICLE: return Core::Get().GetVehicle(id).mObj;
|
2017-02-21 20:24:59 +01:00
|
|
|
default: return NullLightObj();
|
2016-11-16 23:23:59 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
SQInteger Tasks::FindUnused()
|
|
|
|
{
|
|
|
|
for (const auto & t : s_Tasks)
|
|
|
|
{
|
|
|
|
if (INVALID_ENTITY(t.mEntity))
|
|
|
|
{
|
|
|
|
return (&t - s_Tasks); // Return the index of this element
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// No available slot
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-01-30 07:51:39 +01:00
|
|
|
SQInteger Tasks::Create(int32_t id, int32_t type, HSQUIRRELVM vm)
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
2016-11-17 18:59:47 +01:00
|
|
|
// Locate the identifier of a free slot
|
|
|
|
const SQInteger slot = FindUnused();
|
2016-11-16 23:23:59 +01:00
|
|
|
// See if we have where to store this task
|
2016-11-17 18:59:47 +01:00
|
|
|
if (slot < 0)
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
|
|
|
return sq_throwerror(vm, "Reached the maximum number of tasks");
|
|
|
|
}
|
|
|
|
// Grab the top of the stack
|
|
|
|
const SQInteger top = sq_gettop(vm);
|
|
|
|
// See if too many arguments were specified
|
2016-11-17 11:59:29 +01:00
|
|
|
if (top > 12) /* 4 base + 8 parameters = 12 */
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
2016-11-17 22:09:35 +01:00
|
|
|
return sq_throwerror(vm, "Too many parameters specified");
|
2016-11-16 23:23:59 +01:00
|
|
|
}
|
2016-11-17 22:09:35 +01:00
|
|
|
// Was there was a callback specified?
|
2016-11-16 23:23:59 +01:00
|
|
|
else if (top <= 1)
|
|
|
|
{
|
|
|
|
return sq_throwerror(vm, "Missing task callback");
|
|
|
|
}
|
|
|
|
// Validate the callback type
|
2016-11-17 10:27:07 +01:00
|
|
|
else if (sq_gettype(vm, 2) != OT_CLOSURE && sq_gettype(vm, 2) != OT_NATIVECLOSURE)
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
|
|
|
return sq_throwerror(vm, "Invalid callback type");
|
|
|
|
}
|
2016-11-17 10:27:07 +01:00
|
|
|
// Prepare an entity instance object
|
|
|
|
HSQOBJECT inst;
|
|
|
|
// Attempt to retrieve the entity instance
|
|
|
|
try
|
|
|
|
{
|
2020-04-17 16:42:09 +02:00
|
|
|
inst = FindEntity(id, type).GetObj();
|
2016-11-17 10:27:07 +01:00
|
|
|
}
|
|
|
|
catch (const std::exception & e)
|
|
|
|
{
|
|
|
|
return sq_throwerror(vm, e.what());
|
|
|
|
}
|
|
|
|
// Prepare the function object
|
|
|
|
HSQOBJECT func;
|
2016-11-16 23:23:59 +01:00
|
|
|
// Fetch the specified callback
|
2016-11-17 10:27:07 +01:00
|
|
|
SQRESULT res = sq_getstackobj(vm, 2, &func);
|
2016-11-16 23:23:59 +01:00
|
|
|
// Validate the result
|
|
|
|
if (SQ_FAILED(res))
|
|
|
|
{
|
|
|
|
return res; // Propagate the error
|
|
|
|
}
|
|
|
|
|
|
|
|
// The number of iterations and interval to execute the task
|
|
|
|
SQInteger intrv = 0, itr = 0;
|
|
|
|
// Was there an interval specified?
|
|
|
|
if (top > 2)
|
|
|
|
{
|
|
|
|
// Grab the interval from the stack
|
|
|
|
res = sq_getinteger(vm, 3, &intrv);
|
|
|
|
// Validate the result
|
|
|
|
if (SQ_FAILED(res))
|
|
|
|
{
|
|
|
|
return res; // Propagate the error
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Was there a number of iterations specified?
|
|
|
|
if (top > 3)
|
|
|
|
{
|
|
|
|
// Grab the iterations from the stack
|
|
|
|
res = sq_getinteger(vm, 4, &itr);
|
|
|
|
// Validate the result
|
|
|
|
if (SQ_FAILED(res))
|
|
|
|
{
|
|
|
|
return res; // Propagate the error
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// At this point we can grab a reference to our slot
|
|
|
|
Task & task = s_Tasks[slot];
|
|
|
|
// Were there any arguments specified?
|
|
|
|
if (top > 4)
|
|
|
|
{
|
|
|
|
// Grab a pointer to the arguments array
|
|
|
|
Argument * args = task.mArgv;
|
|
|
|
// Reset the argument counter
|
|
|
|
task.mArgc = 0;
|
|
|
|
// Grab the specified arguments from the stack
|
|
|
|
for (SQInteger i = 5; i <= top; ++i)
|
|
|
|
{
|
|
|
|
res = sq_getstackobj(vm, i, &(args[task.mArgc].mObj));
|
|
|
|
// Validate the result
|
|
|
|
if (SQ_FAILED(res))
|
|
|
|
{
|
|
|
|
// Clear previous arguments
|
|
|
|
task.Clear();
|
|
|
|
// Propagate the error
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
// Keep a strong reference to the argument
|
|
|
|
sq_addref(vm, &(args[task.mArgc].mObj));
|
|
|
|
// Increase the argument counter
|
|
|
|
++task.mArgc;
|
|
|
|
}
|
|
|
|
}
|
2016-11-17 18:59:47 +01:00
|
|
|
|
2016-11-16 23:23:59 +01:00
|
|
|
// Alright, at this point we can initialize the slot
|
2020-03-22 05:53:04 +01:00
|
|
|
task.Init(func, inst, intrv, static_cast< Iterator >(itr), id, type);
|
2016-11-17 22:09:35 +01:00
|
|
|
// Now initialize the timer
|
2016-11-16 23:23:59 +01:00
|
|
|
s_Intervals[slot] = intrv;
|
2016-11-17 15:02:00 +01:00
|
|
|
// Push the tag instance on the stack
|
|
|
|
sq_pushobject(vm, task.mSelf);
|
|
|
|
// Specify that this function returns a value
|
|
|
|
return 1;
|
2016-11-16 23:23:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-01-30 07:51:39 +01:00
|
|
|
SQInteger Tasks::Find(int32_t id, int32_t type, SQInteger & pos, HSQUIRRELVM vm)
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
|
|
|
// Grab the top of the stack
|
|
|
|
const SQInteger top = sq_gettop(vm);
|
2022-03-02 17:57:11 +01:00
|
|
|
// Was there a callback or tag specified?
|
2016-11-16 23:23:59 +01:00
|
|
|
if (top <= 1)
|
|
|
|
{
|
2022-03-02 17:57:11 +01:00
|
|
|
return sq_throwerror(vm, "Missing task callback or tag");
|
2016-11-16 23:23:59 +01:00
|
|
|
}
|
|
|
|
SQRESULT res = SQ_OK;
|
2022-03-02 17:57:11 +01:00
|
|
|
// Fetch the task identifier type
|
|
|
|
const SQObjectType ot = sq_gettype(vm, 2);
|
|
|
|
// Are we looking for a task with a specific tag?
|
|
|
|
if (ot == OT_STRING)
|
|
|
|
{
|
|
|
|
// Attempt to retrieve the value from the stack as a string
|
|
|
|
StackStrF tag(vm, 2);
|
|
|
|
// Have we failed to retrieve the string?
|
|
|
|
if (SQ_FAILED(tag.Proc(true)))
|
|
|
|
{
|
|
|
|
return tag.mRes; // Propagate the error!
|
|
|
|
}
|
|
|
|
// Attempt to find the requested task
|
|
|
|
for (const auto & t : s_Tasks)
|
|
|
|
{
|
|
|
|
if (t.mEntity == id && t.mType == type && t.mTag.compare(0, String::npos, tag.mPtr) == 0)
|
|
|
|
{
|
|
|
|
pos = static_cast< SQInteger >(&t - s_Tasks); // Store the index of this element
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Validate the callback type
|
|
|
|
else if (ot != OT_CLOSURE && ot != OT_NATIVECLOSURE)
|
|
|
|
{
|
|
|
|
return sq_throwerror(vm, "Invalid callback type");
|
|
|
|
}
|
2016-11-16 23:23:59 +01:00
|
|
|
// Should we include the iterations in the criteria?
|
2022-03-02 17:57:11 +01:00
|
|
|
else if (top > 3)
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
|
|
|
SQInteger intrv = 0;
|
|
|
|
// Grab the interval from the stack
|
|
|
|
res = sq_getinteger(vm, 3, &intrv);
|
|
|
|
// Validate the result
|
|
|
|
if (SQ_FAILED(res))
|
|
|
|
{
|
|
|
|
return res; // Propagate the error
|
|
|
|
}
|
2022-03-02 17:57:11 +01:00
|
|
|
// Grab the hash of the callback object
|
|
|
|
const SQHash chash = sq_gethash(vm, 2);
|
2016-11-16 23:23:59 +01:00
|
|
|
// Attempt to find the requested task
|
|
|
|
for (const auto & t : s_Tasks)
|
|
|
|
{
|
|
|
|
if (t.mHash == chash && t.mEntity == id && t.mType == type && t.mInterval == intrv)
|
|
|
|
{
|
|
|
|
pos = static_cast< SQInteger >(&t - s_Tasks); // Store the index of this element
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Should we include the interval in the criteria?
|
|
|
|
else if (top > 2)
|
|
|
|
{
|
|
|
|
SQInteger intrv = 0, sqitr = 0;
|
|
|
|
// Grab the interval from the stack
|
|
|
|
res = sq_getinteger(vm, 3, &intrv);
|
|
|
|
// Validate the result
|
|
|
|
if (SQ_FAILED(res))
|
|
|
|
{
|
|
|
|
return res; // Propagate the error
|
|
|
|
}
|
|
|
|
// Grab the iterations from the stack
|
|
|
|
res = sq_getinteger(vm, 4, &sqitr);
|
|
|
|
// Validate the result
|
|
|
|
if (SQ_FAILED(res))
|
|
|
|
{
|
|
|
|
return res; // Propagate the error
|
|
|
|
}
|
2022-03-02 17:57:11 +01:00
|
|
|
// Grab the hash of the callback object
|
|
|
|
const SQHash chash = sq_gethash(vm, 2);
|
2016-11-16 23:23:59 +01:00
|
|
|
// Cast iterations to the right type
|
|
|
|
const Iterator itr = ConvTo< Iterator >::From(sqitr);
|
|
|
|
// Attempt to find the requested task
|
|
|
|
for (const auto & t : s_Tasks)
|
|
|
|
{
|
|
|
|
if (t.mHash == chash && t.mEntity == id && t.mType == type && t.mInterval == intrv && t.mIterations == itr)
|
|
|
|
{
|
|
|
|
pos = static_cast< SQInteger >(&t - s_Tasks); // Store the index of this element
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-03-02 17:57:11 +01:00
|
|
|
// Grab the hash of the callback object
|
|
|
|
const SQHash chash = sq_gethash(vm, 2);
|
2016-11-16 23:23:59 +01:00
|
|
|
// Attempt to find the requested task
|
|
|
|
for (const auto & t : s_Tasks)
|
|
|
|
{
|
|
|
|
if (t.mHash == chash && t.mEntity == id && t.mType == type)
|
|
|
|
{
|
|
|
|
pos = static_cast< SQInteger >(&t - s_Tasks); // Store the index of this element
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// We could not find such task
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-01-30 07:51:39 +01:00
|
|
|
SQInteger Tasks::Remove(int32_t id, int32_t type, HSQUIRRELVM vm)
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
|
|
|
// Default to not found
|
|
|
|
SQInteger pos = -1;
|
|
|
|
// Perform a search
|
|
|
|
SQRESULT res = Find(id, type, pos, vm);
|
|
|
|
// Did the search failed?
|
|
|
|
if (SQ_FAILED(res))
|
|
|
|
{
|
|
|
|
return res; // Propagate the error
|
|
|
|
}
|
|
|
|
// Did we find anything?
|
|
|
|
else if (pos < 0)
|
|
|
|
{
|
2022-03-02 17:57:11 +01:00
|
|
|
sq_pushbool(vm, SQFalse); // Unable to locate such task
|
2016-11-16 23:23:59 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Release task resources
|
2016-11-17 11:29:58 +01:00
|
|
|
s_Tasks[pos].Terminate();
|
2016-11-16 23:23:59 +01:00
|
|
|
// Reset the timer
|
|
|
|
s_Intervals[pos] = 0;
|
2022-03-02 17:57:11 +01:00
|
|
|
// A task was successfully removed
|
|
|
|
sq_pushbool(vm, SQTrue);
|
2016-11-16 23:23:59 +01:00
|
|
|
}
|
2022-03-02 17:57:11 +01:00
|
|
|
// Specify that we return a value
|
|
|
|
return 1;
|
2016-11-16 23:23:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-01-30 07:51:39 +01:00
|
|
|
SQInteger Tasks::Exists(int32_t id, int32_t type, HSQUIRRELVM vm)
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
|
|
|
// Default to not found
|
|
|
|
SQInteger pos = -1;
|
|
|
|
// Perform a search
|
|
|
|
SQRESULT res = Find(id, type, pos, vm);
|
|
|
|
// Did the search failed?
|
|
|
|
if (SQ_FAILED(res))
|
|
|
|
{
|
|
|
|
return res; // Propagate the error
|
|
|
|
}
|
|
|
|
// Push a boolean on whether this task was found
|
2020-03-22 05:53:04 +01:00
|
|
|
sq_pushbool(vm, static_cast< SQBool >(pos >= 0));
|
2016-11-16 23:23:59 +01:00
|
|
|
// Specify that we're returning a value
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2016-11-17 15:02:00 +01:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-01-30 07:51:39 +01:00
|
|
|
const Tasks::Task & Tasks::FindByTag(int32_t id, int32_t type, StackStrF & tag)
|
2016-11-17 15:02:00 +01:00
|
|
|
{
|
|
|
|
// Attempt to find the requested task
|
|
|
|
for (const auto & t : s_Tasks)
|
|
|
|
{
|
2020-03-22 05:53:04 +01:00
|
|
|
if (t.mEntity == id && t.mType == type && t.mTag == tag.mPtr)
|
2016-11-17 15:02:00 +01:00
|
|
|
{
|
|
|
|
return t; // Return this task instance
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Unable to find such task
|
2021-02-03 16:50:39 +01:00
|
|
|
STHROWF("Unable to find a task with tag ({})", tag.mPtr);
|
2016-11-17 15:02:00 +01:00
|
|
|
// Should not reach this point but if it did, we have to return something
|
2021-01-30 07:51:39 +01:00
|
|
|
SQ_UNREACHABLE
|
2016-11-17 15:02:00 +01:00
|
|
|
}
|
|
|
|
|
2016-11-16 23:23:59 +01:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
2021-01-30 07:51:39 +01:00
|
|
|
void Tasks::Cleanup(int32_t id, int32_t type)
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
|
|
|
for (auto & t : s_Tasks)
|
|
|
|
{
|
|
|
|
if (t.mEntity == id && t.mType == type)
|
|
|
|
{
|
2016-11-17 11:29:58 +01:00
|
|
|
t.Terminate();
|
2016-11-16 23:23:59 +01:00
|
|
|
// Also disable the timer
|
|
|
|
s_Intervals[&t - s_Tasks] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
|
|
* Forward the call to process tasks.
|
|
|
|
*/
|
|
|
|
void ProcessTasks()
|
|
|
|
{
|
|
|
|
Tasks::Process();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
|
|
* Forward the call to initialize tasks.
|
|
|
|
*/
|
|
|
|
void InitializeTasks()
|
|
|
|
{
|
|
|
|
Tasks::Initialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
|
|
* Forward the call to terminate tasks.
|
|
|
|
*/
|
|
|
|
void TerminateTasks()
|
|
|
|
{
|
|
|
|
Tasks::Deinitialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
|
|
* Forward the call to cleanup certain tasks.
|
|
|
|
*/
|
2021-01-30 07:51:39 +01:00
|
|
|
void CleanupTasks(int32_t id, int32_t type)
|
2016-11-16 23:23:59 +01:00
|
|
|
{
|
|
|
|
Tasks::Cleanup(id, type);
|
|
|
|
}
|
|
|
|
|
2021-01-30 07:51:39 +01:00
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
|
|
* Forward the call to register tasks.
|
|
|
|
*/
|
|
|
|
void Register_Tasks(HSQUIRRELVM vm)
|
|
|
|
{
|
|
|
|
Tasks::Register(vm);
|
|
|
|
}
|
|
|
|
|
2016-11-16 23:23:59 +01:00
|
|
|
} // Namespace:: SqMod
|