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

Revise the entity clean up to fix crash at server shutdown, remove duplicate code and overall make the code more reliable.

Various other minor changes surrounding the entity destruction from the server.
This commit is contained in:
Sandu Liviu Catalin 2016-07-16 19:39:51 +03:00
parent 88765b80c0
commit 1229e7f59f
4 changed files with 162 additions and 345 deletions

View File

@ -90,22 +90,22 @@ public:
/* ------------------------------------------------------------------------------------------------
* Implements RAII to make sure that entity containers area cleaned up at all costs.
*/
template < typename T > class ContainerCleaner
class ContainerCleaner
{
// --------------------------------------------------------------------------------------------
const EntityType m_Type; // The type of entity container to clear.
EntityType m_Type; // The type of entity container to clear.
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
ContainerCleaner(T & container, EntityType type, bool shutdown)
template < typename T > ContainerCleaner(T & container, EntityType type, bool destroy)
: m_Type(type)
{
for (auto & ent : container)
{
ent.Destroy(shutdown);
ent.Destroy(destroy, SQMOD_DESTROY_CLEANUP, NullObject());
}
}
@ -141,6 +141,7 @@ Core::Core()
, m_IncomingNameCapacity(0)
, m_Debugging(false)
, m_Executed(false)
, m_Shutdown(false)
{
/* ... */
}
@ -173,16 +174,18 @@ bool Core::Initialize()
switch (ini_ret)
{
case SI_FAIL:
{
OutputError("Failed to load the configuration file. Probably invalid");
break;
} break;
case SI_NOMEM:
{
OutputError("Run out of memory while loading the configuration file");
break;
} break;
case SI_FILE:
{
OutputError("Failed to load the configuration file. %s", std::strerror(errno));
break;
default:
OutputError("Failed to load the configuration file for some unforeseen reason");
} break;
default: OutputError("Failed to load the configuration file for some unforeseen reason");
}
// Failed to load the configuration file
return false;
@ -438,6 +441,8 @@ bool Core::Execute()
// ------------------------------------------------------------------------------------------------
void Core::Terminate(bool shutdown)
{
m_Shutdown = shutdown;
// Is there a virtual machine present?
if (m_VM)
{
LogDbg("Signaling outside plug-ins to release their resources");
@ -446,13 +451,13 @@ void Core::Terminate(bool shutdown)
}
LogDbg("Clearing the entity containers");
// Release all entity resources by clearing the containers
const ContainerCleaner< Players > cc_players(m_Players, ENT_PLAYER, shutdown);
const ContainerCleaner< Vehicles > cc_vehicles(m_Vehicles, ENT_VEHICLE, shutdown);
const ContainerCleaner< Objects > cc_objects(m_Objects, ENT_OBJECT, shutdown);
const ContainerCleaner< Pickups > cc_pickups(m_Pickups, ENT_PICKUP, shutdown);
const ContainerCleaner< Checkpoints > cc_checkpoints(m_Checkpoints, ENT_CHECKPOINT, shutdown);
const ContainerCleaner< Blips > cc_blips(m_Blips, ENT_BLIP, shutdown);
const ContainerCleaner< Keybinds > cc_keybinds(m_Keybinds, ENT_KEYBIND, shutdown);
const ContainerCleaner cc_players(m_Players, ENT_PLAYER, !shutdown);
const ContainerCleaner cc_vehicles(m_Vehicles, ENT_VEHICLE, !shutdown);
const ContainerCleaner cc_objects(m_Objects, ENT_OBJECT, !shutdown);
const ContainerCleaner cc_pickups(m_Pickups, ENT_PICKUP, !shutdown);
const ContainerCleaner cc_checkpoints(m_Checkpoints, ENT_CHECKPOINT, !shutdown);
const ContainerCleaner cc_blips(m_Blips, ENT_BLIP, !shutdown);
const ContainerCleaner cc_keybinds(m_Keybinds, ENT_KEYBIND, !shutdown);
LogDbg("Terminating routines an commands");
// Release all resources from routines
TerminateRoutines();
@ -724,12 +729,12 @@ void Core::BindEvent(Int32 id, Object & env, Function & func)
}
// ------------------------------------------------------------------------------------------------
void Core::BlipInst::Destroy(bool shutdown)
void Core::BlipInst::Destroy(bool destroy, Int32 header, Object & payload)
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
{
Core::Get().EmitBlipDestroyed(mID, SQMOD_DESTROY_CLEANUP, NullObject());
Core::Get().EmitBlipDestroyed(mID, header, payload);
}
// Is there a manager instance associated with this entity?
if (mInst)
@ -739,8 +744,12 @@ void Core::BlipInst::Destroy(bool shutdown)
// Release user data to avoid dangling or circular references
mInst->m_Data.Release();
}
// Prevent further use of the manager instance
mInst = nullptr;
// Release the script object, if any
mObj.Release();
// Are we supposed to clean up this entity? (only at reload)
if (!shutdown && VALID_ENTITY(mID) && (mFlags & ENF_OWNED))
if (destroy && VALID_ENTITY(mID) && (mFlags & ENF_OWNED))
{
// Block the entity pool changes notification from triggering the destroy event
const BitGuardU16 bg(mFlags, static_cast< Uint16 >(ENF_LOCKED));
@ -748,18 +757,18 @@ void Core::BlipInst::Destroy(bool shutdown)
_Func->DestroyCoordBlip(mID);
}
// Reset the instance to it's initial state
ResetInst(*this);
Core::ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}
// ------------------------------------------------------------------------------------------------
void Core::CheckpointInst::Destroy(bool shutdown)
void Core::CheckpointInst::Destroy(bool destroy, Int32 header, Object & payload)
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
{
Core::Get().EmitCheckpointDestroyed(mID, SQMOD_DESTROY_CLEANUP, NullObject());
Core::Get().EmitCheckpointDestroyed(mID, header, payload);
}
// Is there a manager instance associated with this entity?
if (mInst)
@ -769,8 +778,12 @@ void Core::CheckpointInst::Destroy(bool shutdown)
// Release user data to avoid dangling or circular references
mInst->m_Data.Release();
}
// Prevent further use of the manager instance
mInst = nullptr;
// Release the script object, if any
mObj.Release();
// Are we supposed to clean up this entity? (only at reload)
if (!shutdown && VALID_ENTITY(mID) && (mFlags & ENF_OWNED))
if (destroy && VALID_ENTITY(mID) && (mFlags & ENF_OWNED))
{
// Block the entity pool changes notification from triggering the destroy event
const BitGuardU16 bg(mFlags, static_cast< Uint16 >(ENF_LOCKED));
@ -778,18 +791,18 @@ void Core::CheckpointInst::Destroy(bool shutdown)
_Func->DeleteCheckPoint(mID);
}
// Reset the instance to it's initial state
ResetInst(*this);
Core::ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}
// ------------------------------------------------------------------------------------------------
void Core::KeybindInst::Destroy(bool shutdown)
void Core::KeybindInst::Destroy(bool destroy, Int32 header, Object & payload)
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
{
Core::Get().EmitKeybindDestroyed(mID, SQMOD_DESTROY_CLEANUP, NullObject());
Core::Get().EmitKeybindDestroyed(mID, header, payload);
}
// Is there a manager instance associated with this entity?
if (mInst)
@ -799,8 +812,12 @@ void Core::KeybindInst::Destroy(bool shutdown)
// Release user data to avoid dangling or circular references
mInst->m_Data.Release();
}
// Prevent further use of the manager instance
mInst = nullptr;
// Release the script object, if any
mObj.Release();
// Are we supposed to clean up this entity? (only at reload)
if (!shutdown && VALID_ENTITY(mID) && (mFlags & ENF_OWNED))
if (destroy && VALID_ENTITY(mID) && (mFlags & ENF_OWNED))
{
// Block the entity pool changes notification from triggering the destroy event
const BitGuardU16 bg(mFlags, static_cast< Uint16 >(ENF_LOCKED));
@ -808,18 +825,18 @@ void Core::KeybindInst::Destroy(bool shutdown)
_Func->RemoveKeyBind(mID);
}
// Reset the instance to it's initial state
ResetInst(*this);
Core::ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}
// ------------------------------------------------------------------------------------------------
void Core::ObjectInst::Destroy(bool shutdown)
void Core::ObjectInst::Destroy(bool destroy, Int32 header, Object & payload)
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
{
Core::Get().EmitObjectDestroyed(mID, SQMOD_DESTROY_CLEANUP, NullObject());
Core::Get().EmitObjectDestroyed(mID, header, payload);
}
// Is there a manager instance associated with this entity?
if (mInst)
@ -829,8 +846,12 @@ void Core::ObjectInst::Destroy(bool shutdown)
// Release user data to avoid dangling or circular references
mInst->m_Data.Release();
}
// Prevent further use of the manager instance
mInst = nullptr;
// Release the script object, if any
mObj.Release();
// Are we supposed to clean up this entity? (only at reload)
if (!shutdown && VALID_ENTITY(mID) && (mFlags & ENF_OWNED))
if (destroy && VALID_ENTITY(mID) && (mFlags & ENF_OWNED))
{
// Block the entity pool changes notification from triggering the destroy event
const BitGuardU16 bg(mFlags, static_cast< Uint16 >(ENF_LOCKED));
@ -838,18 +859,18 @@ void Core::ObjectInst::Destroy(bool shutdown)
_Func->DeleteObject(mID);
}
// Reset the instance to it's initial state
ResetInst(*this);
Core::ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}
// ------------------------------------------------------------------------------------------------
void Core::PickupInst::Destroy(bool shutdown)
void Core::PickupInst::Destroy(bool destroy, Int32 header, Object & payload)
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
{
Core::Get().EmitPickupDestroyed(mID, SQMOD_DESTROY_CLEANUP, NullObject());
Core::Get().EmitPickupDestroyed(mID, header, payload);
}
// Is there a manager instance associated with this entity?
if (mInst)
@ -859,8 +880,12 @@ void Core::PickupInst::Destroy(bool shutdown)
// Release user data to avoid dangling or circular references
mInst->m_Data.Release();
}
// Prevent further use of the manager instance
mInst = nullptr;
// Release the script object, if any
mObj.Release();
// Are we supposed to clean up this entity? (only at reload)
if (!shutdown && VALID_ENTITY(mID) && (mFlags & ENF_OWNED))
if (destroy && VALID_ENTITY(mID) && (mFlags & ENF_OWNED))
{
// Block the entity pool changes notification from triggering the destroy event
const BitGuardU16 bg(mFlags, static_cast< Uint16 >(ENF_LOCKED));
@ -868,18 +893,18 @@ void Core::PickupInst::Destroy(bool shutdown)
_Func->DeletePickup(mID);
}
// Reset the instance to it's initial state
ResetInst(*this);
Core::ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}
// ------------------------------------------------------------------------------------------------
void Core::PlayerInst::Destroy(bool /*shutdown*/)
void Core::PlayerInst::Destroy(bool /*destroy*/, Int32 header, Object & payload)
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
{
Core::Get().EmitPlayerDestroyed(mID, SQMOD_DESTROY_CLEANUP, NullObject());
Core::Get().EmitPlayerDestroyed(mID, header, payload);
}
// Is there a manager instance associated with this entity?
if (mInst)
@ -891,19 +916,23 @@ void Core::PlayerInst::Destroy(bool /*shutdown*/)
// Release the used memory buffer
mInst->m_Buffer.ResetAll();
}
// Prevent further use of the manager instance
mInst = nullptr;
// Release the script object, if any
mObj.Release();
// Reset the instance to it's initial state
ResetInst(*this);
Core::ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}
// ------------------------------------------------------------------------------------------------
void Core::VehicleInst::Destroy(bool shutdown)
void Core::VehicleInst::Destroy(bool destroy, Int32 header, Object & payload)
{
// Should we notify that this entity is being cleaned up?
if (VALID_ENTITY(mID))
{
Core::Get().EmitVehicleDestroyed(mID, SQMOD_DESTROY_CLEANUP, NullObject());
Core::Get().EmitVehicleDestroyed(mID, header, payload);
}
// Is there a manager instance associated with this entity?
if (mInst)
@ -913,8 +942,12 @@ void Core::VehicleInst::Destroy(bool shutdown)
// Release user data to avoid dangling or circular references
mInst->m_Data.Release();
}
// Prevent further use of the manager instance
mInst = nullptr;
// Release the script object, if any
mObj.Release();
// Are we supposed to clean up this entity? (only at reload)
if (!shutdown && VALID_ENTITY(mID) && (mFlags & ENF_OWNED))
if (destroy && VALID_ENTITY(mID) && (mFlags & ENF_OWNED))
{
// Block the entity pool changes notification from triggering the destroy event
const BitGuardU16 bg(mFlags, static_cast< Uint16 >(ENF_LOCKED));
@ -922,7 +955,7 @@ void Core::VehicleInst::Destroy(bool shutdown)
_Func->DeleteVehicle(mID);
}
// Reset the instance to it's initial state
ResetInst(*this);
Core::ResetInst(*this);
// Don't release the callbacks abruptly
Core::ResetFunc(*this);
}

