Move entities to hashmap
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
#include <utils.hpp>
|
#include <utils.hpp>
|
||||||
#include <object/entity.hpp>
|
#include <object/entity.hpp>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
namespace Game::State {
|
namespace Game::State {
|
||||||
class GameState {
|
class GameState {
|
||||||
@@ -16,22 +17,19 @@ namespace Game::State {
|
|||||||
template<typename Fn>
|
template<typename Fn>
|
||||||
void withEntitiesLocked(Fn&& fn) {
|
void withEntitiesLocked(Fn&& fn) {
|
||||||
std::scoped_lock lock(mMutex);
|
std::scoped_lock lock(mMutex);
|
||||||
fn(mEntities);
|
fn(mEntityMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sort(); // Sort entities by zIndex for correct rendering order
|
|
||||||
void wipe();
|
void wipe();
|
||||||
Object::Entity* getEntityByName(const std::string& name); // Get an entity by name, returns nullptr if no entity with the name exists
|
Object::Entity* getEntityByName(const std::string& name); // Get an entity by name, returns nullptr if no entity with the name exists
|
||||||
std::vector<Object::Entity*> getEntitiesSnapshot(bool sortByZIndex = false); // Get a stable snapshot of entity pointers for iteration outside the lock
|
std::vector<Object::Entity*> getEntitiesSnapshot(bool sortByZIndex = false); // Get a stable snapshot of entity pointers for iteration outside the lock
|
||||||
|
|
||||||
// Update entity at index, by REFERENCE.
|
// Add an entity to the gamestate; returns a pointer to the stored entity.
|
||||||
Object::Entity* getAtIndex(size_t at);
|
|
||||||
// Add an entity to the gamestate; Returns a temporary pointer to the entity added. Note that the validity of this pointer cannot be guaranteed after the first call.
|
|
||||||
Object::Entity* addEntity(std::unique_ptr<Object::Entity> entity);
|
Object::Entity* addEntity(std::unique_ptr<Object::Entity> entity);
|
||||||
bool removeEntity(const std::string& name);
|
bool removeEntity(const std::string& name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable std::mutex mMutex; // Shared mutex for thread safety
|
mutable std::mutex mMutex; // Shared mutex for thread safety
|
||||||
std::vector<std::unique_ptr<Object::Entity>> mEntities;
|
std::unordered_map<std::string, std::unique_ptr<Object::Entity>> mEntityMap; // Own entities while allowing O(1) lookup by name
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -3,22 +3,13 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
namespace Game::State {
|
namespace Game::State {
|
||||||
Object::Entity* GameState::getAtIndex(size_t at) {
|
|
||||||
std::lock_guard<std::mutex> lock(mMutex); // Lock the mutex for thread safety
|
|
||||||
try {
|
|
||||||
return mEntities.at(at).get();
|
|
||||||
} catch (const std::out_of_range& e) {
|
|
||||||
WARN("Tried to access entity from GameState out of range!");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Object::Entity* GameState::addEntity(std::unique_ptr<Object::Entity> entity) {
|
Object::Entity* GameState::addEntity(std::unique_ptr<Object::Entity> entity) {
|
||||||
Object::Entity* addedEntity = nullptr;
|
Object::Entity* addedEntity = nullptr;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mMutex); // Lock the mutex for thread safety
|
std::lock_guard<std::mutex> lock(mMutex); // Lock the mutex for thread safety
|
||||||
mEntities.push_back(std::move(entity));
|
const std::string name = entity->getName();
|
||||||
addedEntity = mEntities.back().get();
|
auto [it, inserted] = mEntityMap.emplace(name, std::move(entity));
|
||||||
|
addedEntity = it->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
addedEntity->start(); // Initialize the entity after insertion without holding the GameState lock.
|
addedEntity->start(); // Initialize the entity after insertion without holding the GameState lock.
|
||||||
@@ -28,40 +19,33 @@ namespace Game::State {
|
|||||||
|
|
||||||
bool GameState::removeEntity(const std::string& name) {
|
bool GameState::removeEntity(const std::string& name) {
|
||||||
std::lock_guard<std::mutex> lock(mMutex); // Lock the mutex for thread safety
|
std::lock_guard<std::mutex> lock(mMutex); // Lock the mutex for thread safety
|
||||||
for (size_t i = 0; i < mEntities.size(); i++) {
|
auto it = mEntityMap.find(name);
|
||||||
if (mEntities[i]->getName() == name) {
|
if (it != mEntityMap.end()) {
|
||||||
mEntities[i]->destroyed();
|
if (it->second) {
|
||||||
mEntities.erase(mEntities.begin() + i);
|
it->second->destroyed();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
mEntityMap.erase(it);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameState::sort() {
|
|
||||||
std::lock_guard<std::mutex> lock(mMutex); // Lock the mutex for thread safety
|
|
||||||
std::sort(mEntities.begin(), mEntities.end(), [](const std::unique_ptr<Object::Entity>& a, const std::unique_ptr<Object::Entity>& b) {
|
|
||||||
return a->getZIndex() < b->getZIndex();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void GameState::wipe() {
|
void GameState::wipe() {
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
for (const auto& entity : mEntities) {
|
for (const auto& pair : mEntityMap) {
|
||||||
if (entity) {
|
if (pair.second) {
|
||||||
entity->destroyed();
|
pair.second->destroyed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mEntities.clear();
|
mEntityMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
Object::Entity* GameState::getEntityByName(const std::string& name) {
|
Object::Entity* GameState::getEntityByName(const std::string& name) {
|
||||||
std::lock_guard<std::mutex> lock(mMutex); // Lock the mutex for thread safety
|
std::lock_guard<std::mutex> lock(mMutex); // Lock the mutex for thread safety
|
||||||
for (const auto& entity : mEntities) {
|
auto it = mEntityMap.find(name);
|
||||||
if (entity->getName() == name) {
|
if (it != mEntityMap.end()) {
|
||||||
return entity.get();
|
return it->second.get();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nullptr; // Return nullptr if no entity with the name exists
|
return nullptr; // Return nullptr if no entity with the name exists
|
||||||
}
|
}
|
||||||
@@ -70,9 +54,9 @@ namespace Game::State {
|
|||||||
std::vector<Object::Entity*> snapshot;
|
std::vector<Object::Entity*> snapshot;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(mMutex);
|
std::lock_guard<std::mutex> lock(mMutex);
|
||||||
snapshot.reserve(mEntities.size());
|
snapshot.reserve(mEntityMap.size());
|
||||||
for (const auto& entity : mEntities) {
|
for (const auto& entity : mEntityMap) {
|
||||||
snapshot.push_back(entity.get());
|
snapshot.push_back(entity.second.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sortByZIndex) {
|
if (sortByZIndex) {
|
||||||
|
|||||||
Reference in New Issue
Block a user