Browse Source

Further refactor: extract renderer bootstrap and level orchestration logic

Co-authored-by: djeada <[email protected]>
copilot-swe-agent[bot] 4 days ago
parent
commit
f9a3f4da25

+ 4 - 0
CMakeLists.txt

@@ -128,6 +128,8 @@ if(QT_VERSION_MAJOR EQUAL 6)
         app/core/minimap_manager.cpp
         app/core/minimap_manager.cpp
         app/core/ambient_state_manager.cpp
         app/core/ambient_state_manager.cpp
         app/core/audio_resource_loader.cpp
         app/core/audio_resource_loader.cpp
+        app/core/renderer_bootstrap.cpp
+        app/core/level_orchestrator.cpp
         app/models/audio_system_proxy.cpp
         app/models/audio_system_proxy.cpp
         app/models/graphics_settings_proxy.cpp
         app/models/graphics_settings_proxy.cpp
         app/models/cursor_manager.cpp
         app/models/cursor_manager.cpp
@@ -148,6 +150,8 @@ else()
         app/core/minimap_manager.cpp
         app/core/minimap_manager.cpp
         app/core/ambient_state_manager.cpp
         app/core/ambient_state_manager.cpp
         app/core/audio_resource_loader.cpp
         app/core/audio_resource_loader.cpp
+        app/core/renderer_bootstrap.cpp
+        app/core/level_orchestrator.cpp
         app/models/audio_system_proxy.cpp
         app/models/audio_system_proxy.cpp
         app/models/graphics_settings_proxy.cpp
         app/models/graphics_settings_proxy.cpp
         app/models/cursor_manager.cpp
         app/models/cursor_manager.cpp

+ 46 - 122
app/core/game_engine.cpp

@@ -16,7 +16,9 @@
 #include "game/audio/AudioSystem.h"
 #include "game/audio/AudioSystem.h"
 #include "game/units/spawn_type.h"
 #include "game/units/spawn_type.h"
 #include "game/units/troop_type.h"
 #include "game/units/troop_type.h"
+#include "level_orchestrator.h"
 #include "minimap_manager.h"
 #include "minimap_manager.h"
+#include "renderer_bootstrap.h"
 #include <QBuffer>
 #include <QBuffer>
 #include <QCoreApplication>
 #include <QCoreApplication>
 #include <QCursor>
 #include <QCursor>
@@ -133,54 +135,28 @@ GameEngine::GameEngine(QObject *parent)
   Game::Systems::GlobalStatsRegistry::instance().initialize();
   Game::Systems::GlobalStatsRegistry::instance().initialize();
 
 
   m_world = std::make_unique<Engine::Core::World>();
   m_world = std::make_unique<Engine::Core::World>();
