OpenRA3 v0.0.1: C++26 modules, BIG4/RefPack reader, minimal skirmish

This commit is contained in:
EnderTheCoder
2026-09-12 00:26:45 +08:00
commit 3ad380c81e
24 changed files with 2630 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
module;
#include <cstdint>
#include <memory>
#include <string_view>
export module ra3.client;
import ra3.core;
import ra3.logic;
/**
* The presentation layer: an abstract output surface plus the client facade
* that owns the simulation and drives the frame loop.
*
* A future W3D/D3D9 backend implements the same `display` interface; the
* default headless backend keeps OpenRA3 runnable on a CPU-only box.
*/
export namespace ra3::client {
using ra3::core::uint32;
/**
* Abstract output surface presented once per logic frame.
*/
class display {
public:
virtual ~display() = default;
virtual auto begin_frame() -> void = 0;
virtual auto end_frame() -> void = 0;
[[nodiscard]] virtual auto name() const -> std::string_view = 0;
};
/**
* A display that renders nothing and consumes no resources.
*/
class headless_display final : public display {
public:
auto begin_frame() -> void override {}
auto end_frame() -> void override {}
[[nodiscard]] auto name() const -> std::string_view override { return "headless"; }
};
/**
* Owns the simulation and its display, and drives the frame loop.
*/
class game_client {
public:
game_client() = default;
[[nodiscard]] auto logic() -> logic::game_logic & { return logic_; }
[[nodiscard]] auto display() -> client::display & { return *display_; }
auto set_display(std::unique_ptr<client::display> value) -> void { display_ = std::move(value); }
/**
* Run `frames` logic steps, bracketing each with a present.
*
* @param target Simulation to advance.
* @param frames Number of 30 Hz logic frames to run.
*/
auto run(logic::game_logic &target, uint32 frames) -> void {
for (uint32 i = 0; i < frames; ++i) {
display_->begin_frame();
target.update();
display_->end_frame();
}
}
private:
logic::game_logic logic_;
std::unique_ptr<client::display> display_ = std::make_unique<headless_display>();
};
}