diff --git a/include/state/gamestate.hpp b/include/state/gamestate.hpp index ebaaf4e..8d881a8 100644 --- a/include/state/gamestate.hpp +++ b/include/state/gamestate.hpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace Game::State { class GameState { @@ -16,22 +17,19 @@ namespace Game::State { template void withEntitiesLocked(Fn&& fn) { std::scoped_lock lock(mMutex); - fn(mEntities); + fn(mEntityMap); } - void sort(); // Sort entities by zIndex for correct rendering order void wipe(); Object::Entity* getEntityByName(const std::string& name); // Get an entity by name, returns nullptr if no entity with the name exists std::vector getEntitiesSnapshot(bool sortByZIndex = false); // Get a stable snapshot of entity pointers for iteration outside the lock - // Update entity at index, by REFERENCE. - 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. + // Add an entity to the gamestate; returns a pointer to the stored entity. Object::Entity* addEntity(std::unique_ptr entity); bool removeEntity(const std::string& name); private: mutable std::mutex mMutex; // Shared mutex for thread safety - std::vector> mEntities; + std::unordered_map> mEntityMap; // Own entities while allowing O(1) lookup by name }; } \ No newline at end of file diff --git a/src/state/gamestate.cpp b/src/state/gamestate.cpp index e3feb48..be37440 100644 --- a/src/state/gamestate.cpp +++ b/src/state/gamestate.cpp @@ -3,22 +3,13 @@ #include namespace Game::State { - Object::Entity* GameState::getAtIndex(size_t at) { - std::lock_guard 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 entity) { Object::Entity* addedEntity = nullptr; { std::lock_guard lock(mMutex); // Lock the mutex for thread safety - mEntities.push_back(std::move(entity)); - addedEntity = mEntities.back().get(); + const std::string name = entity->getName(); + 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. @@ -28,40 +19,33 @@ namespace Game::State { bool GameState::removeEntity(const std::string& name) { std::lock_guard lock(mMutex); // Lock the mutex for thread safety - for (size_t i = 0; i < mEntities.size(); i++) { - if (mEntities[i]->getName() == name) { - mEntities[i]->destroyed(); - mEntities.erase(mEntities.begin() + i); - return true; + auto it = mEntityMap.find(name); + if (it != mEntityMap.end()) { + if (it->second) { + it->second->destroyed(); } + mEntityMap.erase(it); + return true; } return false; } - void GameState::sort() { - std::lock_guard lock(mMutex); // Lock the mutex for thread safety - std::sort(mEntities.begin(), mEntities.end(), [](const std::unique_ptr& a, const std::unique_ptr& b) { - return a->getZIndex() < b->getZIndex(); - }); - } - void GameState::wipe() { std::lock_guard lock(mMutex); - for (const auto& entity : mEntities) { - if (entity) { - entity->destroyed(); + for (const auto& pair : mEntityMap) { + if (pair.second) { + pair.second->destroyed(); } } - mEntities.clear(); + mEntityMap.clear(); } Object::Entity* GameState::getEntityByName(const std::string& name) { std::lock_guard lock(mMutex); // Lock the mutex for thread safety - for (const auto& entity : mEntities) { - if (entity->getName() == name) { - return entity.get(); - } + auto it = mEntityMap.find(name); + if (it != mEntityMap.end()) { + return it->second.get(); } return nullptr; // Return nullptr if no entity with the name exists } @@ -70,9 +54,9 @@ namespace Game::State { std::vector snapshot; std::lock_guard lock(mMutex); - snapshot.reserve(mEntities.size()); - for (const auto& entity : mEntities) { - snapshot.push_back(entity.get()); + snapshot.reserve(mEntityMap.size()); + for (const auto& entity : mEntityMap) { + snapshot.push_back(entity.second.get()); } if (sortByZIndex) {