View File

@ -15,11 +15,6 @@
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Forward declarations.
*/
template < typename T > class ContainerCleaner;
/* ------------------------------------------------------------------------------------------------
* Circular locks employed by the central core.
*/
@ -34,9 +29,6 @@ enum CoreCircularLocks
*/
class Core
{
// --------------------------------------------------------------------------------------------
template < typename T > friend class ContainerCleaner;
private:
// --------------------------------------------------------------------------------------------
@ -94,14 +86,14 @@ protected:
{
if (VALID_ENTITY(mID))
{
Destroy();
Destroy(!Core::Get().ShuttingDown(), SQMOD_DESTROY_CLEANUP, NullObject());
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy(bool shutdown = false);
void Destroy(bool destroy, Int32 header, Object & payload);
// ----------------------------------------------------------------------------------------
Int32 mID; // The unique number that identifies this entity on the server.
@ -145,14 +137,14 @@ protected:
{
if (VALID_ENTITY(mID))
{
Destroy();
Destroy(!Core::Get().ShuttingDown(), SQMOD_DESTROY_CLEANUP, NullObject());
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy(bool shutdown = false);
void Destroy(bool destroy, Int32 header, Object & payload);
// ----------------------------------------------------------------------------------------
Int32 mID; // The unique number that identifies this entity on the server.
@ -189,14 +181,14 @@ protected:
{
if (VALID_ENTITY(mID))
{
Destroy();
Destroy(!Core::Get().ShuttingDown(), SQMOD_DESTROY_CLEANUP, NullObject());
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy(bool shutdown = false);
void Destroy(bool destroy, Int32 header, Object & payload);
// ----------------------------------------------------------------------------------------
Int32 mID; // The unique number that identifies this entity on the server.
@ -239,14 +231,14 @@ protected:
{
if (VALID_ENTITY(mID))
{
Destroy();
Destroy(!Core::Get().ShuttingDown(), SQMOD_DESTROY_CLEANUP, NullObject());
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy(bool shutdown = false);
void Destroy(bool destroy, Int32 header, Object & payload);
// ----------------------------------------------------------------------------------------
Int32 mID; // The unique number that identifies this entity on the server.
@ -283,14 +275,14 @@ protected:
{
if (VALID_ENTITY(mID))
{
Destroy();
Destroy(!Core::Get().ShuttingDown(), SQMOD_DESTROY_CLEANUP, NullObject());
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy(bool shutdown = false);
void Destroy(bool destroy, Int32 header, Object & payload);
// ----------------------------------------------------------------------------------------
Int32 mID; // The unique number that identifies this entity on the server.
@ -328,14 +320,14 @@ protected:
{
if (VALID_ENTITY(mID))
{
Destroy();
Destroy(false, SQMOD_DESTROY_CLEANUP, NullObject());
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy(bool shutdown = false);
void Destroy(bool destroy, Int32 header, Object & payload);
// ----------------------------------------------------------------------------------------
Int32 mID; // The unique number that identifies this entity on the server.
@ -448,14 +440,14 @@ protected:
{
if (VALID_ENTITY(mID))
{
Destroy();
Destroy(!Core::Get().ShuttingDown(), SQMOD_DESTROY_CLEANUP, NullObject());
}
}
/* ----------------------------------------------------------------------------------------
* Destroy the entity instance from the server, if necessary.
*/
void Destroy(bool shutdown = false);
void Destroy(bool destroy, Int32 header, Object & payload);
// ----------------------------------------------------------------------------------------
Int32 mID; // The unique number that identifies this entity on the server.
@ -540,6 +532,7 @@ private:
// --------------------------------------------------------------------------------------------
bool m_Debugging; // Enable debugging features, if any.
bool m_Executed; // Whether the scripts were executed.
bool m_Shutdown; // Whether the server currently shutting down.
public:
@ -603,6 +596,14 @@ public:
return m_Executed;
}
/* --------------------------------------------------------------------------------------------
* See whether the server is currently in the process of shutting down.
*/
bool ShuttingDown() const
{
return m_Shutdown;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the value of the specified option.
*/
@ -807,46 +808,12 @@ public:
const Players & GetPlayers() const { return m_Players; }
const Vehicles & GetVehicles() const { return m_Vehicles; }
protected:
/* --------------------------------------------------------------------------------------------
* Container cleaner.
*/
void ClearContainer(EntityType type)
{
switch (type)
{
case ENT_BLIP:
{
m_Blips.clear();
} break;
case ENT_CHECKPOINT:
{
m_Checkpoints.clear();
} break;
case ENT_KEYBIND:
{
m_Keybinds.clear();
} break;
case ENT_OBJECT:
{
m_Objects.clear();
} break;
case ENT_PICKUP:
{
m_Pickups.clear();
} break;
case ENT_PLAYER:
{
m_Players.clear();
} break;
case ENT_VEHICLE:
{
m_Vehicles.clear();
} break;
default: STHROWF("Cannot clear unknown entity type container");
}
}
void ClearContainer(EntityType type);
protected:
/* --------------------------------------------------------------------------------------------
* Instance cleaners.

View File

@ -396,43 +396,11 @@ void Core::DeallocBlip(Int32 id, bool destroy, Int32 header, Object & payload)
}
// Retrieve the specified entity instance
BlipInst & inst = m_Blips[id];
// Make sure that the instance is even allocated
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
// Make sure that the instance is even allocated and we are allowed to destroy it
if (VALID_ENTITY(inst.mID) && !(inst.mFlags & ENF_LOCKED))
{
return; // Nothing to deallocate!
inst.Destroy(destroy, header, payload); // Now attempt to destroy the entity from the server
}
// Prevent further attempts to delete this entity
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
// Let the script callbacks know this entity should no longer be used
try
{
EmitBlipDestroyed(id, header, payload);
}
catch (...)
{
// The error was probably dealt with already
}
// Is there a manager instance associated with this entity?
if (inst.mInst)
{
// Prevent further use of this entity
inst.mInst->m_ID = -1;
// Release user data to avoid dangling or circular references
inst.mInst->m_Data.Release();
}
// Should we delete this entity from the server as well?
if (destroy || (inst.mFlags & ENF_OWNED))
{
_Func->DestroyCoordBlip(inst.mID);
}
// Reset the entity instance
ResetInst(inst);
// Release associated script callbacks
ResetFunc(inst);
// Prevent further use of the manager instance
inst.mInst = nullptr;
// Release the script object, if any
inst.mObj.Release();
}
// --------------------------------------------------------------------------------------------
@ -445,43 +413,11 @@ void Core::DeallocCheckpoint(Int32 id, bool destroy, Int32 header, Object & payl
}
// Retrieve the specified entity instance
CheckpointInst & inst = m_Checkpoints[id];
// Make sure that the instance is even allocated
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
// Make sure that the instance is even allocated and we are allowed to destroy it
if (VALID_ENTITY(inst.mID) && !(inst.mFlags & ENF_LOCKED))
{
return; // Nothing to deallocate!
inst.Destroy(destroy, header, payload); // Now attempt to destroy the entity from the server
}
// Prevent further attempts to delete this entity
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
// Let the script callbacks know this entity should no longer be used
try
{
EmitCheckpointDestroyed(id, header, payload);
}
catch (...)
{
// The error was probably dealt with already
}
// Is there a manager instance associated with this entity?
if (inst.mInst)
{
// Prevent further use of this entity
inst.mInst->m_ID = -1;
// Release user data to avoid dangling or circular references
inst.mInst->m_Data.Release();
}
// Should we delete this entity from the server as well?
if (destroy || (inst.mFlags & ENF_OWNED))
{
_Func->DeleteCheckPoint(inst.mID);
}
// Reset the entity instance
ResetInst(inst);
// Release associated script callbacks
ResetFunc(inst);
// Prevent further use of the manager instance
inst.mInst = nullptr;
// Release the script object, if any
inst.mObj.Release();
}
// --------------------------------------------------------------------------------------------
@ -494,43 +430,11 @@ void Core::DeallocKeybind(Int32 id, bool destroy, Int32 header, Object & payload
}
// Retrieve the specified entity instance
KeybindInst & inst = m_Keybinds[id];
// Make sure that the instance is even allocated
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
// Make sure that the instance is even allocated and we are allowed to destroy it
if (VALID_ENTITY(inst.mID) && !(inst.mFlags & ENF_LOCKED))
{
return; // Nothing to deallocate!
inst.Destroy(destroy, header, payload); // Now attempt to destroy the entity from the server
}
// Prevent further attempts to delete this entity
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
// Let the script callbacks know this entity should no longer be used
try
{
EmitBlipDestroyed(id, header, payload);
}
catch (...)
{
// The error was dealt with already
}
// Is there a manager instance associated with this entity?
if (inst.mInst)
{
// Prevent further use of this entity
inst.mInst->m_ID = -1;
// Release user data to avoid dangling or circular references
inst.mInst->m_Data.Release();
}
// Should we delete this entity from the server as well?
if (destroy || (inst.mFlags & ENF_OWNED))
{
_Func->RemoveKeyBind(inst.mID);
}
// Reset the entity instance
ResetInst(inst);
// Release associated script callbacks
ResetFunc(inst);
// Prevent further use of the manager instance
inst.mInst = nullptr;
// Release the script object, if any
inst.mObj.Release();
}
// --------------------------------------------------------------------------------------------
@ -543,43 +447,11 @@ void Core::DeallocObject(Int32 id, bool destroy, Int32 header, Object & payload)
}
// Retrieve the specified entity instance
ObjectInst & inst = m_Objects[id];
// Make sure that the instance is even allocated
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
// Make sure that the instance is even allocated and we are allowed to destroy it
if (VALID_ENTITY(inst.mID) && !(inst.mFlags & ENF_LOCKED))
{
return; // Nothing to deallocate!
inst.Destroy(destroy, header, payload); // Now attempt to destroy the entity from the server
}
// Prevent further attempts to delete this entity
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
// Let the script callbacks know this entity should no longer be used
try
{
EmitObjectDestroyed(id, header, payload);
}
catch (...)
{
// The error was probably dealt with already
}
// Is there a manager instance associated with this entity?
if (inst.mInst)
{
// Prevent further use of this entity
inst.mInst->m_ID = -1;
// Release user data to avoid dangling or circular references
inst.mInst->m_Data.Release();
}
// Should we delete this entity from the server as well?
if (destroy || (inst.mFlags & ENF_OWNED))
{
_Func->DeleteObject(inst.mID);
}
// Reset the entity instance
ResetInst(inst);
// Release associated script callbacks
ResetFunc(inst);
// Prevent further use of the manager instance
inst.mInst = nullptr;
// Release the script object, if any
inst.mObj.Release();
}
// --------------------------------------------------------------------------------------------
@ -592,43 +464,11 @@ void Core::DeallocPickup(Int32 id, bool destroy, Int32 header, Object & payload)
}
// Retrieve the specified entity instance
PickupInst & inst = m_Pickups[id];
// Make sure that the instance is even allocated
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
// Make sure that the instance is even allocated and we are allowed to destroy it
if (VALID_ENTITY(inst.mID) && !(inst.mFlags & ENF_LOCKED))
{
return; // Nothing to deallocate!
inst.Destroy(destroy, header, payload); // Now attempt to destroy the entity from the server
}
// Prevent further attempts to delete this entity
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
// Let the script callbacks know this entity should no longer be used
try
{
EmitPickupDestroyed(id, header, payload);
}
catch (...)
{
// The error was probably dealt with already
}
// Is there a manager instance associated with this entity?
if (inst.mInst)
{
// Prevent further use of this entity
inst.mInst->m_ID = -1;
// Release user data to avoid dangling or circular references
inst.mInst->m_Data.Release();
}
// Should we delete this entity from the server as well?
if (destroy || (inst.mFlags & ENF_OWNED))
{
_Func->DeletePickup(inst.mID);
}
// Reset the entity instance
ResetInst(inst);
// Release associated script callbacks
ResetFunc(inst);
// Prevent further use of the manager instance
inst.mInst = nullptr;
// Release the script object, if any
inst.mObj.Release();
}
// --------------------------------------------------------------------------------------------
@ -641,43 +481,11 @@ void Core::DeallocVehicle(Int32 id, bool destroy, Int32 header, Object & payload
}
// Retrieve the specified entity instance
VehicleInst & inst = m_Vehicles[id];
// Make sure that the instance is even allocated
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
// Make sure that the instance is even allocated and we are allowed to destroy it
if (VALID_ENTITY(inst.mID) && !(inst.mFlags & ENF_LOCKED))
{
return; // Nothing to deallocate!
inst.Destroy(destroy, header, payload); // Now attempt to destroy the entity from the server
}
// Prevent further attempts to delete this entity
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
// Let the script callbacks know this entity should no longer be used
try
{
EmitVehicleDestroyed(id, header, payload);
}
catch (...)
{
// The error was probably dealt with already
}
// Is there a manager instance associated with this entity?
if (inst.mInst)
{
// Prevent further use of this entity
inst.mInst->m_ID = -1;
// Release user data to avoid dangling or circular references
inst.mInst->m_Data.Release();
}
// Should we delete this entity from the server as well?
if (destroy || (inst.mFlags & ENF_OWNED))
{
_Func->DeleteVehicle(inst.mID);
}
// Reset the entity instance
ResetInst(inst);
// Release associated script callbacks
ResetFunc(inst);
// Prevent further use of the manager instance
inst.mInst = nullptr;
// Release the script object, if any
inst.mObj.Release();
}
// --------------------------------------------------------------------------------------------
@ -914,7 +722,7 @@ bool Core::DelVehicle(Int32 id, Int32 header, Object & payload)
return true;
}
// --------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------
void Core::ConnectPlayer(Int32 id, Int32 header, Object & payload)
{
// Make sure that the specified entity identifier is valid
@ -952,6 +760,7 @@ void Core::ConnectPlayer(Int32 id, Int32 header, Object & payload)
EmitPlayerCreated(id, header, payload);
}
// ------------------------------------------------------------------------------------------------
void Core::DisconnectPlayer(Int32 id, Int32 header, Object & payload)
{
// Make sure that the specified entity identifier is valid
@ -961,40 +770,11 @@ void Core::DisconnectPlayer(Int32 id, Int32 header, Object & payload)
}
// Retrieve the specified entity instance
PlayerInst & inst = m_Players[id];
// Make sure that the instance is even allocated and we're allowed to deallocate it
if (INVALID_ENTITY(inst.mID) || (inst.mFlags & ENF_LOCKED))
// Make sure that the instance is even allocated and we are allowed to destroy it
if (VALID_ENTITY(inst.mID) && !(inst.mFlags & ENF_LOCKED))
{
return; // Nothing to deallocate!
inst.Destroy(false, header, payload); // Now attempt to destroy the entity from the server
}
// Prevent further attempts to delete this entity
const BitGuardU16 bg(inst.mFlags, static_cast< Uint16 >(ENF_LOCKED));
// Let the script callbacks know this entity should no longer be used
try
{
EmitPlayerDestroyed(id, header, payload);
}
catch (...)
{
// The error was probably dealt with already
}
// Is there a manager instance associated with this entity?
if (inst.mInst)
{
// Prevent further use of this entity
inst.mInst->m_ID = -1;
// Release user data to avoid dangling or circular references
inst.mInst->m_Data.Release();
// Release the used memory buffer
inst.mInst->m_Buffer.ResetAll();
}
// Reset the entity instance
ResetInst(inst);
// Release associated script callbacks
ResetFunc(inst);
// Prevent further use of the manager instance
inst.mInst = nullptr;
// Release the script object, if any
inst.mObj.Release();
}
} // Namespace:: SqMod

View File

@ -4,6 +4,43 @@
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
void Core::ClearContainer(EntityType type)
{
switch (type)
{
case ENT_BLIP:
{
m_Blips.clear();
} break;
case ENT_CHECKPOINT:
{
m_Checkpoints.clear();
} break;
case ENT_KEYBIND:
{
m_Keybinds.clear();
} break;
case ENT_OBJECT:
{
m_Objects.clear();
} break;
case ENT_PICKUP:
{
m_Pickups.clear();
} break;
case ENT_PLAYER:
{
m_Players.clear();
} break;
case ENT_VEHICLE:
{
m_Vehicles.clear();
} break;
default: STHROWF("Cannot clear unknown entity type container");
}
}
// ------------------------------------------------------------------------------------------------
void Core::ResetInst(BlipInst & inst)
{