From 1d12ddd60d97a39498306e31a3faff6497ee09b0 Mon Sep 17 00:00:00 2001 From: Sandu Liviu Catalin Date: Tue, 21 Jun 2016 09:02:44 +0300 Subject: [PATCH] Improve searching for active entities. Also fix a possible crash because the entity instance pushed on the stack was appending to itself instead of the array. --- cbp/Module.cbp | 2 ++ source/Base/Algo.cpp | 8 ++++++++ source/Base/Algo.hpp | 29 +++++++++++++++++++++++++++++ source/Entity/Blip.cpp | 23 ++++++++++------------- source/Entity/Checkpoint.cpp | 23 ++++++++++------------- source/Entity/Keybind.cpp | 23 ++++++++++------------- source/Entity/Object.cpp | 23 ++++++++++------------- source/Entity/Pickup.cpp | 23 ++++++++++------------- source/Entity/Player.cpp | 23 ++++++++++------------- source/Entity/Vehicle.cpp | 23 ++++++++++------------- 10 files changed, 109 insertions(+), 91 deletions(-) create mode 100644 source/Base/Algo.cpp create mode 100644 source/Base/Algo.hpp diff --git a/cbp/Module.cbp b/cbp/Module.cbp index 7876310a..1ecd5e3a 100644 --- a/cbp/Module.cbp +++ b/cbp/Module.cbp @@ -437,6 +437,8 @@ + + diff --git a/source/Base/Algo.cpp b/source/Base/Algo.cpp new file mode 100644 index 00000000..3143e070 --- /dev/null +++ b/source/Base/Algo.cpp @@ -0,0 +1,8 @@ +// ------------------------------------------------------------------------------------------------ +#include "Base/Algo.hpp" + +// ------------------------------------------------------------------------------------------------ +namespace SqMod { + + +} // Namespace:: SqMod diff --git a/source/Base/Algo.hpp b/source/Base/Algo.hpp new file mode 100644 index 00000000..07e1ca04 --- /dev/null +++ b/source/Base/Algo.hpp @@ -0,0 +1,29 @@ +#ifndef _BASE_ALGO_HPP_ +#define _BASE_ALGO_HPP_ + +// ------------------------------------------------------------------------------------------------ +#include + +// ------------------------------------------------------------------------------------------------ +namespace SqMod { +namespace Algo { + +/* ------------------------------------------------------------------------------------------------ + * Collect all elements within the specified range that the inspector deems worthy. +*/ +template < typename Iterator, typename Inspector, typename Collector > +void Collect(Iterator first, Iterator last, Inspector inspect, Collector collect) +{ + for (; first != last; ++first) + { + if (inspect(*first)) + { + collect(*first); + } + } +} + +} // Namespace:: Algo +} // Namespace:: SqMod + +#endif // _BASE_ALGO_HPP_ diff --git a/source/Entity/Blip.cpp b/source/Entity/Blip.cpp index ccae5dd4..78d162d8 100644 --- a/source/Entity/Blip.cpp +++ b/source/Entity/Blip.cpp @@ -1,5 +1,6 @@ // ------------------------------------------------------------------------------------------------ #include "Entity/Blip.hpp" +#include "Base/Algo.hpp" #include "Core.hpp" // ------------------------------------------------------------------------------------------------ @@ -358,28 +359,24 @@ static const Object & Blip_FindBySprID(Int32 sprid) // ------------------------------------------------------------------------------------------------ static Array Blip_FindActive() { - // Remember the initial stack size - StackGuard sg; - // Obtain the ends of the entity pool - Core::Blips::const_iterator itr = Core::Get().GetBlips().cbegin(); - Core::Blips::const_iterator end = Core::Get().GetBlips().cend(); + const StackGuard sg; // Allocate an empty array on the stack sq_newarray(DefaultVM::Get(), 0); // Process each entity in the pool - for (; itr != end; ++itr) - { - // Is this entity instance active? - if (VALID_ENTITY(itr->mID)) - { + Algo::Collect(Core::Get().GetBlips().cbegin(), Core::Get().GetBlips().cend(), + [](Core::Blips::const_reference inst) -> bool { + return VALID_ENTITY(inst.mID); + }, + [](Core::Blips::const_reference inst) -> void { // Push the script object on the stack - sq_pushobject(DefaultVM::Get(), (HSQOBJECT &)((*itr).mObj)); + sq_pushobject(DefaultVM::Get(), inst.mObj.GetObject()); // Append the object at the back of the array - if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -1))) + if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -2))) { STHROWF("Unable to append entity instance to the list"); } } - } + ); // Return the array at the top of the stack return Var< Array >(DefaultVM::Get(), -1).value; } diff --git a/source/Entity/Checkpoint.cpp b/source/Entity/Checkpoint.cpp index 4fbd295e..adafa230 100644 --- a/source/Entity/Checkpoint.cpp +++ b/source/Entity/Checkpoint.cpp @@ -1,6 +1,7 @@ // ------------------------------------------------------------------------------------------------ #include "Entity/Checkpoint.hpp" #include "Entity/Player.hpp" +#include "Base/Algo.hpp" #include "Base/Color4.hpp" #include "Base/Vector3.hpp" #include "Core.hpp" @@ -532,28 +533,24 @@ static const Object & Checkpoint_FindByTag(CSStr tag) // ------------------------------------------------------------------------------------------------ static Array Checkpoint_FindActive() { - // Remember the initial stack size - StackGuard sg; - // Obtain the ends of the entity pool - Core::Checkpoints::const_iterator itr = Core::Get().GetCheckpoints().cbegin(); - Core::Checkpoints::const_iterator end = Core::Get().GetCheckpoints().cend(); + const StackGuard sg; // Allocate an empty array on the stack sq_newarray(DefaultVM::Get(), 0); // Process each entity in the pool - for (; itr != end; ++itr) - { - // Is this entity instance active? - if (VALID_ENTITY(itr->mID)) - { + Algo::Collect(Core::Get().GetCheckpoints().cbegin(), Core::Get().GetCheckpoints().cend(), + [](Core::Checkpoints::const_reference inst) -> bool { + return VALID_ENTITY(inst.mID); + }, + [](Core::Checkpoints::const_reference inst) -> void { // Push the script object on the stack - sq_pushobject(DefaultVM::Get(), (HSQOBJECT &)((*itr).mObj)); + sq_pushobject(DefaultVM::Get(), inst.mObj.GetObject()); // Append the object at the back of the array - if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -1))) + if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -2))) { STHROWF("Unable to append entity instance to the list"); } } - } + ); // Return the array at the top of the stack return Var< Array >(DefaultVM::Get(), -1).value; } diff --git a/source/Entity/Keybind.cpp b/source/Entity/Keybind.cpp index a94cf6e2..08de5d4e 100644 --- a/source/Entity/Keybind.cpp +++ b/source/Entity/Keybind.cpp @@ -1,5 +1,6 @@ // ------------------------------------------------------------------------------------------------ #include "Entity/Keybind.hpp" +#include "Base/Algo.hpp" #include "Core.hpp" // ------------------------------------------------------------------------------------------------ @@ -230,28 +231,24 @@ static const Object & Keybind_FindByTag(CSStr tag) // ------------------------------------------------------------------------------------------------ static Array Keybind_FindActive() { - // Remember the initial stack size - StackGuard sg; - // Obtain the ends of the entity pool - Core::Keybinds::const_iterator itr = Core::Get().GetKeybinds().cbegin(); - Core::Keybinds::const_iterator end = Core::Get().GetKeybinds().cend(); + const StackGuard sg; // Allocate an empty array on the stack sq_newarray(DefaultVM::Get(), 0); // Process each entity in the pool - for (; itr != end; ++itr) - { - // Is this entity instance active? - if (VALID_ENTITY(itr->mID)) - { + Algo::Collect(Core::Get().GetKeybinds().cbegin(), Core::Get().GetKeybinds().cend(), + [](Core::Keybinds::const_reference inst) -> bool { + return VALID_ENTITY(inst.mID); + }, + [](Core::Keybinds::const_reference inst) -> void { // Push the script object on the stack - sq_pushobject(DefaultVM::Get(), (HSQOBJECT &)((*itr).mObj)); + sq_pushobject(DefaultVM::Get(), inst.mObj.GetObject()); // Append the object at the back of the array - if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -1))) + if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -2))) { STHROWF("Unable to append entity instance to the list"); } } - } + ); // Return the array at the top of the stack return Var< Array >(DefaultVM::Get(), -1).value; } diff --git a/source/Entity/Object.cpp b/source/Entity/Object.cpp index 4b0febf6..d5e897ae 100644 --- a/source/Entity/Object.cpp +++ b/source/Entity/Object.cpp @@ -1,6 +1,7 @@ // ------------------------------------------------------------------------------------------------ #include "Entity/Object.hpp" #include "Entity/Player.hpp" +#include "Base/Algo.hpp" #include "Base/Quaternion.hpp" #include "Base/Vector3.hpp" #include "Core.hpp" @@ -856,28 +857,24 @@ static const Object & Object_FindByTag(CSStr tag) // ------------------------------------------------------------------------------------------------ static Array Object_FindActive() { - // Remember the initial stack size - StackGuard sg; - // Obtain the ends of the entity pool - Core::Objects::const_iterator itr = Core::Get().GetObjects().cbegin(); - Core::Objects::const_iterator end = Core::Get().GetObjects().cend(); + const StackGuard sg; // Allocate an empty array on the stack sq_newarray(DefaultVM::Get(), 0); // Process each entity in the pool - for (; itr != end; ++itr) - { - // Is this entity instance active? - if (VALID_ENTITY(itr->mID)) - { + Algo::Collect(Core::Get().GetObjects().cbegin(), Core::Get().GetObjects().cend(), + [](Core::Objects::const_reference inst) -> bool { + return VALID_ENTITY(inst.mID); + }, + [](Core::Objects::const_reference inst) -> void { // Push the script object on the stack - sq_pushobject(DefaultVM::Get(), (HSQOBJECT &)((*itr).mObj)); + sq_pushobject(DefaultVM::Get(), inst.mObj.GetObject()); // Append the object at the back of the array - if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -1))) + if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -2))) { STHROWF("Unable to append entity instance to the list"); } } - } + ); // Return the array at the top of the stack return Var< Array >(DefaultVM::Get(), -1).value; } diff --git a/source/Entity/Pickup.cpp b/source/Entity/Pickup.cpp index 6414badc..06fd1ec9 100644 --- a/source/Entity/Pickup.cpp +++ b/source/Entity/Pickup.cpp @@ -1,6 +1,7 @@ // ------------------------------------------------------------------------------------------------ #include "Entity/Pickup.hpp" #include "Entity/Player.hpp" +#include "Base/Algo.hpp" #include "Base/Vector3.hpp" #include "Core.hpp" @@ -418,28 +419,24 @@ static const Object & Pickup_FindByTag(CSStr tag) // ------------------------------------------------------------------------------------------------ static Array Pickup_FindActive() { - // Remember the initial stack size - StackGuard sg; - // Obtain the ends of the entity pool - Core::Pickups::const_iterator itr = Core::Get().GetPickups().cbegin(); - Core::Pickups::const_iterator end = Core::Get().GetPickups().cend(); + const StackGuard sg; // Allocate an empty array on the stack sq_newarray(DefaultVM::Get(), 0); // Process each entity in the pool - for (; itr != end; ++itr) - { - // Is this entity instance active? - if (VALID_ENTITY(itr->mID)) - { + Algo::Collect(Core::Get().GetPickups().cbegin(), Core::Get().GetPickups().cend(), + [](Core::Pickups::const_reference inst) -> bool { + return VALID_ENTITY(inst.mID); + }, + [](Core::Pickups::const_reference inst) -> void { // Push the script object on the stack - sq_pushobject(DefaultVM::Get(), (HSQOBJECT &)((*itr).mObj)); + sq_pushobject(DefaultVM::Get(), inst.mObj.GetObject()); // Append the object at the back of the array - if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -1))) + if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -2))) { STHROWF("Unable to append entity instance to the list"); } } - } + ); // Return the array at the top of the stack return Var< Array >(DefaultVM::Get(), -1).value; } diff --git a/source/Entity/Player.cpp b/source/Entity/Player.cpp index 35c3ef2c..8454f5ab 100644 --- a/source/Entity/Player.cpp +++ b/source/Entity/Player.cpp @@ -1,6 +1,7 @@ // ------------------------------------------------------------------------------------------------ #include "Entity/Player.hpp" #include "Entity/Vehicle.hpp" +#include "Base/Algo.hpp" #include "Base/Color3.hpp" #include "Base/Color4.hpp" #include "Base/Vector3.hpp" @@ -2112,28 +2113,24 @@ static const Object & Player_FindByTag(CSStr tag) // ------------------------------------------------------------------------------------------------ static Array Player_FindActive() { - // Remember the initial stack size - StackGuard sg; - // Obtain the ends of the entity pool - Core::Players::const_iterator itr = Core::Get().GetPlayers().cbegin(); - Core::Players::const_iterator end = Core::Get().GetPlayers().cend(); + const StackGuard sg; // Allocate an empty array on the stack sq_newarray(DefaultVM::Get(), 0); // Process each entity in the pool - for (; itr != end; ++itr) - { - // Is this entity instance active? - if (VALID_ENTITY(itr->mID)) - { + Algo::Collect(Core::Get().GetPlayers().cbegin(), Core::Get().GetPlayers().cend(), + [](Core::Players::const_reference inst) -> bool { + return VALID_ENTITY(inst.mID); + }, + [](Core::Players::const_reference inst) -> void { // Push the script object on the stack - sq_pushobject(DefaultVM::Get(), (HSQOBJECT &)((*itr).mObj)); + sq_pushobject(DefaultVM::Get(), inst.mObj.GetObject()); // Append the object at the back of the array - if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -1))) + if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -2))) { STHROWF("Unable to append entity instance to the list"); } } - } + ); // Return the array at the top of the stack return Var< Array >(DefaultVM::Get(), -1).value; } diff --git a/source/Entity/Vehicle.cpp b/source/Entity/Vehicle.cpp index 2fa23a84..44986deb 100644 --- a/source/Entity/Vehicle.cpp +++ b/source/Entity/Vehicle.cpp @@ -1,6 +1,7 @@ // ------------------------------------------------------------------------------------------------ #include "Entity/Vehicle.hpp" #include "Entity/Player.hpp" +#include "Base/Algo.hpp" #include "Base/Quaternion.hpp" #include "Base/Vector2.hpp" #include "Base/Vector3.hpp" @@ -1675,28 +1676,24 @@ static const Object & Vehicle_FindByTag(CSStr tag) // ------------------------------------------------------------------------------------------------ static Array Vehicle_FindActive() { - // Remember the initial stack size - StackGuard sg; - // Obtain the ends of the entity pool - Core::Vehicles::const_iterator itr = Core::Get().GetVehicles().cbegin(); - Core::Vehicles::const_iterator end = Core::Get().GetVehicles().cend(); + const StackGuard sg; // Allocate an empty array on the stack sq_newarray(DefaultVM::Get(), 0); // Process each entity in the pool - for (; itr != end; ++itr) - { - // Is this entity instance active? - if (VALID_ENTITY(itr->mID)) - { + Algo::Collect(Core::Get().GetVehicles().cbegin(), Core::Get().GetVehicles().cend(), + [](Core::Vehicles::const_reference inst) -> bool { + return VALID_ENTITY(inst.mID); + }, + [](Core::Vehicles::const_reference inst) -> void { // Push the script object on the stack - sq_pushobject(DefaultVM::Get(), (HSQOBJECT &)((*itr).mObj)); + sq_pushobject(DefaultVM::Get(), inst.mObj.GetObject()); // Append the object at the back of the array - if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -1))) + if (SQ_FAILED(sq_arrayappend(DefaultVM::Get(), -2))) { STHROWF("Unable to append entity instance to the list"); } } - } + ); // Return the array at the top of the stack return Var< Array >(DefaultVM::Get(), -1).value; }