mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 00:37:15 +01:00
Catch exceptions during server callbacks.
Allow routines to safely terminate routines during execution. Various other fixes and improvements.
This commit is contained in:
parent
d58099461a
commit
d2f3da1747
@ -51,6 +51,15 @@ template <> struct NumLimit< long double > { static const long double Min, Max;
|
||||
*/
|
||||
struct StackGuard
|
||||
{
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor.
|
||||
*/
|
||||
StackGuard()
|
||||
: m_Top(sq_gettop(DefaultVM::Get())), m_VM(DefaultVM::Get())
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
|
540
source/Main.cpp
540
source/Main.cpp
@ -109,351 +109,617 @@ SQMOD_API_EXPORT unsigned int VcmpPluginInit(PluginFuncs * funcs, PluginCallback
|
||||
return SQMOD_SUCCESS;
|
||||
}
|
||||
|
||||
#define SQMOD_CATCH_EVENT_EXCEPTION(ev) /*
|
||||
*/ catch (const Sqrat::Exception & e) /*
|
||||
*/ { /*
|
||||
*/ LogErr("Squirrel exception caught during (" #ev ") event"); /*
|
||||
*/ LogInf("Message: %s", e.Message().c_str()); /*
|
||||
*/ } /*
|
||||
*/ catch (const std::exception & e) /*
|
||||
*/ { /*
|
||||
*/ LogErr("Program exception caught during (" #ev ") event"); /*
|
||||
*/ LogInf("Message: %s", e.what()); /*
|
||||
*/ } /*
|
||||
*/ catch (...) /*
|
||||
*/ { /*
|
||||
*/ LogErr("Unknown exception caught during (" #ev ") event"); /*
|
||||
*/ } /*
|
||||
*/
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
static int VC_InitServer(void)
|
||||
{
|
||||
// Don't even try to initialize if there's no core instance
|
||||
if (!_Core)
|
||||
{
|
||||
return SQMOD_FAILURE;
|
||||
|
||||
}
|
||||
// Mark the initialization as successful by default
|
||||
_Core->SetState(1);
|
||||
// Obtain the API version as a string
|
||||
String apiver(ToStrF("%d", SQMOD_API_VER));
|
||||
// Signal outside plugins to do fetch our proxies
|
||||
_Func->SendCustomCommand(0xDABBAD00, apiver.c_str());
|
||||
// Attempt to load the module core
|
||||
if (_Core->Load())
|
||||
_Core->EmitServerStartup();
|
||||
else
|
||||
LogFtl("Unable to load the plugin resources properly");
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
|
||||
// Obtain the API version as a string
|
||||
String apiver(ToStrF("%d", SQMOD_API_VER));
|
||||
// Signal outside plug-ins to do fetch our proxies
|
||||
_Func->SendCustomCommand(0xDABBAD00, apiver.c_str());
|
||||
// Attempt to load the module core
|
||||
if (_Core->Load())
|
||||
{
|
||||
_Core->EmitServerStartup();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFtl("Unable to load the plugin resources properly");
|
||||
}
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(InitServer)
|
||||
// Return the last known plug-in state
|
||||
return _Core->GetState();
|
||||
}
|
||||
|
||||
static void VC_ShutdownServer(void)
|
||||
{
|
||||
// Don't even try to de-initialize if there's no core instance
|
||||
if (!_Core)
|
||||
{
|
||||
return;
|
||||
|
||||
_Core->EmitServerShutdown();
|
||||
// Deallocate and release everything obtained at startup
|
||||
_Core->Terminate();
|
||||
// The server still triggers callbacks and we deallocated everything!
|
||||
UnbindCallbacks();
|
||||
// Destroy components
|
||||
DestroyComponents();
|
||||
}
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitServerShutdown();
|
||||
// Deallocate and release everything obtained at startup
|
||||
_Core->Terminate();
|
||||
// The server still triggers callbacks and we deallocated everything!
|
||||
UnbindCallbacks();
|
||||
// Destroy components
|
||||
DestroyComponents();
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(ShutdownServer)
|
||||
}
|
||||
|
||||
static void VC_Frame(float delta)
|
||||
{
|
||||
_Core->EmitServerFrame(delta);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitServerFrame(delta);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(Frame)
|
||||
}
|
||||
|
||||
static void VC_PlayerConnect(int player)
|
||||
{
|
||||
_Core->ConnectPlayer(player, SQMOD_CREATE_AUTOMATIC, NullObject());
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->ConnectPlayer(player, SQMOD_CREATE_AUTOMATIC, NullObject());
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerConnect)
|
||||
}
|
||||
|
||||
static void VC_PlayerDisconnect(int player, int reason)
|
||||
{
|
||||
_Core->DisconnectPlayer(player, reason, NullObject());
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->DisconnectPlayer(player, reason, NullObject());
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerDisconnect)
|
||||
}
|
||||
|
||||
static void VC_PlayerBeginTyping(int player)
|
||||
{
|
||||
_Core->EmitPlayerStartTyping(player);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerStartTyping(player);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerBeginTyping)
|
||||
}
|
||||
|
||||
static void VC_PlayerEndTyping(int player)
|
||||
{
|
||||
_Core->EmitPlayerStopTyping(player);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerStopTyping(player);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerEndTyping)
|
||||
}
|
||||
|
||||
static int VC_PlayerRequestClass(int player, int offset)
|
||||
{
|
||||
// Mark the initialization as successful by default
|
||||
_Core->SetState(SQMOD_SUCCESS);
|
||||
_Core->EmitPlayerRequestClass(player, offset);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerRequestClass(player, offset);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerEndTyping)
|
||||
// Return the last known plug-in state
|
||||
return _Core->GetState();
|
||||
}
|
||||
|
||||
static int VC_PlayerRequestSpawn(int player)
|
||||
{
|
||||
// Mark the initialization as successful by default
|
||||
_Core->SetState(SQMOD_SUCCESS);
|
||||
_Core->EmitPlayerRequestSpawn(player);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerRequestSpawn(player);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerRequestSpawn)
|
||||
// Return the last known plug-in state
|
||||
return _Core->GetState();
|
||||
}
|
||||
|
||||
static void VC_PlayerSpawn(int player)
|
||||
{
|
||||
_Core->EmitPlayerSpawn(player);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerSpawn(player);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerSpawn)
|
||||
}
|
||||
|
||||
static void VC_PlayerDeath(int player, int killer, int reason, int body_part)
|
||||
{
|
||||
if (_Func->IsPlayerConnected(killer))
|
||||
_Core->EmitPlayerKilled(player, killer, reason, body_part);
|
||||
else
|
||||
_Core->EmitPlayerWasted(player, reason);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
if (_Func->IsPlayerConnected(killer))
|
||||
{
|
||||
_Core->EmitPlayerKilled(player, killer, reason, body_part);
|
||||
}
|
||||
else
|
||||
{
|
||||
_Core->EmitPlayerWasted(player, reason);
|
||||
}
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerDeath)
|
||||
}
|
||||
|
||||
static void VC_PlayerUpdate(int player, int type)
|
||||
{
|
||||
_Core->EmitPlayerUpdate(player, type);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerUpdate(player, type);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerUpdate)
|
||||
}
|
||||
|
||||
static int VC_PlayerRequestEnter(int player, int vehicle, int slot)
|
||||
{
|
||||
// Mark the initialization as successful by default
|
||||
_Core->SetState(SQMOD_SUCCESS);
|
||||
_Core->EmitPlayerEmbarking(player, vehicle, slot);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerEmbarking(player, vehicle, slot);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerRequestEnter)
|
||||
// Return the last known plug-in state
|
||||
return _Core->GetState();
|
||||
}
|
||||
|
||||
static void VC_PlayerEnterVehicle(int player, int vehicle, int slot)
|
||||
{
|
||||
_Core->EmitPlayerEmbarked(player, vehicle, slot);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerEmbarked(player, vehicle, slot);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerEnterVehicle)
|
||||
}
|
||||
|
||||
static void VC_PlayerExitVehicle(int player, int vehicle)
|
||||
{
|
||||
_Core->EmitPlayerDisembark(player, vehicle);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerDisembark(player, vehicle);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerExitVehicle)
|
||||
}
|
||||
|
||||
static int VC_PickupClaimPicked(int pickup, int player)
|
||||
{
|
||||
// Mark the initialization as successful by default
|
||||
_Core->SetState(SQMOD_SUCCESS);
|
||||
_Core->EmitPickupClaimed(player, pickup);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPickupClaimed(player, pickup);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PickupClaimPicked)
|
||||
// Return the last known plug-in state
|
||||
return _Core->GetState();
|
||||
}
|
||||
|
||||
static void VC_PickupPickedUp(int pickup, int player)
|
||||
{
|
||||
_Core->EmitPickupCollected(player, pickup);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPickupCollected(player, pickup);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PickupPickedUp)
|
||||
}
|
||||
|
||||
static void VC_PickupRespawn(int pickup)
|
||||
{
|
||||
_Core->EmitPickupRespawn(pickup);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPickupRespawn(pickup);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PickupRespawn)
|
||||
}
|
||||
|
||||
static void VC_VehicleUpdate(int vehicle, int type)
|
||||
{
|
||||
_Core->EmitVehicleUpdate(vehicle, type);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitVehicleUpdate(vehicle, type);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(VehicleUpdate)
|
||||
}
|
||||
|
||||
static void VC_VehicleExplode(int vehicle)
|
||||
{
|
||||
_Core->EmitVehicleExplode(vehicle);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitVehicleExplode(vehicle);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(VehicleExplode)
|
||||
}
|
||||
|
||||
static void VC_VehicleRespawn(int vehicle)
|
||||
{
|
||||
_Core->EmitVehicleRespawn(vehicle);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitVehicleRespawn(vehicle);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(VehicleRespawn)
|
||||
}
|
||||
|
||||
static void VC_ObjectShot(int object, int player, int weapon)
|
||||
{
|
||||
_Core->EmitObjectShot(player, object, weapon);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitObjectShot(player, object, weapon);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(ObjectShot)
|
||||
}
|
||||
|
||||
static void VC_ObjectBump(int object, int player)
|
||||
{
|
||||
_Core->EmitObjectBump(player, object);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitObjectBump(player, object);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(ObjectBump)
|
||||
}
|
||||
|
||||
static int VC_PublicMessage(int player, const char * text)
|
||||
{
|
||||
// Mark the initialization as successful by default
|
||||
_Core->SetState(SQMOD_SUCCESS);
|
||||
_Core->EmitPlayerChat(player, text);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerChat(player, text);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PublicMessage)
|
||||
// Return the last known plug-in state
|
||||
return _Core->GetState();
|
||||
}
|
||||
|
||||
static int VC_CommandMessage(int player, const char * text)
|
||||
{
|
||||
// Mark the initialization as successful by default
|
||||
_Core->SetState(SQMOD_SUCCESS);
|
||||
_Core->EmitPlayerCommand(player, text);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerCommand(player, text);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(CommandMessage)
|
||||
// Return the last known plug-in state
|
||||
return _Core->GetState();
|
||||
}
|
||||
|
||||
static int VC_PrivateMessage(int player, int target, const char * text)
|
||||
{
|
||||
// Mark the initialization as successful by default
|
||||
_Core->SetState(SQMOD_SUCCESS);
|
||||
_Core->EmitPlayerMessage(player, target, text);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerMessage(player, target, text);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PrivateMessage)
|
||||
// Return the last known plug-in state
|
||||
return _Core->GetState();
|
||||
}
|
||||
|
||||
static int VC_InternalCommand(unsigned int type, const char * text)
|
||||
{
|
||||
// Mark the initialization as successful by default
|
||||
_Core->SetState(SQMOD_SUCCESS);
|
||||
_Core->EmitInternalCommand(type, text);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitInternalCommand(type, text);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(InternalCommand)
|
||||
// Return the last known plug-in state
|
||||
return _Core->GetState();
|
||||
}
|
||||
|
||||
static int VC_LoginAttempt(char * name, const char * passwd, const char * address)
|
||||
{
|
||||
// Mark the initialization as successful by default
|
||||
_Core->SetState(SQMOD_SUCCESS);
|
||||
_Core->EmitLoginAttempt(name, passwd, address);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitLoginAttempt(name, passwd, address);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(LoginAttempt)
|
||||
// Return the last known plug-in state
|
||||
return _Core->GetState();
|
||||
}
|
||||
|
||||
static void VC_EntityPool(int type, int id, unsigned int deleted)
|
||||
{
|
||||
_Core->EmitEntityPool(type, id, static_cast<bool>(deleted));
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitEntityPool(type, id, static_cast< bool >(deleted));
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(EntityPool)
|
||||
}
|
||||
|
||||
static void VC_KeyBindDown(int player, int bind)
|
||||
{
|
||||
_Core->EmitPlayerKeyPress(player, bind);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerKeyPress(player, bind);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(KeyBindDown)
|
||||
}
|
||||
|
||||
static void VC_KeyBindUp(int player, int bind)
|
||||
{
|
||||
_Core->EmitPlayerKeyRelease(player, bind);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerKeyRelease(player, bind);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(KeyBindUp)
|
||||
}
|
||||
|
||||
static void VC_PlayerAway(int player, unsigned int status)
|
||||
{
|
||||
_Core->EmitPlayerAway(player, static_cast<bool>(status));
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerAway(player, static_cast< bool >(status));
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerAway)
|
||||
}
|
||||
|
||||
static void VC_PlayerSpectate(int player, int target)
|
||||
{
|
||||
_Core->EmitPlayerSpectate(player, target);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerSpectate(player, target);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerSpectate)
|
||||
}
|
||||
|
||||
static void VC_PlayerCrashReport(int player, const char * report)
|
||||
{
|
||||
_Core->EmitPlayerCrashreport(player, report);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerCrashreport(player, report);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerCrashReport)
|
||||
}
|
||||
|
||||
static void VC_ServerPerformanceReport(int count, const char ** description, unsigned long long * millis)
|
||||
static void VC_ServerPerformanceReport(int /*count*/, const char ** /*description*/, unsigned long long * /*millis*/)
|
||||
{
|
||||
// Ignored for now...
|
||||
SQMOD_UNUSED_VAR(count);
|
||||
SQMOD_UNUSED_VAR(description);
|
||||
SQMOD_UNUSED_VAR(millis);
|
||||
}
|
||||
|
||||
static void VC_PlayerName(int player, const char * previous, const char * current)
|
||||
{
|
||||
_Core->EmitPlayerRename(player, previous, current);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerRename(player, previous, current);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerName)
|
||||
}
|
||||
|
||||
static void VC_PlayerState(int player, int previous, int current)
|
||||
{
|
||||
_Core->EmitPlayerState(player, previous, current);
|
||||
|
||||
switch (current)
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
case SQMOD_PLAYER_STATE_NONE:
|
||||
_Core->EmitStateNone(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_NORMAL:
|
||||
_Core->EmitStateNormal(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_SHOOTING:
|
||||
_Core->EmitStateShooting(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_DRIVER:
|
||||
_Core->EmitStateDriver(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_PASSENGER:
|
||||
_Core->EmitStatePassenger(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_ENTERING_AS_DRIVER:
|
||||
_Core->EmitStateEnterDriver(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_ENTERING_AS_PASSENGER:
|
||||
_Core->EmitStateEnterPassenger(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_EXITING_VEHICLE:
|
||||
_Core->EmitStateExitVehicle(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_UNSPAWNED:
|
||||
_Core->EmitStateUnspawned(player, previous);
|
||||
break;
|
||||
_Core->EmitPlayerState(player, previous, current);
|
||||
// Identify the current state and trigger the listeners specific to that
|
||||
switch (current)
|
||||
{
|
||||
case SQMOD_PLAYER_STATE_NONE:
|
||||
_Core->EmitStateNone(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_NORMAL:
|
||||
_Core->EmitStateNormal(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_SHOOTING:
|
||||
_Core->EmitStateShooting(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_DRIVER:
|
||||
_Core->EmitStateDriver(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_PASSENGER:
|
||||
_Core->EmitStatePassenger(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_ENTERING_AS_DRIVER:
|
||||
_Core->EmitStateEnterDriver(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_ENTERING_AS_PASSENGER:
|
||||
_Core->EmitStateEnterPassenger(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_EXITING_VEHICLE:
|
||||
_Core->EmitStateExitVehicle(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_STATE_UNSPAWNED:
|
||||
_Core->EmitStateUnspawned(player, previous);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerState)
|
||||
}
|
||||
|
||||
static void VC_PlayerAction(int player, int previous, int current)
|
||||
{
|
||||
_Core->EmitPlayerAction(player, previous, current);
|
||||
|
||||
switch (current)
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
case SQMOD_PLAYER_ACTION_NONE:
|
||||
_Core->EmitActionNone(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_NORMAL:
|
||||
_Core->EmitActionNormal(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_AIMING:
|
||||
_Core->EmitActionAiming(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_SHOOTING:
|
||||
_Core->EmitActionShooting(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_JUMPING:
|
||||
_Core->EmitActionJumping(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_LYING_ON_GROUND:
|
||||
_Core->EmitActionLieDown(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_GETTING_UP:
|
||||
_Core->EmitActionGettingUp(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_JUMPING_FROM_VEHICLE:
|
||||
_Core->EmitActionJumpVehicle(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_DRIVING:
|
||||
_Core->EmitActionDriving(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_DYING:
|
||||
_Core->EmitActionDying(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_WASTED:
|
||||
_Core->EmitActionWasted(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_ENTERING_VEHICLE:
|
||||
_Core->EmitActionEmbarking(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_EXITING_VEHICLE:
|
||||
_Core->EmitActionDisembarking(player, previous);
|
||||
break;
|
||||
_Core->EmitPlayerAction(player, previous, current);
|
||||
// Identify the current action and trigger the listeners specific to that
|
||||
switch (current)
|
||||
{
|
||||
case SQMOD_PLAYER_ACTION_NONE:
|
||||
_Core->EmitActionNone(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_NORMAL:
|
||||
_Core->EmitActionNormal(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_AIMING:
|
||||
_Core->EmitActionAiming(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_SHOOTING:
|
||||
_Core->EmitActionShooting(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_JUMPING:
|
||||
_Core->EmitActionJumping(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_LYING_ON_GROUND:
|
||||
_Core->EmitActionLieDown(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_GETTING_UP:
|
||||
_Core->EmitActionGettingUp(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_JUMPING_FROM_VEHICLE:
|
||||
_Core->EmitActionJumpVehicle(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_DRIVING:
|
||||
_Core->EmitActionDriving(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_DYING:
|
||||
_Core->EmitActionDying(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_WASTED:
|
||||
_Core->EmitActionWasted(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_ENTERING_VEHICLE:
|
||||
_Core->EmitActionEmbarking(player, previous);
|
||||
break;
|
||||
case SQMOD_PLAYER_ACTION_EXITING_VEHICLE:
|
||||
_Core->EmitActionDisembarking(player, previous);
|
||||
break;
|
||||
}
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerAction)
|
||||
}
|
||||
|
||||
static void VC_PlayerOnFire(int player, unsigned int state)
|
||||
{
|
||||
_Core->EmitPlayerBurning(player, static_cast<bool>(state));
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerBurning(player, static_cast< bool >(state));
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerOnFire)
|
||||
}
|
||||
|
||||
static void VC_PlayerCrouch(int player, unsigned int state)
|
||||
{
|
||||
_Core->EmitPlayerCrouching(player, static_cast<bool>(state));
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerCrouching(player, static_cast< bool >(state));
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerCrouch)
|
||||
}
|
||||
|
||||
static void VC_PlayerGameKeys(int player, int previous, int current)
|
||||
{
|
||||
_Core->EmitPlayerGameKeys(player, previous, current);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitPlayerGameKeys(player, previous, current);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(PlayerGameKeys)
|
||||
}
|
||||
|
||||
static void VC_OnCheckpointEntered(int checkpoint, int player)
|
||||
{
|
||||
_Core->EmitCheckpointEntered(player, checkpoint);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitCheckpointEntered(player, checkpoint);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(CheckpointEntered)
|
||||
}
|
||||
|
||||
static void VC_OnCheckpointExited(int checkpoint, int player)
|
||||
{
|
||||
_Core->EmitCheckpointExited(player, checkpoint);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitCheckpointExited(player, checkpoint);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(CheckpointExited)
|
||||
}
|
||||
|
||||
static void VC_OnSphereEntered(int sphere, int player)
|
||||
{
|
||||
_Core->EmitForcefieldEntered(player, sphere);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitForcefieldEntered(player, sphere);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(SphereEntered)
|
||||
}
|
||||
|
||||
static void VC_OnSphereExited(int sphere, int player)
|
||||
{
|
||||
_Core->EmitForcefieldExited(player, sphere);
|
||||
// Attempt to forward the event
|
||||
try
|
||||
{
|
||||
_Core->EmitForcefieldExited(player, sphere);
|
||||
}
|
||||
SQMOD_CATCH_EVENT_EXCEPTION(SphereExited)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
@ -14,13 +14,24 @@ Routine::Time Routine::s_Last = 0;
|
||||
Routine::Time Routine::s_Prev = 0;
|
||||
Routine::Queue Routine::s_Queue;
|
||||
Routine::Buckets Routine::s_Buckets;
|
||||
Routine::Objects Routine::s_Objects;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger Routine::Typename(HSQUIRRELVM vm)
|
||||
{
|
||||
static SQChar name[] = _SC("SqRoutine");
|
||||
sq_pushstring(vm, name, sizeof(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Routine::Attach(Routine * routine, Interval interval)
|
||||
{
|
||||
// Do we have a valid routine and interval bucket to attach?
|
||||
if (!routine || ! interval)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Attempt to locate the bucket with the specified interval
|
||||
Buckets::iterator itr = std::find_if(s_Buckets.begin(), s_Buckets.end(), IntrvFunc(interval));
|
||||
// Does this bucket exist?
|
||||
@ -33,8 +44,9 @@ void Routine::Attach(Routine * routine, Interval interval)
|
||||
}
|
||||
// Is this routine already attached to this bucket?
|
||||
else if (std::find(itr->mRoutines.begin(), itr->mRoutines.end(), routine) != itr->mRoutines.end())
|
||||
// Then let's attach it now
|
||||
itr->mRoutines.push_back(routine);
|
||||
{
|
||||
itr->mRoutines.push_back(routine); // Then let's attach it now
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -42,22 +54,89 @@ void Routine::Detach(Routine * routine, Interval interval)
|
||||
{
|
||||
// Do we have a valid routine and interval to detach?
|
||||
if (!routine || ! interval)
|
||||
{
|
||||
return;
|
||||
}
|
||||
// Attempt to locate the bucket with this interval
|
||||
Buckets::iterator bitr = std::find_if(s_Buckets.begin(), s_Buckets.end(), IntrvFunc(interval));
|
||||
// Was there a bucket with this interval?
|
||||
if (bitr == s_Buckets.end())
|
||||
{
|
||||
return; // Nothing to detach from!
|
||||
}
|
||||
// Attempt to find this routine in the associated bucket
|
||||
Routines::iterator ritr = std::find(bitr->mRoutines.begin(), bitr->mRoutines.end(), routine);
|
||||
// Was this routine even attached?
|
||||
if (ritr != bitr->mRoutines.end())
|
||||
// Then erase it and move on
|
||||
bitr->mRoutines.erase(ritr);
|
||||
{
|
||||
bitr->mRoutines.erase(ritr); // Then erase it and move on
|
||||
}
|
||||
// Any reason to keep this bucket?
|
||||
if (bitr->mRoutines.empty())
|
||||
// Remove the bucket as well
|
||||
s_Buckets.erase(bitr);
|
||||
{
|
||||
s_Buckets.erase(bitr); // Remove the bucket as well
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object Routine::Associate(Routine * routine)
|
||||
{
|
||||
// Attempt to see if this instance already exists in the pool
|
||||
Objects::iterator itr = s_Objects.find(routine);
|
||||
// Is this routine remembered for the first time?
|
||||
if (itr == s_Objects.end())
|
||||
{
|
||||
// Obtain the initial stack size
|
||||
const StackGuard sg;
|
||||
// Push this instance on the stack
|
||||
ClassType< Routine >::PushInstance(DefaultVM::Get(), routine);
|
||||
// Initialize this element into the pool
|
||||
itr = s_Objects.emplace(routine, Var< Object >(DefaultVM::Get(), -1).value).first;
|
||||
// If the iterator still points to a null element then we failed
|
||||
if (itr == s_Objects.end())
|
||||
{
|
||||
SqThrowF("Unable to remember routine instance");
|
||||
}
|
||||
}
|
||||
// Does this routine still keep a strong reference to it self?
|
||||
else if (itr->second.IsNull())
|
||||
{
|
||||
// Obtain the initial stack size
|
||||
const StackGuard sg;
|
||||
// Push this instance on the stack
|
||||
ClassType< Routine >::PushInstance(DefaultVM::Get(), routine);
|
||||
// Obtain a strong reference to it
|
||||
itr->second = Var< Object >(DefaultVM::Get(), -1).value;
|
||||
}
|
||||
// Return the object that we have
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Routine::Dissociate(Routine * routine)
|
||||
{
|
||||
// Attempt to see if this instance already exists in the pool
|
||||
Objects::iterator itr = s_Objects.find(routine);
|
||||
// Was this routine even stored in the pool?
|
||||
if (itr != s_Objects.end() && !itr->second.IsNull())
|
||||
{
|
||||
itr->second.Release(); // Release the reference to self
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
bool Routine::Associated(Routine * routine)
|
||||
{
|
||||
// Attempt to see if this instance already exists in the pool
|
||||
Objects::iterator itr = s_Objects.find(routine);
|
||||
// Return whether this routine is pooled and references itself
|
||||
return (itr != s_Objects.end() && !itr->second.IsNull());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Routine::Forget(Routine * routine)
|
||||
{
|
||||
s_Objects.erase(routine);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -65,16 +144,28 @@ void Routine::ProcQueue()
|
||||
{
|
||||
// Do we have any queued commands that must be performed when unlocked?
|
||||
if (s_Queue.empty() || s_Lock)
|
||||
{
|
||||
return; // We're done here!
|
||||
}
|
||||
// Process all commands in the queue
|
||||
for (const auto & cmd : s_Queue)
|
||||
{
|
||||
// Are we supposed to detach the associated routine?
|
||||
if (cmd.mCommand == CMD_DETACH)
|
||||
{
|
||||
// Detach the routine from it's associated bucket first
|
||||
Detach(cmd.mRoutine, cmd.mInterval);
|
||||
// Break association to allow the instance to be destroyed
|
||||
Dissociate(cmd.mRoutine);
|
||||
}
|
||||
// Are we supposed to attach the associated routine?
|
||||
else if (cmd.mCommand == CMD_ATTACH)
|
||||
{
|
||||
// Attach the routine to it's associated bucket first
|
||||
Attach(cmd.mRoutine, cmd.mInterval);
|
||||
// Prevent destruction of this routine while buckets are locked
|
||||
Associate(cmd.mRoutine);
|
||||
}
|
||||
}
|
||||
// Clear processed commands
|
||||
s_Queue.clear();
|
||||
@ -109,10 +200,14 @@ void Routine::Process()
|
||||
bucket.mElapsed += delta;
|
||||
// Have we completed the bucket interval?
|
||||
if (bucket.mElapsed < bucket.mInterval)
|
||||
{
|
||||
continue; // Move to the next one
|
||||
}
|
||||
// Attempt to execute bucket routines, if any
|
||||
for (auto & routine : bucket.mRoutines)
|
||||
{
|
||||
routine->Execute();
|
||||
}
|
||||
// Reset the bucket elapsed time
|
||||
bucket.mElapsed = 0;
|
||||
}
|
||||
@ -141,6 +236,8 @@ void Routine::TerminateAll()
|
||||
}
|
||||
// Clear all references to routines
|
||||
s_Buckets.clear();
|
||||
// Clear all routine instance associations
|
||||
s_Objects.clear();
|
||||
// Clear the last time-stamp in case of a reload
|
||||
s_Last = 0;
|
||||
}
|
||||
@ -153,6 +250,8 @@ Routine::Routine(Object & env, Function & func, Interval interval)
|
||||
, m_Suspended(false)
|
||||
, m_Terminated(false)
|
||||
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||
, m_Tag()
|
||||
, m_Data()
|
||||
{
|
||||
Create();
|
||||
}
|
||||
@ -164,6 +263,8 @@ Routine::Routine(Object & env, Function & func, Interval interval, Iterate itera
|
||||
, m_Suspended(false)
|
||||
, m_Terminated(false)
|
||||
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||
, m_Tag()
|
||||
, m_Data()
|
||||
{
|
||||
Create();
|
||||
}
|
||||
@ -177,6 +278,8 @@ Routine::Routine(Object & env, Function & func, Interval interval, Iterate itera
|
||||
, m_Suspended(false)
|
||||
, m_Terminated(false)
|
||||
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||
, m_Tag()
|
||||
, m_Data()
|
||||
, m_Arg1(a1)
|
||||
{
|
||||
Create();
|
||||
@ -191,6 +294,8 @@ Routine::Routine(Object & env, Function & func, Interval interval, Iterate itera
|
||||
, m_Suspended(false)
|
||||
, m_Terminated(false)
|
||||
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||
, m_Tag()
|
||||
, m_Data()
|
||||
, m_Arg1(a1), m_Arg2(a2)
|
||||
{
|
||||
Create();
|
||||
@ -205,6 +310,8 @@ Routine::Routine(Object & env, Function & func, Interval interval, Iterate itera
|
||||
, m_Suspended(false)
|
||||
, m_Terminated(false)
|
||||
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||
, m_Tag()
|
||||
, m_Data()
|
||||
, m_Arg1(a1), m_Arg2(a2), m_Arg3(a3)
|
||||
{
|
||||
Create();
|
||||
@ -219,6 +326,8 @@ Routine::Routine(Object & env, Function & func, Interval interval, Iterate itera
|
||||
, m_Suspended(false)
|
||||
, m_Terminated(false)
|
||||
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||
, m_Tag()
|
||||
, m_Data()
|
||||
, m_Arg1(a1), m_Arg2(a2), m_Arg3(a3), m_Arg4(a4)
|
||||
{
|
||||
Create();
|
||||
@ -233,6 +342,8 @@ Routine::Routine(Object & env, Function & func, Interval interval, Iterate itera
|
||||
, m_Suspended(false)
|
||||
, m_Terminated(false)
|
||||
, m_Callback(env.GetVM(), env, func.GetFunc())
|
||||
, m_Tag()
|
||||
, m_Data()
|
||||
, m_Arg1(a1), m_Arg2(a2), m_Arg3(a3), m_Arg4(a4), m_Arg5(a5)
|
||||
{
|
||||
Create();
|
||||
@ -241,9 +352,13 @@ Routine::Routine(Object & env, Function & func, Interval interval, Iterate itera
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Routine::~Routine()
|
||||
{
|
||||
// Remove this instance from the pool
|
||||
Forget(this);
|
||||
// Was the routine already terminated?
|
||||
if (m_Terminated)
|
||||
return;
|
||||
{
|
||||
return; // Nothing to release!
|
||||
}
|
||||
// Detach from the associated bucket
|
||||
Detach();
|
||||
// Release script resources
|
||||
@ -267,12 +382,63 @@ CSStr Routine::ToString() const
|
||||
return ToStrF(_PRINT_INT_FMT, m_Interval);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
const String & Routine::GetTag() const
|
||||
{
|
||||
return m_Tag;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Routine::SetTag(CSStr tag)
|
||||
{
|
||||
m_Tag.assign(tag);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object & Routine::GetData()
|
||||
{
|
||||
// Validate the routine lifetime
|
||||
Validate();
|
||||
// Return the requested information
|
||||
return m_Data;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Routine::SetData(Object & data)
|
||||
{
|
||||
// Validate the routine lifetime
|
||||
Validate();
|
||||
// Apply the specified value
|
||||
m_Data = data;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Routine & Routine::ApplyTag(CSStr tag)
|
||||
{
|
||||
m_Tag.assign(tag);
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Routine & Routine::ApplyData(Object & data)
|
||||
{
|
||||
// Validate the routine lifetime
|
||||
Validate();
|
||||
// Apply the specified value
|
||||
m_Data = data;
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Routine::Terminate()
|
||||
{
|
||||
// Was the routine already terminated?
|
||||
if (m_Terminated)
|
||||
SqThrowF("Routine was already terminated");
|
||||
{
|
||||
SqThrowF("Routine [%s] => Was already terminated", m_Tag.c_str());
|
||||
}
|
||||
// Detach from the associated bucket
|
||||
Detach();
|
||||
// Release script resources and mark it as terminated
|
||||
@ -280,11 +446,10 @@ void Routine::Terminate()
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Routine::SetArg(Uint8 num, Object & val)
|
||||
Routine & Routine::SetArg(Uint8 num, Object & val)
|
||||
{
|
||||
// Was the routine terminated?
|
||||
if (m_Terminated)
|
||||
SqThrowF("Routine was terminated");
|
||||
// Validate the routine lifetime
|
||||
Validate();
|
||||
// Identify which argument was requested
|
||||
switch (num)
|
||||
{
|
||||
@ -302,15 +467,17 @@ void Routine::SetArg(Uint8 num, Object & val)
|
||||
case 12: m_Arg12 = val; break;
|
||||
case 13: m_Arg13 = val; break;
|
||||
case 14: m_Arg14 = val; break;
|
||||
default: SqThrowF("Argument is out of range: %d", num);
|
||||
default: SqThrowF("Routine [%s] => Argument is out of range: %d", m_Tag.c_str(), num);
|
||||
}
|
||||
// Allow chaining
|
||||
return *this;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object & Routine::GetArg(Uint8 num)
|
||||
{
|
||||
// Was the routine terminated?
|
||||
if (m_Terminated)
|
||||
SqThrowF("Routine was terminated");
|
||||
// Validate the routine lifetime
|
||||
Validate();
|
||||
// Identify which argument was requested
|
||||
switch (num)
|
||||
{
|
||||
@ -328,7 +495,7 @@ Object & Routine::GetArg(Uint8 num)
|
||||
case 12: return m_Arg12;
|
||||
case 13: return m_Arg13;
|
||||
case 14: return m_Arg14;
|
||||
default: SqThrowF("Argument is out of range: %d", num);
|
||||
default: SqThrowF("Routine [%s] => Argument is out of range: %d", m_Tag.c_str(), num);
|
||||
}
|
||||
// Shouldn't really reach this point
|
||||
return NullObject();
|
||||
@ -340,14 +507,16 @@ Routine::Interval Routine::GetInterval() const
|
||||
return m_Interval;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Routine::SetInterval(Interval interval)
|
||||
{
|
||||
// Was the routine terminated?
|
||||
if (m_Terminated)
|
||||
SqThrowF("Routine was terminated");
|
||||
// Validate the routine lifetime
|
||||
Validate();
|
||||
// Is the specified interval valid?
|
||||
else if (!interval)
|
||||
SqThrowF("Invalid routine interval");
|
||||
if (!interval)
|
||||
{
|
||||
SqThrowF("Routine [%s] => Invalid interval", m_Tag.c_str());
|
||||
}
|
||||
// Detach from the current bucket
|
||||
Detach();
|
||||
// Update the interval
|
||||
@ -362,11 +531,11 @@ Routine::Iterate Routine::GetIterations() const
|
||||
return m_Iterations;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Routine::SetIterations(Iterate iterations)
|
||||
{
|
||||
// Was the routine terminated?
|
||||
if (m_Terminated)
|
||||
SqThrowF("Routine was terminated");
|
||||
// Validate the routine lifetime
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Iterations = iterations;
|
||||
}
|
||||
@ -379,12 +548,13 @@ Uint8 Routine::GetArguments() const
|
||||
|
||||
void Routine::SetArguments(Uint8 num)
|
||||
{
|
||||
// Was the routine terminated?
|
||||
if (m_Terminated)
|
||||
SqThrowF("Routine was terminated");
|
||||
// Validate the routine lifetime
|
||||
Validate();
|
||||
// Is the specified argument count valid?
|
||||
else if (num > 14)
|
||||
SqThrowF("Argument is out of range: %d", num);
|
||||
if (num > 14)
|
||||
{
|
||||
SqThrowF("Routine [%s] => Argument is out of range: %d", m_Tag.c_str(), num);
|
||||
}
|
||||
// Perform the requested operation
|
||||
m_Arguments = num;
|
||||
}
|
||||
@ -395,11 +565,11 @@ bool Routine::GetSuspended() const
|
||||
return m_Suspended;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Routine::SetSuspended(bool toggle)
|
||||
{
|
||||
// Was the routine terminated?
|
||||
if (m_Terminated)
|
||||
SqThrowF("Routine was terminated");
|
||||
// Validate the routine lifetime
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Suspended = toggle;
|
||||
}
|
||||
@ -413,18 +583,17 @@ bool Routine::GetTerminated() const
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Function & Routine::GetCallback()
|
||||
{
|
||||
// Was the routine terminated?
|
||||
if (m_Terminated)
|
||||
SqThrowF("Routine was terminated");
|
||||
// Validate the routine lifetime
|
||||
Validate();
|
||||
// Return the requested information
|
||||
return m_Callback;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Routine::SetCallback(Object & env, Function & func)
|
||||
{
|
||||
// Was the routine terminated?
|
||||
if (m_Terminated)
|
||||
SqThrowF("Routine was terminated");
|
||||
// Validate the routine lifetime
|
||||
Validate();
|
||||
// Perform the requested operation
|
||||
m_Callback = Function(env.GetVM(), env, func.GetFunc());
|
||||
}
|
||||
@ -432,9 +601,11 @@ void Routine::SetCallback(Object & env, Function & func)
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Routine::Release()
|
||||
{
|
||||
// Was the routine terminated?
|
||||
// Was the routine already terminated?
|
||||
if (m_Terminated)
|
||||
return;
|
||||
{
|
||||
return; // Nothing to release!
|
||||
}
|
||||
// Mark it as terminated
|
||||
m_Terminated = true;
|
||||
// Release the callback
|
||||
@ -459,14 +630,18 @@ void Routine::Release()
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void Routine::Create()
|
||||
{
|
||||
// Was the routine terminated?
|
||||
// Do we even have a valid interval?
|
||||
if (!m_Interval)
|
||||
SqThrowF("Invalid routine interval");
|
||||
// Is the specified callback valid?
|
||||
{
|
||||
SqThrowF("Routine [%s] => Invalid interval", m_Tag.c_str());
|
||||
}
|
||||
// Is the specified callback even valid?
|
||||
else if (m_Callback.IsNull())
|
||||
SqThrowF("Invalid routine callback");
|
||||
// Attempt to attach the routine
|
||||
Attach();
|
||||
{
|
||||
SqThrowF("Routine [%s] => Invalid callback", m_Tag.c_str());
|
||||
}
|
||||
// Always use the command queue to attach the routine when created
|
||||
s_Queue.emplace_back(this, m_Interval, CMD_ATTACH);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -474,14 +649,23 @@ void Routine::Attach()
|
||||
{
|
||||
// Do we have a valid interval?
|
||||
if (!m_Interval)
|
||||
{
|
||||
return; // Nothing to attach to!
|
||||
}
|
||||
// Are the buckets locked?
|
||||
else if (s_Lock)
|
||||
{
|
||||
// Queue a command to attach this routine when the bucket is unlocked
|
||||
s_Queue.emplace_back(this, m_Interval, CMD_ATTACH);
|
||||
}
|
||||
// Attempt to attach the the routine now
|
||||
else
|
||||
{
|
||||
// Attach to the associated bucket
|
||||
Attach(this, m_Interval);
|
||||
// Associate the instance with it's script object to prevent unexpected release
|
||||
Associate(this);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -489,14 +673,23 @@ void Routine::Detach()
|
||||
{
|
||||
// Do we have a valid interval?
|
||||
if (!m_Interval)
|
||||
{
|
||||
return; // Nothing to detach from!
|
||||
}
|
||||
// Are the buckets locked?
|
||||
else if (s_Lock)
|
||||
{
|
||||
// Queue a command to detach this routine when the bucket is unlocked
|
||||
s_Queue.emplace_back(this, m_Interval, CMD_DETACH);
|
||||
}
|
||||
// Attempt to detach the the routine now
|
||||
else
|
||||
{
|
||||
// Detach from the associated bucket
|
||||
Detach(this, m_Interval);
|
||||
// Break association to allow the instance to be released
|
||||
Dissociate(this);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
@ -504,53 +697,91 @@ void Routine::Execute()
|
||||
{
|
||||
// Is this routine suspended or has nothing to call?
|
||||
if (m_Suspended || m_Callback.IsNull())
|
||||
return; // We're done here!
|
||||
// Attempt to identify how many arguments should be passed
|
||||
switch (m_Arguments)
|
||||
{
|
||||
case 0: m_Callback.Execute();
|
||||
break;
|
||||
case 1: m_Callback.Execute(m_Arg1);
|
||||
break;
|
||||
case 2: m_Callback.Execute(m_Arg1, m_Arg2);
|
||||
break;
|
||||
case 3: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3);
|
||||
break;
|
||||
case 4: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4);
|
||||
break;
|
||||
case 5: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5);
|
||||
break;
|
||||
case 6: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6);
|
||||
break;
|
||||
case 7: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7);
|
||||
break;
|
||||
case 8: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
return; // We're done here!
|
||||
}
|
||||
// Make sure that we have a known number of arguments
|
||||
else if (m_Arguments > 14)
|
||||
{
|
||||
SqThrowF("Routine [%s] => Out of range argument count: %d", m_Tag.c_str(), m_Arguments);
|
||||
}
|
||||
// Attempt to forward the call
|
||||
try
|
||||
{
|
||||
switch (m_Arguments)
|
||||
{
|
||||
// Attempt to identify how many arguments should be passed
|
||||
case 0:
|
||||
m_Callback.Execute();
|
||||
break;
|
||||
case 1:
|
||||
m_Callback.Execute(m_Arg1);
|
||||
break;
|
||||
case 2:
|
||||
m_Callback.Execute(m_Arg1, m_Arg2);
|
||||
break;
|
||||
case 3:
|
||||
m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3);
|
||||
break;
|
||||
case 4:
|
||||
m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4);
|
||||
break;
|
||||
case 5:
|
||||
m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5);
|
||||
break;
|
||||
case 6:
|
||||
m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6);
|
||||
break;
|
||||
case 7:
|
||||
m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7);
|
||||
break;
|
||||
case 8:
|
||||
m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
m_Arg8);
|
||||
break;
|
||||
case 9: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
break;
|
||||
case 9:
|
||||
m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
m_Arg8, m_Arg9);
|
||||
break;
|
||||
case 10: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
break;
|
||||
case 10:
|
||||
m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
m_Arg8, m_Arg9, m_Arg10);
|
||||
break;
|
||||
case 11: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
break;
|
||||
case 11:
|
||||
m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
m_Arg8, m_Arg9, m_Arg10, m_Arg11);
|
||||
break;
|
||||
case 12: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
break;
|
||||
case 12:
|
||||
m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
m_Arg8, m_Arg9, m_Arg10, m_Arg11, m_Arg12);
|
||||
break;
|
||||
case 13: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
break;
|
||||
case 13:
|
||||
m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
m_Arg8, m_Arg9, m_Arg10, m_Arg11, m_Arg12, m_Arg13);
|
||||
break;
|
||||
case 14: m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
break;
|
||||
case 14:
|
||||
m_Callback.Execute(m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
m_Arg8, m_Arg9, m_Arg10, m_Arg11, m_Arg12, m_Arg13, m_Arg14);
|
||||
break;
|
||||
default:
|
||||
SqThrowF("Unknown argument count: %d", m_Arguments);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (const Sqrat::Exception & e)
|
||||
{
|
||||
SqThrowF("Routine [%s] => Squirrel error: %s", m_Tag.c_str(), e.Message().c_str());
|
||||
}
|
||||
catch (const std::exception & e)
|
||||
{
|
||||
SqThrowF("Routine [%s] => Program error: %s", m_Tag.c_str(), e.what());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
SqThrowF("Routine [%s] => Unknown error", m_Tag.c_str());
|
||||
}
|
||||
// Decrease the number of iterations if necessary
|
||||
if (m_Iterations && (--m_Iterations) == 0)
|
||||
{
|
||||
Terminate(); // This routine reached the end of it's life
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
@ -569,28 +800,103 @@ void TerminateRoutine()
|
||||
Routine::TerminateAll();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object Routine::Create(Object & env, Function & func, Interval interval)
|
||||
{
|
||||
return Associate(new Routine(env, func, interval));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object Routine::Create(Object & env, Function & func, Interval interval, Iterate iterations)
|
||||
{
|
||||
return Associate(new Routine(env, func, interval, iterations));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object Routine::Create(Object & env, Function & func, Interval interval, Iterate iterations
|
||||
, Object & a1)
|
||||
{
|
||||
return Associate(new Routine(env, func, interval, iterations, a1));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object Routine::Create(Object & env, Function & func, Interval interval, Iterate iterations
|
||||
, Object & a1, Object & a2)
|
||||
{
|
||||
return Associate(new Routine(env, func, interval, iterations, a1, a2));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object Routine::Create(Object & env, Function & func, Interval interval, Iterate iterations
|
||||
, Object & a1, Object & a2, Object & a3)
|
||||
{
|
||||
return Associate(new Routine(env, func, interval, iterations, a1, a2, a3));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object Routine::Create(Object & env, Function & func, Interval interval, Iterate iterations
|
||||
, Object & a1, Object & a2, Object & a3, Object & a4)
|
||||
{
|
||||
return Associate(new Routine(env, func, interval, iterations, a1, a2, a3, a4));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object Routine::Create(Object & env, Function & func, Interval interval, Iterate iterations
|
||||
, Object & a1, Object & a2, Object & a3, Object & a4, Object & a5)
|
||||
{
|
||||
return Associate(new Routine(env, func, interval, iterations, a1, a2, a3, a4, a5));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Uint32 Routine::Count()
|
||||
{
|
||||
return static_cast< Uint32 >(s_Objects.size());
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object Routine::FindByTag(CSStr tag)
|
||||
{
|
||||
// Perform a validity check on the specified tag
|
||||
if (!tag || *tag == '\0')
|
||||
{
|
||||
SqThrowF("The specified routine tag is invalid: null/empty");
|
||||
}
|
||||
// Process each routine in the pool
|
||||
for (const auto & elem : s_Objects)
|
||||
{
|
||||
// Is this routine valid (should always be) and does the tag match the specified one?
|
||||
if (elem.first != nullptr && elem.first->m_Tag.compare(tag) == 0)
|
||||
{
|
||||
// Do we need to obtain the script object again?
|
||||
if (elem.second.IsNull())
|
||||
{
|
||||
// Obtain the initial stack size
|
||||
const StackGuard sg;
|
||||
// Push this instance on the stack
|
||||
ClassType< Routine >::PushInstance(DefaultVM::Get(), elem.first);
|
||||
// Obtain a strong reference to it and return it
|
||||
return Var< Object >(DefaultVM::Get(), -1).value;
|
||||
}
|
||||
// Stop searching and return this routine
|
||||
return elem.second;
|
||||
}
|
||||
}
|
||||
// Unable to locate a routine matching the specified tag
|
||||
return NullObject();
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_Routine(HSQUIRRELVM vm)
|
||||
{
|
||||
RootTable(vm).Bind(_SC("SqRoutine"),
|
||||
Class< Routine, NoCopy< Routine > >(vm, _SC("SqRoutine"))
|
||||
/* Constructors */
|
||||
.Ctor< Object &, Function &, Routine::Interval >()
|
||||
.Ctor< Object &, Function &, Routine::Interval, Routine::Iterate >()
|
||||
.Ctor< Object &, Function &, Routine::Interval, Routine::Iterate
|
||||
, Object & >()
|
||||
.Ctor< Object &, Function &, Routine::Interval, Routine::Iterate
|
||||
, Object &, Object & >()
|
||||
.Ctor< Object &, Function &, Routine::Interval, Routine::Iterate
|
||||
, Object &, Object &, Object & >()
|
||||
.Ctor< Object &, Function &, Routine::Interval, Routine::Iterate
|
||||
, Object &, Object &, Object &, Object & >()
|
||||
.Ctor< Object &, Function &, Routine::Interval, Routine::Iterate
|
||||
, Object &, Object &, Object &, Object &, Object & >()
|
||||
Class< Routine, NoConstructor< Routine > >(vm, _SC("SqRoutine"))
|
||||
/* Metamethods */
|
||||
.Func(_SC("_cmp"), &Routine::Cmp)
|
||||
.SquirrelFunc(_SC("_typename"), &Routine::Typename)
|
||||
.Func(_SC("_tostring"), &Routine::ToString)
|
||||
/* Properties */
|
||||
.Prop(_SC("Tag"), &Routine::GetTag, &Routine::SetTag)
|
||||
.Prop(_SC("Data"), &Routine::GetData, &Routine::SetData)
|
||||
.Prop(_SC("Interval"), &Routine::GetInterval, &Routine::SetInterval)
|
||||
.Prop(_SC("Iterations"), &Routine::GetIterations, &Routine::SetIterations)
|
||||
.Prop(_SC("Arguments"), &Routine::GetArguments, &Routine::SetArguments)
|
||||
@ -598,10 +904,35 @@ void Register_Routine(HSQUIRRELVM vm)
|
||||
.Prop(_SC("Terminated"), &Routine::GetTerminated)
|
||||
.Prop(_SC("Callback"), &Routine::GetCallback)
|
||||
/* Functions */
|
||||
.Func(_SC("SetTag"), &Routine::ApplyTag)
|
||||
.Func(_SC("SetData"), &Routine::ApplyData)
|
||||
.Func(_SC("Terminate"), &Routine::Terminate)
|
||||
.Func(_SC("Bind"), &Routine::SetCallback)
|
||||
.Func(_SC("GetArg"), &Routine::GetArg)
|
||||
.Func(_SC("SetArg"), &Routine::SetArg)
|
||||
// Static Functions
|
||||
.StaticFunc(_SC("Count"), &Routine::Count)
|
||||
.StaticFunc(_SC("FindByTag"), &Routine::FindByTag)
|
||||
// Static Overloads
|
||||
.StaticOverload< Object (*)(Object &, Function &, Routine::Interval) >
|
||||
(_SC("Create"), &Routine::Create)
|
||||
.StaticOverload< Object (*)(Object &, Function &, Routine::Interval, Routine::Iterate) >
|
||||
(_SC("Create"), &Routine::Create)
|
||||
.StaticOverload< Object (*)(Object &, Function &, Routine::Interval, Routine::Iterate,
|
||||
Object &) >
|
||||
(_SC("Create"), &Routine::Create)
|
||||
.StaticOverload< Object (*)(Object &, Function &, Routine::Interval, Routine::Iterate,
|
||||
Object &, Object &) >
|
||||
(_SC("Create"), &Routine::Create)
|
||||
.StaticOverload< Object (*)(Object &, Function &, Routine::Interval, Routine::Iterate,
|
||||
Object &, Object &, Object &) >
|
||||
(_SC("Create"), &Routine::Create)
|
||||
.StaticOverload< Object (*)(Object &, Function &, Routine::Interval, Routine::Iterate,
|
||||
Object &, Object &, Object &, Object &) >
|
||||
(_SC("Create"), &Routine::Create)
|
||||
.StaticOverload< Object (*)(Object &, Function &, Routine::Interval, Routine::Iterate,
|
||||
Object &, Object &, Object &, Object &, Object &) >
|
||||
(_SC("Create"), &Routine::Create)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -138,9 +138,10 @@ protected:
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Int64 Time;
|
||||
typedef std::vector< Cmd > Queue;
|
||||
typedef std::vector< Bucket > Buckets;
|
||||
typedef Int64 Time;
|
||||
typedef std::vector< Cmd > Queue;
|
||||
typedef std::vector< Bucket > Buckets;
|
||||
typedef std::unordered_map< Routine *, Object > Objects;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Functor used to search for buckets with a certain interval.
|
||||
@ -186,6 +187,7 @@ protected:
|
||||
static Time s_Prev; /* Previous time point. */
|
||||
static Queue s_Queue; /* Actions to be performed when the buckets aren't locked */
|
||||
static Buckets s_Buckets; /* Buckets of routines grouped by similar intervals. */
|
||||
static Objects s_Objects; /* List of existing routines and their associated object. */
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attach a routine to a certain bucket.
|
||||
@ -197,43 +199,44 @@ protected:
|
||||
*/
|
||||
static void Detach(Routine * routine, Interval interval);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Create or locate the object for the specified routine and keep a strong reference to it.
|
||||
*/
|
||||
static Object Associate(Routine * routine);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Release the strong reference associated with the specified routine so it can be destroyed.
|
||||
*/
|
||||
static void Dissociate(Routine * routine);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether the specified routine exists in the pool and references itself.
|
||||
*/
|
||||
static bool Associated(Routine * routine);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Remove the specified routine from the pool and any associated reference, if any.
|
||||
*/
|
||||
static void Forget(Routine * routine);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Process queue commands.
|
||||
*/
|
||||
static void ProcQueue();
|
||||
|
||||
private:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor. (disabled)
|
||||
* See whether this routine is valid otherwise throw an exception.
|
||||
*/
|
||||
Routine(const Routine &);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator. (disabled)
|
||||
*/
|
||||
Routine & operator = (const Routine &);
|
||||
void Validate() const
|
||||
{
|
||||
if (m_Terminated)
|
||||
{
|
||||
SqThrowF("Routine [%s] => Was terminated", m_Tag.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Iterate m_Iterations; /* Number of iterations before self destruct. */
|
||||
Interval m_Interval; /* Interval between calls. */
|
||||
Uint8 m_Arguments; /* Number of arguments to forward. */
|
||||
bool m_Suspended; /* Whether calls should be ignored. */
|
||||
bool m_Terminated; /* Whether the routine was terminated. */
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Function m_Callback; /* The callback to be executed when triggered. */
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Arguments to be forwarded to the callback.
|
||||
*/
|
||||
Object m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
m_Arg8, m_Arg9, m_Arg10, m_Arg11, m_Arg12, m_Arg13, m_Arg14;
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Constructor with just an interval.
|
||||
*/
|
||||
@ -274,6 +277,66 @@ public:
|
||||
Routine(Object & env, Function & func, Interval interval, Iterate iterations
|
||||
, Object & a1, Object & a2, Object & a3, Object & a4, Object & a5);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor. (disabled)
|
||||
*/
|
||||
Routine(const Routine &);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator. (disabled)
|
||||
*/
|
||||
Routine & operator = (const Routine &);
|
||||
|
||||
private:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Number of iterations before self destruct.
|
||||
*/
|
||||
Iterate m_Iterations;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Interval between calls.
|
||||
*/
|
||||
Interval m_Interval;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Number of arguments to forward.
|
||||
*/
|
||||
Uint8 m_Arguments;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Whether calls should be ignored.
|
||||
*/
|
||||
bool m_Suspended;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Whether the routine was terminated.
|
||||
*/
|
||||
bool m_Terminated;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* The callback to be executed when triggered.
|
||||
*/
|
||||
Function m_Callback;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* User tag associated with this instance.
|
||||
*/
|
||||
String m_Tag;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* User data associated with this instance.
|
||||
*/
|
||||
Object m_Data;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Arguments to be forwarded to the callback.
|
||||
*/
|
||||
Object m_Arg1, m_Arg2, m_Arg3, m_Arg4, m_Arg5, m_Arg6, m_Arg7,
|
||||
m_Arg8, m_Arg9, m_Arg10, m_Arg11, m_Arg12, m_Arg13, m_Arg14;
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
@ -289,6 +352,41 @@ public:
|
||||
*/
|
||||
CSStr ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to retrieve the name from instances of this type.
|
||||
*/
|
||||
static SQInteger Typename(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated user tag.
|
||||
*/
|
||||
const String & GetTag() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated user tag.
|
||||
*/
|
||||
void SetTag(CSStr tag);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the associated user data.
|
||||
*/
|
||||
Object & GetData();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated user data.
|
||||
*/
|
||||
void SetData(Object & data);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated user tag and allow chaining of operations.
|
||||
*/
|
||||
Routine & ApplyTag(CSStr tag);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify the associated user data and allow chaining of operations.
|
||||
*/
|
||||
Routine & ApplyData(Object & data);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Terminate this routine by releasing all resources and scheduling it for detachment.
|
||||
*/
|
||||
@ -297,7 +395,7 @@ public:
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Modify an explicit value to be passed as the specified argument.
|
||||
*/
|
||||
void SetArg(Uint8 num, Object & val);
|
||||
Routine & SetArg(Uint8 num, Object & val);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Retrieve the value that is passed as the specified argument.
|
||||
@ -385,6 +483,59 @@ protected:
|
||||
* Execute the binded callback.
|
||||
*/
|
||||
void Execute();
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Create a routine with just an interval.
|
||||
*/
|
||||
static Object Create(Object & env, Function & func, Interval interval);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Create a routine with just an interval and explicit iterations.
|
||||
*/
|
||||
static Object Create(Object & env, Function & func, Interval interval, Iterate iterations);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Create a routine with just an interval, explicit iterations and arguments.
|
||||
*/
|
||||
static Object Create(Object & env, Function & func, Interval interval, Iterate iterations
|
||||
, Object & a1);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Create a routine with just an interval, explicit iterations and arguments.
|
||||
*/
|
||||
static Object Create(Object & env, Function & func, Interval interval, Iterate iterations
|
||||
, Object & a1, Object & a2);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Create a routine with just an interval, explicit iterations and arguments.
|
||||
*/
|
||||
static Object Create(Object & env, Function & func, Interval interval, Iterate iterations
|
||||
, Object & a1, Object & a2, Object & a3);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Create a routine with just an interval, explicit iterations and arguments.
|
||||
*/
|
||||
static Object Create(Object & env, Function & func, Interval interval, Iterate iterations
|
||||
, Object & a1, Object & a2, Object & a3, Object & a4);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Create a routine with just an interval, explicit iterations and arguments.
|
||||
*/
|
||||
static Object Create(Object & env, Function & func, Interval interval, Iterate iterations
|
||||
, Object & a1, Object & a2, Object & a3, Object & a4, Object & a5);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Return the number of known routines.
|
||||
*/
|
||||
static Uint32 Count();
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Attempt to find a certain routine by its associated tag.
|
||||
*/
|
||||
static Object FindByTag(CSStr tag);
|
||||
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
Loading…
Reference in New Issue
Block a user