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

Don't clear entity containers untill after the virtual machine was closed. Should close #22

This commit is contained in:
Sandu Liviu Catalin 2016-07-16 15:45:36 +03:00
parent 7fe7116df4
commit e32464b6ea
4 changed files with 260 additions and 35 deletions

View File

@ -87,6 +87,37 @@ public:
}
};
/* ------------------------------------------------------------------------------------------------
* Implements RAII to make sure that entity containers area cleaned up at all costs.
*/
template < typename T > class ContainerCleaner
{
// --------------------------------------------------------------------------------------------
const EntityType m_Type; // The type of entity container to clear.
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
ContainerCleaner(T & container, EntityType type)
: m_Type(type)
{
for (auto & ent : container)
{
ent.Destroy();
}
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~ContainerCleaner()
{
Core::Get().ClearContainer(m_Type);
}
};
// ------------------------------------------------------------------------------------------------
Core Core::s_Inst;
@ -413,14 +444,16 @@ void Core::Terminate()
// Tell modules to do their monkey business
_Func->SendPluginCommand(0xDEADC0DE, "");
}
LogDbg("Clearing the entity containers");
// Release all entity resources by clearing the containers
m_Players.clear();
m_Vehicles.clear();
m_Objects.clear();
m_Pickups.clear();
m_Checkpoints.clear();
m_Blips.clear();
m_Keybinds.clear();
ContainerCleaner< Players > cc_players(m_Players, ENT_PLAYER);
ContainerCleaner< Vehicles > cc_vehicles(m_Vehicles, ENT_VEHICLE);
ContainerCleaner< Objects > cc_objects(m_Objects, ENT_OBJECT);
ContainerCleaner< Pickups > cc_pickups(m_Pickups, ENT_PICKUP);
ContainerCleaner< Checkpoints > cc_checkpoints(m_Checkpoints, ENT_CHECKPOINT);
ContainerCleaner< Blips > cc_blips(m_Blips, ENT_BLIP);
ContainerCleaner< Keybinds > cc_keybinds(m_Keybinds, ENT_KEYBIND);
LogDbg("Terminating routines an commands");
// Release all resources from routines
TerminateRoutines();
// Release all resources from command managers
@ -435,6 +468,7 @@ void Core::Terminate()
// Is there a VM to close?
if (m_VM)
{
LogDbg("Closing the virtual machine");
// Release all script callbacks
ResetFunc();
// Release the script instances
@ -451,6 +485,8 @@ void Core::Terminate()
// Tell modules to do their monkey business
_Func->SendPluginCommand(0xDEADBEAF, "");
}
LogDbg("Squirrel plugin was successfully terminated");
}
// ------------------------------------------------------------------------------------------------
@ -688,7 +724,7 @@ void Core::BindEvent(Int32 id, Object & env, Function & func)
}
// ------------------------------------------------------------------------------------------------
Core::BlipInst::~BlipInst()
void Core::BlipInst::Destroy()
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
@ -711,12 +747,14 @@ Core::BlipInst::~BlipInst()
// Now attempt to destroy this entity from the server
_Func->DestroyCoordBlip(mID);
}
// Don't release the callbacks abruptly in destructor
// Reset the instance to it's initial state
ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}
// ------------------------------------------------------------------------------------------------
Core::CheckpointInst::~CheckpointInst()
void Core::CheckpointInst::Destroy()
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
@ -739,12 +777,14 @@ Core::CheckpointInst::~CheckpointInst()
// Now attempt to destroy this entity from the server
_Func->DeleteCheckPoint(mID);
}
// Don't release the callbacks abruptly in destructor
// Reset the instance to it's initial state
ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}
// ------------------------------------------------------------------------------------------------
Core::KeybindInst::~KeybindInst()
void Core::KeybindInst::Destroy()
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
@ -767,12 +807,14 @@ Core::KeybindInst::~KeybindInst()
// Now attempt to destroy this entity from the server
_Func->RemoveKeyBind(mID);
}
// Don't release the callbacks abruptly in destructor
// Reset the instance to it's initial state
ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}
// ------------------------------------------------------------------------------------------------
Core::ObjectInst::~ObjectInst()
void Core::ObjectInst::Destroy()
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
@ -795,12 +837,14 @@ Core::ObjectInst::~ObjectInst()
// Now attempt to destroy this entity from the server
_Func->DeleteObject(mID);
}
// Don't release the callbacks abruptly in destructor
// Reset the instance to it's initial state
ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}
// ------------------------------------------------------------------------------------------------
Core::PickupInst::~PickupInst()
void Core::PickupInst::Destroy()
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
@ -823,12 +867,14 @@ Core::PickupInst::~PickupInst()
// Now attempt to destroy this entity from the server
_Func->DeletePickup(mID);
}
// Don't release the callbacks abruptly in destructor
// Reset the instance to it's initial state
ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}
// ------------------------------------------------------------------------------------------------
Core::PlayerInst::~PlayerInst()
void Core::PlayerInst::Destroy()
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
@ -845,12 +891,14 @@ Core::PlayerInst::~PlayerInst()
// Release the used memory buffer
mInst->m_Buffer.ResetAll();
}
// Don't release the callbacks abruptly in destructor
// Reset the instance to it's initial state
ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}
// ------------------------------------------------------------------------------------------------
Core::VehicleInst::~VehicleInst()
void Core::VehicleInst::Destroy()
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
@ -873,7 +921,9 @@ Core::VehicleInst::~VehicleInst()
// Now attempt to destroy this entity from the server
_Func->DeleteVehicle(mID);
}
// Don't release the callbacks abruptly in destructor
// Reset the instance to it's initial state
ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}