-  m_renderer = std::make_unique<Render::GL::Renderer>();
-  m_camera = std::make_unique<Render::GL::Camera>();
-  m_ground = std::make_unique<Render::GL::GroundRenderer>();
-  m_terrain = std::make_unique<Render::GL::TerrainRenderer>();
-  m_biome = std::make_unique<Render::GL::BiomeRenderer>();
-  m_river = std::make_unique<Render::GL::RiverRenderer>();
-  m_road = std::make_unique<Render::GL::RoadRenderer>();
-  m_riverbank = std::make_unique<Render::GL::RiverbankRenderer>();
-  m_bridge = std::make_unique<Render::GL::BridgeRenderer>();
-  m_fog = std::make_unique<Render::GL::FogRenderer>();
-  m_stone = std::make_unique<Render::GL::StoneRenderer>();
-  m_plant = std::make_unique<Render::GL::PlantRenderer>();
-  m_pine = std::make_unique<Render::GL::PineRenderer>();
-  m_olive = std::make_unique<Render::GL::OliveRenderer>();
-  m_firecamp = std::make_unique<Render::GL::FireCampRenderer>();
-
-  m_passes = {m_ground.get(), m_terrain.get(),   m_river.get(),
-              m_road.get(),   m_riverbank.get(), m_bridge.get(),
-              m_biome.get(),  m_stone.get(),     m_plant.get(),
-              m_pine.get(),   m_olive.get(),     m_firecamp.get(),
-              m_fog.get()};
-
-  std::unique_ptr<Engine::Core::System> arrow_sys =
-      std::make_unique<Game::Systems::ArrowSystem>();
-  m_world->add_system(std::move(arrow_sys));
-
-  std::unique_ptr<Engine::Core::System> projectile_sys =
-      std::make_unique<Game::Systems::ProjectileSystem>();
-  m_world->add_system(std::move(projectile_sys));
-
-  m_world->add_system(std::make_unique<Game::Systems::MovementSystem>());
-  m_world->add_system(std::make_unique<Game::Systems::PatrolSystem>());
-  m_world->add_system(std::make_unique<Game::Systems::CombatSystem>());
-  m_world->add_system(std::make_unique<Game::Systems::CatapultAttackSystem>());
-  m_world->add_system(std::make_unique<Game::Systems::BallistaAttackSystem>());
-  m_world->add_system(std::make_unique<Game::Systems::HealingSystem>());
-  m_world->add_system(std::make_unique<Game::Systems::CaptureSystem>());
-  m_world->add_system(std::make_unique<Game::Systems::AISystem>());
-  m_world->add_system(std::make_unique<Game::Systems::ProductionSystem>());
-  m_world->add_system(
-      std::make_unique<Game::Systems::TerrainAlignmentSystem>());
-  m_world->add_system(std::make_unique<Game::Systems::CleanupSystem>());
-
-  {
-    std::unique_ptr<Engine::Core::System> sel_sys =
-        std::make_unique<Game::Systems::SelectionSystem>();
-    m_world->add_system(std::move(sel_sys));
-  }
+
+  // Initialize rendering components
+  auto rendering = RendererBootstrap::initialize_rendering();
+  m_renderer = std::move(rendering.renderer);
+  m_camera = std::move(rendering.camera);
+  m_ground = std::move(rendering.ground);
+  m_terrain = std::move(rendering.terrain);
+  m_biome = std::move(rendering.biome);
+  m_river = std::move(rendering.river);
+  m_road = std::move(rendering.road);
+  m_riverbank = std::move(rendering.riverbank);
+  m_bridge = std::move(rendering.bridge);
+  m_fog = std::move(rendering.fog);
+  m_stone = std::move(rendering.stone);
+  m_plant = std::move(rendering.plant);
+  m_pine = std::move(rendering.pine);
+  m_olive = std::move(rendering.olive);
+  m_firecamp = std::move(rendering.firecamp);
+  m_passes = std::move(rendering.passes);
+
+  // Initialize world systems
+  RendererBootstrap::initialize_world_systems(*m_world);
 
 
   m_pickingService = std::make_unique<Game::Systems::PickingService>();
   m_pickingService = std::make_unique<Game::Systems::PickingService>();
   m_victoryService = std::make_unique<Game::Systems::VictoryService>();
   m_victoryService = std::make_unique<Game::Systems::VictoryService>();
@@ -1283,58 +1259,41 @@ void GameEngine::start_skirmish(const QString &map_path,
       m_hoverTracker->update_hover(-1, -1, *m_world, *m_camera, 0, 0);
       m_hoverTracker->update_hover(-1, -1, *m_world, *m_camera, 0, 0);
     }
     }
 
 
