Refactor: Split main.zig into modular game components#17
Conversation
This PR implements the remaining high-priority SOLID refactoring task: splitting the monolithic . - ****: Extracted and definitions. - ****: Extracted UI rendering logic for menus. - ****: Extracted seed generation utilities. - ****: Encapsulated the main application logic (init, run, deinit) into an struct. - ****: Reduced to a minimal entry point. This significantly improves SRP and maintainability.
|
/oc can you do a indepth code review of this PR |
Code Review: Refactor main.zig into Modular Game ComponentsVulkan/OpenGL Parity Issues1. Critical: Shadow Maps Not Implemented for Vulkan
Issue: Shadow maps are entirely disabled for Vulkan: const shadow_map = if (!is_vulkan) ShadowMap.init(rhi, settings.shadow_resolution) catch null else null;Impact: Major feature disparity. Vulkan path completely lacks shadow rendering, cascades, and the entire shadow pipeline. Recommendation: Implement Vulkan shadow mapping via RHI or explicitly document this as a known limitation. 2. Debug Visualization OpenGL-Only
Issue: Debug shadow visualization ( if (self.debug_shadows and self.debug_shader != null and self.shadow_map != null) {
self.debug_shader.?.use();
c.glBindVertexArray().?(self.debug_quad_vao); // OpenGL calls
// ...
}Impact: Debug shadow toggle ( 3. Atmosphere/Clouds API Divergence
Issue: Different initialization and rendering APIs:
Impact: Cloud rendering (line 578) only executes on OpenGL: 4. VSync Handling Inconsistency
Issue: Different VSync configuration paths:
Risk: Settings change at line 349-352 calls SOLID Principles Issues1. Single Responsibility: App Struct is a God Object
The
Violation: Clearly violates Single Responsibility Principle. Recommendation: Extract subsystems:
2. Open/Closed: Backend Selection Hardcoded
The init function and render loop have extensive Recommendation: Use strategy pattern with backend-specific implementations behind a unified interface. 3. Interface Segregation: Menus Pass Too Many Dependencies
switch (self.app_state) {
.home => Menus.drawHome(u, screen_w, screen_h, &self.app_state, &self.input, &self.last_state, &self.seed_focused),
.settings => Menus.drawSettings(u, screen_w, screen_h, &self.app_state, &self.settings, &self.input, self.last_state, self.rhi),
.singleplayer => try Menus.drawSingleplayer(u, screen_w, screen_h, &self.app_state, &self.input, &self.seed_input, &self.seed_focused, self.allocator, &self.time, &self.pending_new_world_seed),
}Each menu function takes 7+ parameters. This suggests tight coupling. Recommendation: Create a 4. Dependency Inversion: Direct Dependencies on Engine Modules
App directly imports and knows about all engine internals (Camera, Shader, UISystem, Atmosphere, Clouds, ShadowMap, TextureAtlas, etc.). Violation: High-level module (App) depends on low-level details. Recommendation: App should depend on abstractions (e.g., Memory Management Issues1. Leak: OpenGL Debug Quad Resources Never Freed
Issue: pub fn deinit(self: *App) void {
// ... other cleanup ...
// Missing: c.glDeleteVertexArrays(1, &self.debug_quad_vao);
// Missing: c.glDeleteBuffers(1, &self.debug_quad_vbo);
}Severity: Minor leak (only 2 objects), but should be fixed. 2. Unsafe: App Returned as Raw Pointer
pub fn init(allocator: std.mem.Allocator) !*App { // Returns raw pointer
const app = try allocator.create(App);
// ...
return app;
}
pub fn deinit(self: *App) void {
// ...
self.allocator.destroy(self); // Self-destruction!
}Issue: Recommendation: Return 3. Risk:
|
| Category | Issues | Severity |
|---|---|---|
| Vulkan Parity | Shadow maps missing, debug visualization OpenGL-only, clouds not rendering on Vulkan | HIGH |
| SOLID | App is a god object, tight coupling, no abstraction layer | MEDIUM |
| Memory | Debug quad leak, unsafe self-destruction pattern, potential race in world cleanup | MEDIUM |
Overall: This is a good first step toward modularity, but the App struct still has too many responsibilities and the Vulkan backend is feature-incomplete compared to OpenGL. The memory management issues are real but not catastrophic.
- Updated menus.zig to return MenuAction from drawHome - Updated app.zig to handle MenuAction.quit - Added cleanup for debug_quad_vao/vbo in App.deinit

Summary
This PR addresses the remaining high-priority task from the SOLID refactoring feedback: splitting the monolithic
main.ziginto smaller, focused modules.Changes
src/game/state.zig: DefinesAppStateandSettingsstructs.src/game/menus.zig: Contains UI rendering logic for Home, Settings, and Singleplayer screens.src/game/seed.zig: Utilities for seed generation and parsing.src/game/app.zig: Encapsulates the application lifecycle (init, run, deinit) in anAppstruct.src/main.zig: Reduced to a simple entry point that instantiates and runsApp.Verification
zig build.zig build run -- --backend vulkan(verified menu navigation and world entry).