View File

@ -15,6 +15,11 @@
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Forward declarations.
*/
template < typename T > class ContainerCleaner;
/* ------------------------------------------------------------------------------------------------
* Circular locks employed by the central core.
*/
@ -29,6 +34,9 @@ enum CoreCircularLocks
*/
class Core
{
// --------------------------------------------------------------------------------------------
template < typename T > friend class ContainerCleaner;
private:
// --------------------------------------------------------------------------------------------
@ -71,10 +79,29 @@ protected:
*/
struct BlipInst
{
/* ----------------------------------------------------------------------------------------
* Default constructor.
*/
BlipInst() : mID(-1), mFlags(ENF_DEFAULT), mInst(nullptr)
{ /* ... */ }
{
Core::Get().ResetInst(*this);
}
~BlipInst();
/* ----------------------------------------------------------------------------------------
* Destructor.
*/
~BlipInst()
{
if (VALID_ENTITY(mID))
{
Destroy();
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy();
// ----------------------------------------------------------------------------------------
Int32 mID;
@ -103,10 +130,29 @@ protected:
*/
struct CheckpointInst
{
/* ----------------------------------------------------------------------------------------
* Default constructor.
*/
CheckpointInst() : mID(-1), mFlags(ENF_DEFAULT), mInst(nullptr)
{ /* ... */ }
{
Core::Get().ResetInst(*this);
}
~CheckpointInst();
/* ----------------------------------------------------------------------------------------
* Destructor.
*/
~CheckpointInst()
{
if (VALID_ENTITY(mID))
{
Destroy();
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy();
// ----------------------------------------------------------------------------------------
Int32 mID;
@ -127,10 +173,29 @@ protected:
*/
struct KeybindInst
{
/* ----------------------------------------------------------------------------------------
* Default constructor.
*/
KeybindInst() : mID(-1), mFlags(ENF_DEFAULT), mInst(nullptr)
{ /* ... */ }
{
Core::Get().ResetInst(*this);
}
~KeybindInst();
/* ----------------------------------------------------------------------------------------
* Destructor.
*/
~KeybindInst()
{
if (VALID_ENTITY(mID))
{
Destroy();
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy();
// ----------------------------------------------------------------------------------------
Int32 mID;
@ -158,10 +223,29 @@ protected:
*/
struct ObjectInst
{
/* ----------------------------------------------------------------------------------------
* Default constructor.
*/
ObjectInst() : mID(-1), mFlags(ENF_DEFAULT), mInst(nullptr)
{ /* ... */ }
{
Core::Get().ResetInst(*this);
}
~ObjectInst();
/* ----------------------------------------------------------------------------------------
* Destructor.
*/
~ObjectInst()
{
if (VALID_ENTITY(mID))
{
Destroy();
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy();
// ----------------------------------------------------------------------------------------
Int32 mID;
@ -183,10 +267,29 @@ protected:
*/
struct PickupInst
{
/* ----------------------------------------------------------------------------------------
* Default constructor.
*/
PickupInst() : mID(-1), mFlags(ENF_DEFAULT), mInst(nullptr)
{ /* ... */ }
{
Core::Get().ResetInst(*this);
}
~PickupInst();
/* ----------------------------------------------------------------------------------------
* Destructor.
*/
~PickupInst()
{
if (VALID_ENTITY(mID))
{
Destroy();
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy();
// ----------------------------------------------------------------------------------------
Int32 mID;
@ -209,10 +312,29 @@ protected:
*/
struct PlayerInst
{
/* ----------------------------------------------------------------------------------------
* Default constructor.
*/
PlayerInst() : mID(-1), mFlags(ENF_DEFAULT), mInst(nullptr)
{ /* ... */ }
{
Core::Get().ResetInst(*this);
}
~PlayerInst();
/* ----------------------------------------------------------------------------------------
* Destructor.
*/
~PlayerInst()
{
if (VALID_ENTITY(mID))
{
Destroy();
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy();
// ----------------------------------------------------------------------------------------
Int32 mID;
@ -310,10 +432,29 @@ protected:
*/
struct VehicleInst
{
/* ----------------------------------------------------------------------------------------
* Default constructor.
*/
VehicleInst() : mID(-1), mFlags(ENF_DEFAULT), mInst(nullptr)
{ /* ... */ }
{
Core::Get().ResetInst(*this);
}
~VehicleInst();
/* ----------------------------------------------------------------------------------------
* Destructor.
*/
~VehicleInst()
{
if (VALID_ENTITY(mID))
{
Destroy();
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy();
// ----------------------------------------------------------------------------------------
Int32 mID;
@ -667,6 +808,24 @@ public:
protected:
/* --------------------------------------------------------------------------------------------
* Container cleaner.
*/
void ClearContainer(EntityType type)
{
switch (type)
{
case ENT_BLIP: m_Blips.clear(); break;
case ENT_CHECKPOINT: m_Blips.clear(); break;
case ENT_KEYBIND: m_Blips.clear(); break;
case ENT_OBJECT: m_Blips.clear(); break;
case ENT_PICKUP: m_Blips.clear(); break;
case ENT_PLAYER: m_Blips.clear(); break;
case ENT_VEHICLE: m_Blips.clear(); break;
default: STHROWF("Cannot clear unknown entity type container");
}
}
/* --------------------------------------------------------------------------------------------
* Instance cleaners.
*/

View File

@ -224,6 +224,7 @@ static void OnPlayerDisconnect(int32_t player_id, vcmpDisconnectReason reason)
// Attempt to forward the event
try
{
printf("Disconnecting... %d\n", player_id);
Core::Get().DisconnectPlayer(player_id, reason, NullObject());
}
SQMOD_CATCH_EVENT_EXCEPTION(OnPlayerDisconnect)

View File

@ -394,6 +394,21 @@ enum EntityFlags
ENF_LOCKED = (2 << 1)
};
/* ------------------------------------------------------------------------------------------------
* Used to identify entity types.
*/
enum EntityType
{
ENT_UNKNOWN = 0,
ENT_BLIP,
ENT_CHECKPOINT,
ENT_KEYBIND,
ENT_OBJECT,
ENT_PICKUP,
ENT_PLAYER,
ENT_VEHICLE
};
} // Namespace:: SqMod
/* ------------------------------------------------------------------------------------------------