-    m_entity_cache.reset();
+    LevelOrchestrator orchestrator;
+    LevelOrchestrator::RendererRefs renderers{
+        m_renderer.get(), m_camera.get(),     m_ground.get(),
+        m_terrain.get(),  m_biome.get(),      m_river.get(),
+        m_road.get(),     m_riverbank.get(),  m_bridge.get(),
+        m_fog.get(),      m_stone.get(),      m_plant.get(),
+        m_pine.get(),     m_olive.get(),      m_firecamp.get()};
 
 
-    Game::Map::SkirmishLoader loader(*m_world, *m_renderer, *m_camera);
-    loader.set_ground_renderer(m_ground.get());
-    loader.set_terrain_renderer(m_terrain.get());
-    loader.set_biome_renderer(m_biome.get());
-    loader.set_river_renderer(m_river.get());
-    loader.set_road_renderer(m_road.get());
-    loader.set_riverbank_renderer(m_riverbank.get());
-    loader.set_bridge_renderer(m_bridge.get());
-    loader.set_fog_renderer(m_fog.get());
-    loader.set_stone_renderer(m_stone.get());
-    loader.set_plant_renderer(m_plant.get());
-    loader.set_pine_renderer(m_pine.get());
-    loader.set_olive_renderer(m_olive.get());
-    loader.set_fire_camp_renderer(m_firecamp.get());
-
-    loader.set_on_owners_updated([this]() { emit owner_info_changed(); });
-
-    loader.set_on_visibility_mask_ready([this]() {
+    auto visibility_ready = [this]() {
       m_runtime.visibility_version =
       m_runtime.visibility_version =
           Game::Map::VisibilityService::instance().version();
           Game::Map::VisibilityService::instance().version();
       m_runtime.visibility_update_accumulator = 0.0F;
       m_runtime.visibility_update_accumulator = 0.0F;
-    });
+    };
+
+    auto owner_update = [this]() { emit owner_info_changed(); };
 
 
-    int updated_player_id = m_selected_player_id;
-    auto result = loader.start(map_path, playerConfigs, m_selected_player_id,
-                               updated_player_id);
+    auto load_result = orchestrator.load_skirmish(
+        map_path, playerConfigs, m_selected_player_id, *m_world, renderers,
+        m_level, m_entity_cache, m_victoryService.get(),
+        m_minimap_manager.get(), visibility_ready, owner_update);
 
 
-    if (updated_player_id != m_selected_player_id) {
-      m_selected_player_id = updated_player_id;
+    if (load_result.updated_player_id != m_selected_player_id) {
+      m_selected_player_id = load_result.updated_player_id;
       emit selected_player_id_changed();
       emit selected_player_id_changed();
     }
     }
 
 
-    if (!result.ok && !result.errorMessage.isEmpty()) {
-      set_error(result.errorMessage);
+    if (!load_result.success) {
+      set_error(load_result.error_message);
+      m_runtime.loading = false;
+      return;
     }
     }
 
 
