#pragma once #include #include #include #include #include #include #include #include #include #include #include #include namespace Game { using clock = std::chrono::steady_clock; enum class GameStateEnum { RUNNING, PAUSED, STOPPED }; enum class SharedDataType { STRING, INT, FLOAT, BOOL }; class GameManager { public: GameManager() { LOG("Created GameManager"); }; DISABLE_COPY_AND_MOVE(GameManager); ~GameManager() = default; // Start the game logic slave thread, which will update the gamestate and entities; Run as jthread void run(std::stop_token stopToken); void setTargetUpdatesPerSecond(int target) { mTargetUpdatesPerSecond = target; } int getTargetUpdatesPerSecond() { return mTargetUpdatesPerSecond; } float getLastDelta() { return mLastDelta; } template static void setSharedData(const std::string& key, T data); template static T getSharedData(const std::string& key); static void removeSharedData(const std::string& key, SharedDataType type); static GameStateEnum getCurrentGameState() { return mCurrentGameState; } static void setCurrentGameState(GameStateEnum newState) { mCurrentGameState = newState; } template static bool instantiateEntity(std::unique_ptr entity); template static T* getEntityByName(const std::string& name); template static void destroyEntity(T* entity); static void processPendingEntityRemovals(); private: int mTargetUpdatesPerSecond = TARGET_UPDATE_RATE; clock::time_point mLastUpdate; static std::unordered_map mSharedStrings; static std::unordered_map mSharedInts; static std::unordered_map mSharedFloats; static std::unordered_map mSharedBools; static GameStateEnum mCurrentGameState; float mLastDelta = 0.f; }; template void GameManager::setSharedData(const std::string& key, T data) { if constexpr (std::is_same_v) { mSharedStrings[key] = data; } else if constexpr (std::is_same_v) { mSharedInts[key] = data; } else if constexpr (std::is_same_v) { mSharedFloats[key] = data; } else if constexpr (std::is_same_v) { mSharedBools[key] = data; } } template T GameManager::getSharedData(const std::string& key) { if constexpr (std::is_same_v) { auto it = mSharedStrings.find(key); if (it != mSharedStrings.end()) { return it->second; } else { return ""; } } else if constexpr (std::is_same_v) { auto it = mSharedInts.find(key); if (it != mSharedInts.end()) { return it->second; } else { return 0; } } else if constexpr (std::is_same_v) { auto it = mSharedFloats.find(key); if (it != mSharedFloats.end()) { return it->second; } else { return 0.0f; } } else if constexpr (std::is_same_v) { auto it = mSharedBools.find(key); if (it != mSharedBools.end()) { return it->second; } else { return false; } } static_assert( std::is_same_v || std::is_same_v || std::is_same_v || std::is_same_v, "Unsupported type for shared data" ); return T{}; } template bool GameManager::instantiateEntity(std::unique_ptr entity) { static_assert(std::is_base_of_v, "T must derive from Object::Entity"); State::GameState::getInstance().addEntity(std::move(entity)); return true; } template T* GameManager::getEntityByName(const std::string& name) { static_assert(std::is_base_of_v, "T must derive from Object::Entity"); Object::Entity* entity = State::GameState::getInstance().getEntityByName(name); return dynamic_cast(entity); } template void GameManager::destroyEntity(T* entity) { static_assert(std::is_base_of_v, "T must derive from Object::Entity"); if (entity) { entity->setActive(false); State::GameState::getInstance().queueEntityRemoval(entity->getName()); } } }