55 std::shared_ptr<ThreadPool> threadPool, std::shared_ptr<EventBus> eventBus)
57 _threadPool(threadPool),
62 _world = std::make_shared<ecs::wrapper::ECSWorld>();
71 LOG_DEBUG(
"GameLogic: Running in single-threaded mode");
75 _luaEngine = std::make_unique<scripting::LuaEngine>(
"server/Scripting/scripts/");
77 LOG_INFO(
"GameLogic: Lua scripting engine initialized");
79 LOG_DEBUG(
"GameLogic: EventBus enabled for event publishing");
82 LOG_DEBUG(
"GameLogic: GameStateManager initialized");
93 LOG_INFO(
"Initializing game logic...");
105 auto luaSystem = std::make_unique<scripting::LuaSystemAdapter>(
_luaEngine.get(),
_world.get());
106 _world->registerSystem(
"Lua", std::move(luaSystem));
107 LOG_INFO(
"✓ Lua system registered (executes before spawn processing)");
116 LOG_INFO(
"✓ All systems registered (",
_world->getSystemCount(),
" systems)");
118 LOG_INFO(
"✓ Systems will execute in parallel mode (4 groups)");
120 LOG_INFO(
"✓ Systems will execute sequentially");
124 _stateManager->registerState(0, std::make_shared<LobbyState>());
125 _stateManager->registerState(1, std::make_shared<InGameState>());
126 _stateManager->registerState(2, std::make_shared<GameOverState>());
137 LOG_INFO(
"✓ GameStateManager initialized with 3 states");
141 LOG_INFO(
"✓ Initialization complete!");
143 }
catch (
const std::exception &e) {
144 LOG_ERROR(
"Initialization failed: ", e.what());
172 LOG_INFO(
"Spawning player: ", playerName,
" (ID: ", playerId,
")");
176 LOG_ERROR(
"Player ", playerId,
" already exists!");
192 .
with(
ecs::Sprite(
"PlayerShips.gif", {1, 69, 33, 14}, 3.0f, 0.0f,
false,
false, 0))
193 .
with(playerAnimations)
217 LOG_INFO(
"✓ Orbital drone spawned for player (ID: ", droneId,
")");
220 return entityAddress;
221 }
catch (
const std::exception &e) {
222 LOG_ERROR(
"Failed to spawn player: ", e.what());
239 playerEntity = it->second;
243 LOG_INFO(
"Despawning player ", playerId,
" (entity: ", playerEntity,
")");
246 _world->getEntity(playerEntity)
248 LOG_INFO(
"✓ Player marked for destruction (will be processed in next tick)");
249 }
catch (
const std::exception &e) {
250 LOG_ERROR(
"Failed to despawn player: ", e.what());
255 uint32_t sequenceId) {
262 if (sequenceId <= it->second) {
269 _pendingInput[playerId].push_back({playerId, inputX, inputY, isShooting, sequenceId});
276 if (inputs.empty()) {
287 size_t inputsToProcess = 1;
288 if (inputs.size() > 5) {
292 for (
size_t i = 0; i < inputsToProcess && !inputs.empty(); ++i) {
293 const auto &input = inputs.front();
314 " entity missing Velocity or Transform component (entity destroyed?)");
337 float dirX =
static_cast<float>(input.
inputX);
338 float dirY =
static_cast<float>(input.
inputY);
341 if (dirX != 0.0f && dirY != 0.0f) {
342 float length = std::sqrt(dirX * dirX + dirY * dirY);
359 float dirX =
static_cast<float>(input.
inputX);
360 float dirY =
static_cast<float>(input.
inputY);
363 if (dirX != 0.0f && dirY != 0.0f) {
364 float length = std::sqrt(dirX * dirX + dirY * dirY);
373 auto pos = transform.getPosition();
376 transform.setPosition(newX, newY);
392 weapon.setShouldShoot(
false);
397 }
catch (
const std::exception &e) {
398 LOG_ERROR(
"Error applying input for player ", playerId,
": ", e.what());
405 _world->update(deltaTime);
413 std::vector<std::string> group1 = {
"MovementSystem",
"OrbitalSystem"};
416 std::vector<std::string> group2 = {
"AnimationSystem"};
419 std::vector<std::string> group3 = {
"CollisionSystem",
"BoundarySystem"};
422 std::vector<std::string> group4 = {
"HealthSystem",
"WeaponSystem"};
425 std::vector<std::string> group5 = {
"Lua"};
428 std::vector<std::string> group6 = {
"AISystem",
"SpawnSystem"};
431 auto executeGroup = [
this, deltaTime](
const std::vector<std::string> &group) {
433 auto completed = std::make_shared<std::atomic<int>>(0);
434 const int total =
static_cast<int>(group.size());
436 for (
const auto &systemName : group) {
438 _threadPool->enqueue([
this, systemName, deltaTime, completed]() {
439 _world->updateSystem(systemName, deltaTime);
445 while (*completed < total) {
446 std::this_thread::yield();
451 executeGroup(group1);
452 executeGroup(group2);
453 executeGroup(group3);
454 executeGroup(group4);
455 executeGroup(group5);
456 executeGroup(group6);
463 for (
auto &entity : entitiesToDestroy) {
470 if (it->second == entityAddress) {
471 LOG_INFO(
"Removing player ", it->first,
" from player map (entity destroyed)");
480 _world->destroyEntity(entity);
495 bool allPlayersDead =
true;
496 bool anyEnemiesRemain =
false;
504 for (
const auto &[playerId, entityAddress] :
_playerMap) {
508 allPlayersDead =
false;
520 for (
auto &enemyEntity : enemies) {
525 anyEnemiesRemain =
true;
535 bool spawnerStillActive =
false;
537 for (
auto &spawnerEntity : spawners) {
542 spawnerStillActive =
true;
552 if (!anyEnemiesRemain && !spawnerStillActive && !allPlayersDead) {
553 LOG_INFO(
"Victory! All enemies defeated!");
563 if (allPlayersDead) {
564 LOG_INFO(
"Defeat! All players eliminated.");
589 LOG_INFO(
"Game started! Loading map...");
592 loadMap(
"assets/maps/level_1.json");
594 LOG_INFO(
"✓ Map loaded and spawning will begin!");
598 LOG_INFO(
"Loading map from: ", mapFilePath);
602 if (!mapDataOpt.has_value()) {
603 LOG_ERROR(
"Failed to load map from: ", mapFilePath);
614 if (!mapEntities.empty()) {
616 auto mapEntity = mapEntities[0];
617 mapEntity.with(mapData);
618 LOG_INFO(
"Updated existing map entity");
621 _world->createEntity().with(mapData);
628 LOG_INFO(
"Loading spawn script: ", spawnScript);
633 LOG_INFO(
"✓ Spawner created with script: ", spawnScript);
System managing enemy AI behavior and attack patterns.
Component containing all available animations for an entity.
System managing sprite animation playback.
Component managing current animation playback state.
void setCurrentFrameIndex(int frameIndex)
Set the current frame index.
std::string getCurrentClipName() const
Get the current animation clip name.
void setCurrentClipName(const std::string &clipName)
Set the current animation clip name.
void setTimer(float timer)
Set the playback timer.
System managing entity boundaries and screen limits.
System managing buff timers and applying buff effects.
Component for collision detection and physics interactions.
System handling collision detection between entities.
Component identifying an entity as an enemy with AI behavior.
System managing entity health, invincibility and death.
Component representing entity health and invincibility.
int getCurrentHealth() const
Get current health points.
Component that holds the path to a Lua script for entity behavior.
Component storing information about the current map/level.
const std::string & getMapId() const
Get the map unique identifier.
float getScrollSpeed() const
Get the scroll speed.
const std::string & getSpawnScript() const
Get the spawn script path.
float getDuration() const
Get the map duration.
const std::string & getName() const
Get the map display name.
System managing map state, scrolling, and transitions.
System handling entity movement based on velocity.
System managing orbital module movement around parent entities.
Marker component indicating entity should be destroyed.
Component identifying an entity as a player with game statistics.
static ecs::Address createOrbitalModule(ecs::Registry ®istry, uint32_t parentEntityId, float orbitRadius=50.0f, float orbitSpeed=2.0f, float startAngle=0.0f, int damage=10, int moduleHealth=50)
Create an orbital module (drone) entity.
System managing entity spawning and wave generation.
Component that holds spawn requests to be processed by SpawnSystem.
Component representing a visual sprite from a texture.
Component representing movement direction and speed.
float getSpeed() const
Get the movement speed.
void setDirection(float dirX, float dirY)
Set the direction vector.
System managing weapon firing and cooldowns.
Component for entities capable of shooting projectiles.
void setShouldShoot(bool shouldShoot)
Set whether the weapon should shoot.
High-level entity wrapper providing fluent interface.
Entity & with(const T &component)
Add/set a component to this entity.
bool has() const
Check if this entity has a specific component.
T & get()
Get a component from this entity.
Address getAddress() const
Get the entity's address.
static std::optional< ecs::MapData > loadFromFile(const std::string &filePath)
Load a map from a JSON file.
Event triggered when the game ends.
void _applyPlayerInput(uint32_t playerId, const PlayerInput &input)
Apply a single input snapshot to a player entity.
void _executeSystems(float deltaTime)
Execute all systems in order.
uint32_t spawnPlayer(uint32_t playerId, const std::string &playerName) override
Spawn a player entity.
std::shared_ptr< ThreadPool > _threadPool
void resetGame() override
Reset game state (new game)
std::unordered_map< uint32_t, std::deque< PlayerInput > > _pendingInput
void _checkGameOverCondition()
Check if all players are dead and trigger game over.
bool initialize() override
Initialize game logic and ECS systems.
void despawnPlayer(uint32_t playerId) override
Remove a player from the game.
bool loadMap(const std::string &mapFilePath)
Load and activate a new map from a JSON file.
static constexpr float FIXED_TIMESTEP
void _cleanupDeadEntities()
Clean up dead entities.
std::unordered_map< uint32_t, ecs::Address > _playerMap
std::shared_ptr< EventBus > _eventBus
std::unique_ptr< scripting::LuaEngine > _luaEngine
GameLogic(std::shared_ptr< ecs::wrapper::ECSWorld > world=nullptr, std::shared_ptr< ThreadPool > threadPool=nullptr, std::shared_ptr< EventBus > eventBus=nullptr)
Constructor.
std::shared_ptr< ecs::wrapper::ECSWorld > _world
std::atomic< bool > _initialized
void update(float deltaTime, uint32_t currentTick) override
Update game state for one frame.
void onGameStart()
Notify Lua scripts that the game has started.
void _processInput()
Process accumulated player input.
std::shared_ptr< GameStateManager > _stateManager
std::unordered_map< uint32_t, uint32_t > _lastReceivedSequenceId
std::unordered_map< uint32_t, uint32_t > _lastAppliedSequenceId
void processPlayerInput(uint32_t playerId, int inputX, int inputY, bool isShooting, uint32_t sequenceId) override
Process player input event.
constexpr uint32_t getPlayerSpawnY() const
constexpr uint32_t getPlayerSpawnX() const
constexpr uint32_t getDefaultPlayerSpeed() const
constexpr uint32_t getDefaultPlayerDamage() const
constexpr uint32_t getDefaultPlayerHealth() const
constexpr float getDefaultPlayerFireRate() const
Handles switching between game states.
ecs::AnimationSet createPlayerAnimations()
Create player ship animations.
std::uint32_t Address
Type used to represent an entity address/ID.
@ Manual
Manually destroyed (script, etc.)