-    m_runtime.local_owner_id = updated_player_id;
-    m_level.map_name = result.map_name;
-    m_level.player_unit_id = result.player_unit_id;
-    m_level.cam_fov = result.cam_fov;
-    m_level.cam_near = result.cam_near;
-    m_level.cam_far = result.cam_far;
-    m_level.max_troops_per_player = result.max_troops_per_player;
-
-    Game::GameConfig::instance().set_max_troops_per_player(
-        result.max_troops_per_player);
+    m_runtime.local_owner_id = load_result.updated_player_id;
 
 
     if (m_victoryService) {
     if (m_victoryService) {
-      m_victoryService->configure(result.victoryConfig,
-                                  m_runtime.local_owner_id);
       m_victoryService->setVictoryCallback([this](const QString &state) {
       m_victoryService->setVictoryCallback([this](const QString &state) {
         if (m_runtime.victory_state != state) {
         if (m_runtime.victory_state != state) {
           m_runtime.victory_state = state;
           m_runtime.victory_state = state;
@@ -1347,44 +1306,9 @@ void GameEngine::start_skirmish(const QString &map_path,
       });
       });
     }
     }
 
 
-    if (result.has_focus_position && m_camera) {
-      const auto &cam_config = Game::GameConfig::instance().camera();
-      m_camera->set_rts_view(result.focusPosition, cam_config.default_distance,
-                             cam_config.default_pitch, cam_config.default_yaw);
-    }
-
-    Game::Map::MapDefinition map_def;
-    QString map_error;
-    if (Game::Map::MapLoader::loadFromJsonFile(map_path, map_def, &map_error)) {
-      if (m_minimap_manager) {
-        m_minimap_manager->generate_for_map(map_def);
-      }
-    } else {
-      qWarning() << "GameEngine: Failed to load map for minimap generation:"
-                 << map_error;
-    }
-
     m_runtime.loading = false;
     m_runtime.loading = false;
 
 
-    if (auto *ai_system = m_world->get_system<Game::Systems::AISystem>()) {
-      ai_system->reinitialize();
-    }
-
     rebuild_entity_cache();
     rebuild_entity_cache();
-    auto &troops = Game::Systems::TroopCountRegistry::instance();
-    troops.rebuild_from_world(*m_world);
-
-    auto &stats_registry = Game::Systems::GlobalStatsRegistry::instance();
-    stats_registry.rebuild_from_world(*m_world);
-
-    auto &owner_registry = Game::Systems::OwnerRegistry::instance();
-    const auto &all_owners = owner_registry.get_all_owners();
-    for (const auto &owner : all_owners) {
-      if (owner.type == Game::Systems::OwnerType::Player ||
-          owner.type == Game::Systems::OwnerType::AI) {
-        stats_registry.mark_game_start(owner.owner_id);
-      }
-    }
 
 
     m_ambient_state_manager = std::make_unique<AmbientStateManager>();
     m_ambient_state_manager = std::make_unique<AmbientStateManager>();
 
 

+ 1 - 0
app/core/game_engine.h

@@ -12,6 +12,7 @@
 #include "game/core/event_manager.h"
 #include "game/core/event_manager.h"
 #include "game/systems/game_state_serializer.h"
 #include "game/systems/game_state_serializer.h"
 #include "minimap_manager.h"
 #include "minimap_manager.h"
+#include "renderer_bootstrap.h"
 #include <QJsonObject>
 #include <QJsonObject>
 #include <QList>
 #include <QList>
 #include <QMatrix4x4>
 #include <QMatrix4x4>

+ 114 - 0
app/core/level_orchestrator.cpp

@@ -0,0 +1,114 @@
+#include "level_orchestrator.h"
+
+#include "game/core/world.h"
+#include "game/game_config.h"
+#include "game/map/map_loader.h"
+#include "game/map/skirmish_loader.h"
+#include "game/systems/ai_system.h"
+#include "game/systems/game_state_serializer.h"
+#include "game/systems/global_stats_registry.h"
+#include "game/systems/owner_registry.h"
+#include "game/systems/troop_count_registry.h"
+#include "game/systems/victory_service.h"
+#include "minimap_manager.h"
+#include "render/gl/camera.h"
+#include "render/scene_renderer.h"
+#include <QDebug>
+
+auto LevelOrchestrator::load_skirmish(
+    const QString &map_path, const QVariantList &player_configs,
+    int selected_player_id, Engine::Core::World &world,
+    const RendererRefs &renderers, Game::Systems::LevelSnapshot &level,
+    EntityCache &entity_cache, Game::Systems::VictoryService *victory_service,
+    MinimapManager *minimap_manager, VisibilityReadyCallback visibility_ready,
+    OwnerUpdateCallback owner_update) -> LevelLoadResult {
+
+  LevelLoadResult result;
+  result.updated_player_id = selected_player_id;
+
+  entity_cache.reset();
+
+  Game::Map::SkirmishLoader loader(world, *renderers.renderer,
+                                   *renderers.camera);
+  loader.set_ground_renderer(renderers.ground);
+  loader.set_terrain_renderer(renderers.terrain);
+  loader.set_biome_renderer(renderers.biome);
+  loader.set_river_renderer(renderers.river);
+  loader.set_road_renderer(renderers.road);
+  loader.set_riverbank_renderer(renderers.riverbank);
+  loader.set_bridge_renderer(renderers.bridge);
+  loader.set_fog_renderer(renderers.fog);
+  loader.set_stone_renderer(renderers.stone);
+  loader.set_plant_renderer(renderers.plant);
+  loader.set_pine_renderer(renderers.pine);
+  loader.set_olive_renderer(renderers.olive);
+  loader.set_fire_camp_renderer(renderers.firecamp);
+
+  loader.set_on_owners_updated(owner_update);
+  loader.set_on_visibility_mask_ready(visibility_ready);
+
+  auto load_result = loader.start(map_path, player_configs, selected_player_id,
+                                   result.updated_player_id);
+
+  if (!load_result.ok) {
+    result.success = false;
+    result.error_message = load_result.errorMessage;
+    return result;
+  }
+
+  level.map_name = load_result.map_name;
+  level.player_unit_id = load_result.player_unit_id;
+  level.cam_fov = load_result.cam_fov;
+  level.cam_near = load_result.cam_near;
+  level.cam_far = load_result.cam_far;
+  level.max_troops_per_player = load_result.max_troops_per_player;
+
+  Game::GameConfig::instance().set_max_troops_per_player(
+      load_result.max_troops_per_player);
+
+  if (victory_service) {
+    victory_service->configure(load_result.victoryConfig,
+                               result.updated_player_id);
+  }
+
+  if (load_result.has_focus_position && renderers.camera) {
+    const auto &cam_config = Game::GameConfig::instance().camera();
+    renderers.camera->set_rts_view(load_result.focusPosition,
+                                   cam_config.default_distance,
+                                   cam_config.default_pitch,
+                                   cam_config.default_yaw);
+  }
+
+  Game::Map::MapDefinition map_def;
+  QString map_error;
+  if (Game::Map::MapLoader::loadFromJsonFile(map_path, map_def, &map_error)) {
+    if (minimap_manager) {
+      minimap_manager->generate_for_map(map_def);
+    }
+  } else {
+    qWarning() << "LevelOrchestrator: Failed to load map for minimap:"
+               << map_error;
+  }
+
+  if (auto *ai_system = world.get_system<Game::Systems::AISystem>()) {
+    ai_system->reinitialize();
+  }
+
+  auto &troops = Game::Systems::TroopCountRegistry::instance();
+  troops.rebuild_from_world(world);
+
+  auto &stats_registry = Game::Systems::GlobalStatsRegistry::instance();
+  stats_registry.rebuild_from_world(world);
+
+  auto &owner_registry = Game::Systems::OwnerRegistry::instance();
+  const auto &all_owners = owner_registry.get_all_owners();
+  for (const auto &owner : all_owners) {
+    if (owner.type == Game::Systems::OwnerType::Player ||
+        owner.type == Game::Systems::OwnerType::AI) {
+      stats_registry.mark_game_start(owner.owner_id);
+    }
+  }
+
+  result.success = true;
+  return result;
+}

+ 74 - 0
app/core/level_orchestrator.h

@@ -0,0 +1,74 @@
+#pragma once
+
+#include <QString>
+#include <QVariantList>
+#include <functional>
+#include <memory>
+
+namespace Engine::Core {
+class World;
+}
+
+namespace Render::GL {
+class Renderer;
+class Camera;
+class GroundRenderer;
+class TerrainRenderer;
+class BiomeRenderer;
+class RiverRenderer;
+class RoadRenderer;
+class RiverbankRenderer;
+class BridgeRenderer;
+class FogRenderer;
+class StoneRenderer;
+class PlantRenderer;
+class PineRenderer;
+class OliveRenderer;
+class FireCampRenderer;
+} // namespace Render::GL
+
+namespace Game::Systems {
+struct LevelSnapshot;
+class VictoryService;
+} // namespace Game::Systems
+
+class MinimapManager;
+class EntityCache;
+
+struct LevelLoadResult {
+  bool success = false;
+  QString error_message;
+  int updated_player_id = 1;
+};
+
+class LevelOrchestrator {
+public:
+  struct RendererRefs {
+    Render::GL::Renderer *renderer;
+    Render::GL::Camera *camera;
+    Render::GL::GroundRenderer *ground;
+    Render::GL::TerrainRenderer *terrain;
+    Render::GL::BiomeRenderer *biome;
+    Render::GL::RiverRenderer *river;
+    Render::GL::RoadRenderer *road;
+    Render::GL::RiverbankRenderer *riverbank;
+    Render::GL::BridgeRenderer *bridge;
+    Render::GL::FogRenderer *fog;
+    Render::GL::StoneRenderer *stone;
+    Render::GL::PlantRenderer *plant;
+    Render::GL::PineRenderer *pine;
+    Render::GL::OliveRenderer *olive;
+    Render::GL::FireCampRenderer *firecamp;
+  };
+
+  using VisibilityReadyCallback = std::function<void()>;
+  using OwnerUpdateCallback = std::function<void()>;
+
+  LevelLoadResult load_skirmish(
+      const QString &map_path, const QVariantList &player_configs,
+      int selected_player_id, Engine::Core::World &world,
+      const RendererRefs &renderers, Game::Systems::LevelSnapshot &level,
+      EntityCache &entity_cache, Game::Systems::VictoryService *victory_service,
+      MinimapManager *minimap_manager, VisibilityReadyCallback visibility_ready,
+      OwnerUpdateCallback owner_update);
+};

+ 79 - 0
app/core/renderer_bootstrap.cpp

@@ -0,0 +1,79 @@
+#include "renderer_bootstrap.h"
+
+#include "game/core/world.h"
+#include "game/systems/ai_system.h"
+#include "game/systems/arrow_system.h"
+#include "game/systems/ballista_attack_system.h"
+#include "game/systems/capture_system.h"
+#include "game/systems/catapult_attack_system.h"
+#include "game/systems/cleanup_system.h"
+#include "game/systems/combat_system.h"
+#include "game/systems/healing_system.h"
+#include "game/systems/movement_system.h"
+#include "game/systems/patrol_system.h"
+#include "game/systems/production_system.h"
+#include "game/systems/projectile_system.h"
+#include "game/systems/selection_system.h"
+#include "game/systems/terrain_alignment_system.h"
+#include "render/gl/camera.h"
+#include "render/ground/biome_renderer.h"
+#include "render/ground/bridge_renderer.h"
+#include "render/ground/firecamp_renderer.h"
+#include "render/ground/fog_renderer.h"
+#include "render/ground/ground_renderer.h"
+#include "render/ground/olive_renderer.h"
+#include "render/ground/pine_renderer.h"
+#include "render/ground/plant_renderer.h"
+#include "render/ground/river_renderer.h"
+#include "render/ground/riverbank_renderer.h"
+#include "render/ground/road_renderer.h"
+#include "render/ground/stone_renderer.h"
+#include "render/ground/terrain_renderer.h"
+#include "render/scene_renderer.h"
+
+auto RendererBootstrap::initialize_rendering() -> RenderingComponents {
+  RenderingComponents components;
+
+  components.renderer = std::make_unique<Render::GL::Renderer>();
+  components.camera = std::make_unique<Render::GL::Camera>();
+  components.ground = std::make_unique<Render::GL::GroundRenderer>();
+  components.terrain = std::make_unique<Render::GL::TerrainRenderer>();
+  components.biome = std::make_unique<Render::GL::BiomeRenderer>();
+  components.river = std::make_unique<Render::GL::RiverRenderer>();
+  components.road = std::make_unique<Render::GL::RoadRenderer>();
+  components.riverbank = std::make_unique<Render::GL::RiverbankRenderer>();
+  components.bridge = std::make_unique<Render::GL::BridgeRenderer>();
+  components.fog = std::make_unique<Render::GL::FogRenderer>();
+  components.stone = std::make_unique<Render::GL::StoneRenderer>();
+  components.plant = std::make_unique<Render::GL::PlantRenderer>();
+  components.pine = std::make_unique<Render::GL::PineRenderer>();
+  components.olive = std::make_unique<Render::GL::OliveRenderer>();
+  components.firecamp = std::make_unique<Render::GL::FireCampRenderer>();
+
+  components.passes = {components.ground.get(),  components.terrain.get(),
+                       components.river.get(),    components.road.get(),
+                       components.riverbank.get(), components.bridge.get(),
+                       components.biome.get(),    components.stone.get(),
+                       components.plant.get(),    components.pine.get(),
+                       components.olive.get(),    components.firecamp.get(),
+                       components.fog.get()};
+
+  return components;
+}
+
+void RendererBootstrap::initialize_world_systems(Engine::Core::World &world) {
+  world.add_system(std::make_unique<Game::Systems::ArrowSystem>());
+  world.add_system(std::make_unique<Game::Systems::ProjectileSystem>());
+  world.add_system(std::make_unique<Game::Systems::MovementSystem>());
+  world.add_system(std::make_unique<Game::Systems::PatrolSystem>());
+  world.add_system(std::make_unique<Game::Systems::CombatSystem>());
+  world.add_system(std::make_unique<Game::Systems::CatapultAttackSystem>());
+  world.add_system(std::make_unique<Game::Systems::BallistaAttackSystem>());
+  world.add_system(std::make_unique<Game::Systems::HealingSystem>());
+  world.add_system(std::make_unique<Game::Systems::CaptureSystem>());
+  world.add_system(std::make_unique<Game::Systems::AISystem>());
+  world.add_system(std::make_unique<Game::Systems::ProductionSystem>());
+  world.add_system(std::make_unique<Game::Systems::TerrainAlignmentSystem>());
+  world.add_system(std::make_unique<Game::Systems::CleanupSystem>());
+  world.add_system(std::make_unique<Game::Systems::SelectionSystem>());
+}

+ 53 - 0
app/core/renderer_bootstrap.h

@@ -0,0 +1,53 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+
+namespace Render::GL {
+class Renderer;
+class Camera;
+class ResourceManager;
+class GroundRenderer;
+class TerrainRenderer;
+class BiomeRenderer;
+class RiverRenderer;
+class RoadRenderer;
+class RiverbankRenderer;
+class BridgeRenderer;
+class FogRenderer;
+class StoneRenderer;
+class PlantRenderer;
+class PineRenderer;
+class OliveRenderer;
+class FireCampRenderer;
+struct IRenderPass;
+} // namespace Render::GL
+
+namespace Engine::Core {
+class World;
+}
+
+class RendererBootstrap {
+public:
+  struct RenderingComponents {
+    std::unique_ptr<Render::GL::Renderer> renderer;
+    std::unique_ptr<Render::GL::Camera> camera;
+    std::unique_ptr<Render::GL::GroundRenderer> ground;
+    std::unique_ptr<Render::GL::TerrainRenderer> terrain;
+    std::unique_ptr<Render::GL::BiomeRenderer> biome;
+    std::unique_ptr<Render::GL::RiverRenderer> river;
+    std::unique_ptr<Render::GL::RoadRenderer> road;
+    std::unique_ptr<Render::GL::RiverbankRenderer> riverbank;
+    std::unique_ptr<Render::GL::BridgeRenderer> bridge;
+    std::unique_ptr<Render::GL::FogRenderer> fog;
+    std::unique_ptr<Render::GL::StoneRenderer> stone;
+    std::unique_ptr<Render::GL::PlantRenderer> plant;
+    std::unique_ptr<Render::GL::PineRenderer> pine;
+    std::unique_ptr<Render::GL::OliveRenderer> olive;
+    std::unique_ptr<Render::GL::FireCampRenderer> firecamp;
+    std::vector<Render::GL::IRenderPass *> passes;
+  };
+
+  static RenderingComponents initialize_rendering();
+  static void initialize_world_systems(Engine::Core::World &world);
+};