10#include "../audio/IAudioManager.hpp"
11#include "../audio/NullAudioManager.hpp"
12#include "../audio/RaylibAudioManager.hpp"
22App::App(
int argc,
char** argv) : args(argc, argv) {}
33 auto socket = std::make_unique<TcpSocket>();
40 std::cout <<
"[INFO] Running in headless mode\n";
56 socket->send(
"mct\n");
60 while (
auto event = eventQueue.
pop()) {
68 socket->send(
"sst " + std::to_string(*newSpeed) +
"\n");
72 std::cerr <<
"[Network] " << e.
what() <<
"\n";
76 socket = std::make_unique<TcpSocket>();
97 while (socket.
poll(0)) {
98 std::optional<std::string> line = socket.
recvLine();
101 if (event) queue.
push(*event);
109 auto now = std::chrono::steady_clock::now();
110 if (now -
_lastStuSent < std::chrono::seconds(1))
return;
117 std::cerr <<
"[Network] stu: no response after 3 attempts, disabling uptime polling\n";
123 socket.
send(
"stu\n");
137 for (
int attempt = 1; attempt <=
MAX_RETRIES; attempt++) {
140 socket.
send(
"GRAPHIC\n");
141 std::cerr <<
"[Network] Connected to " << host <<
":" << port <<
"\n";
144 std::cerr <<
"[Network] " << e.
what() <<
" (attempt " << attempt <<
"/" <<
MAX_RETRIES
148 std::cerr <<
"[Network] Retrying in " << s <<
"s... \r";
150 std::this_thread::sleep_for(std::chrono::seconds(1));
156 std::cerr <<
"\n[Network] Could not connect after " <<
MAX_RETRIES <<
" attempts.\n";
volatile sig_atomic_t g_interrupted
static constexpr int MAX_RETRIES
bool _connectWithRetry(TcpSocket &socket, const std::string &host, int port)
Attempts to connect with exponential backoff. Returns true on success.
std::unique_ptr< IAudioManager > _audioManager
std::chrono::steady_clock::time_point _lastStuSent
void _trySendStu(TcpSocket &socket)
Sends stu once per real second and silences it after 3 consecutive non-responses.
bool shouldRun() const
Checks if the application should run based on the parsed arguments.
int exitCode() const
Gets the exit code to return if the application should not run.
void _resetStuState()
Resets stu polling state, called on reconnect.
void pollAndEnqueue(TcpSocket &socket, EventQueue &queue)
Polls the socket for new data and enqueues any received events.
App(int argc, char **argv)
void run()
Runs the application.
ServerConfig getConfig() const
Thread-safe queue for storing events received from the server. Allows for potential multi-threaded be...
void push(Event event)
Pushes an event to the queue. Thread safe.
void clear()
Clears all pending events from the queue. Thread safe.
std::optional< Event > pop()
Pops an event from the queue. Thread safe.
Represents the current state of the game. Knows the world state, some metadata, and how to apply even...
void applyEvent(const Event &e)
Applies an event to the game state, modifying it accordingly and setting the dirty flag.
A headless renderer that outputs the game state to a stream (e.g., console) instead of rendering it g...
static void setLanguage(Language lang)
Pure interface for rendering the game state.
virtual std::optional< int > getPendingSpeedChange()=0
virtual bool shouldClose()=0
virtual void setState(const GameState &state)=0
virtual void shutdown()=0
virtual void setDevMode(bool dev, int port, const std::string &machine)=0
virtual void handleInput()=0
static std::optional< Event > parse(std::string_view input)
Parses a raw input string from the server and converts it into an Event variant. This method stops at...
A renderer that uses Raylib to display the game state graphically.
Exception class for TCP errors.
const char * what() const noexcept override
Simple TCP socket wrapper.
std::optional< std::string > recvLine()
Receives a line of text from the socket.
void send(const std::string &data)
Sends data through the socket.
bool poll(int timeout_ms)
Polls the socket for incoming data.
void connect(const std::string &host, int port)
Connects to a remote host.
Represents the configuration for the application, including the port, machine, and headless mode.