diff --git a/client/src/game_state.cpp b/client/src/game_state.cpp new file mode 100644 index 0000000..9f70213 --- /dev/null +++ b/client/src/game_state.cpp @@ -0,0 +1,81 @@ +#include +#include +#include + +#include "game_state.h" +#include "gfx/shape_renderer.h" +#include "gfx/txt_renderer.h" +#include "terminal.h" +#include "ui/desktop.h" +#include "ui/ui_window.h" + +GameState::GameState(void) = default; + +GameState::~GameState(void) = default; + +void GameState::init(void) { + /* Create and connect the network client. */ + _network = std::make_unique(); + if(_network->connect("127.0.0.1", 1337)) { + /* TODO: handle connection success message. */ + } else { + /* TODO: handle connection failure. */ + } + + /* Create the desktop. */ + _desktop = std::make_unique(); + + /* + * Create initial terminal window. + */ + auto term = std::make_unique(_network.get()); /* Pass network connection. */ + auto term_window = std::make_unique("Terminal", 100, 100, 800, 500); + term_window->set_content(std::move(term)); + _desktop->add_window(std::move(term_window)); +} + +void GameState::handle_event(SDL_Event* event) { + if(_desktop) { + _desktop->handle_event(event); + } +} + +void GameState::update(void) { + std::string server_msg; + while(_network->poll_message(server_msg)) { + UIWindow* focused_window = _desktop->get_focused_window(); + if(!focused_window) continue; + + Terminal* terminal = focused_window->get_content(); + if(!terminal) continue; + + /* Server sends "output\nprompt", split them. */ + size_t last_newline = server_msg.find_last_of("\n"); + if(last_newline != std::string::npos) { + std::string prompt = server_msg.substr(last_newline+1); + terminal->set_prompt(prompt); + + std::string output = server_msg.substr(0, last_newline); + if(!output.empty()) { + /* split the multiline output and push each line to history. */ + std::stringstream ss(output); + std::string line; + while(std::getline(ss, line, '\n')) { + terminal->add_history(line); + } + } + } else { + terminal->add_history(server_msg); + } + } + if(_desktop) { + _desktop->update(); + } +} + +void GameState::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, + int screen_height, bool show_cursor) { + if(_desktop) { + _desktop->render(shape_renderer, txt_renderer, screen_height, show_cursor); + } +} diff --git a/client/src/game_state.h b/client/src/game_state.h new file mode 100644 index 0000000..b6b1d46 --- /dev/null +++ b/client/src/game_state.h @@ -0,0 +1,25 @@ +#pragma once + +#include + +class ClientNetwork; +class Desktop; +class ShapeRenderer; +class TextRenderer; +union SDL_Event; + +class GameState { +public: + GameState(void); + ~GameState(void); + + void init(void); + void handle_event(SDL_Event* event); + void update(void); + void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, + int screen_height, bool show_cursor); + +private: + std::unique_ptr _network; + std::unique_ptr _desktop; +}; diff --git a/client/src/main.cpp b/client/src/main.cpp index ec72746..77f000c 100644 --- a/client/src/main.cpp +++ b/client/src/main.cpp @@ -10,10 +10,9 @@ #include #include "../../server/src/network_manager.h" -#include "terminal.h" #include "gfx/shape_renderer.h" -#include "ui/desktop.h" -#include "ui/ui_window.h" +#include "gfx/txt_renderer.h" +#include "game_state.h" void run_server(void) { try { @@ -104,16 +103,8 @@ int main(int argc, char** argv) { /* Init shape renderer. */ ShapeRenderer* shape_renderer_instance = new ShapeRenderer(SCREEN_WIDTH, SCREEN_HEIGHT); - /* Create terminal. */ - auto term = std::make_unique(); - - /* Create UI window and pass it a terminal. */ - auto test_window = std::make_unique("Terminal", 100, 100, 800, 500); - test_window->set_content(std::move(term)); - - /* Create desktop and add the window. */ - auto desktop = std::make_unique(); - desktop->add_window(std::move(test_window)); + auto game_state = std::make_unique(); + game_state->init(); /* timer for cursor blink. */ Uint32 last_blink_time = 0; @@ -125,10 +116,10 @@ int main(int argc, char** argv) { SDL_Event event; while(SDL_PollEvent(&event)) { if(event.type == SDL_EVENT_QUIT) { running = false; } - desktop.get()->handle_event(&event); + game_state->handle_event(&event); } - desktop.get()->update(); + game_state->update(); Uint32 current_time = SDL_GetTicks(); if(current_time - last_blink_time > 500) { /* Every 500ms. */ @@ -140,14 +131,14 @@ int main(int argc, char** argv) { glClearColor(0.1f, 0.1f, 0.1, 1.0f); glClear(GL_COLOR_BUFFER_BIT); - desktop.get()->render(shape_renderer_instance, txt_render_instance, SCREEN_HEIGHT, show_cursor); + game_state->render(shape_renderer_instance, txt_render_instance, SCREEN_HEIGHT, show_cursor); /* It's really odd to call it SwapWindow now, rather than SwapBuffer. */ SDL_GL_SwapWindow(window); } /* Cleanup. */ - desktop.reset(); + game_state.reset(); delete shape_renderer_instance; delete txt_render_instance; SDL_GL_DestroyContext(context); diff --git a/client/src/terminal.cpp b/client/src/terminal.cpp index 6f47146..3fa6084 100644 --- a/client/src/terminal.cpp +++ b/client/src/terminal.cpp @@ -1,73 +1,44 @@ #include -#include #include #include #include -#include #include "terminal.h" #include "client_network.h" #include "gfx/txt_renderer.h" -Terminal::Terminal(void) { +Terminal::Terminal(ClientNetwork* network) : _network(network) { /* Placeholder welcome message to history. */ - _history.push_back("Welcome to Bettola"); - _history.push_back("Connecting to server..."); - - _network = std::make_unique(); _should_close = false; _scroll_offset = 0; _prompt = ""; - - /* TODO: Move network to main.cpp, or better yet, a dedicatated game state file */ - if(_network->connect("127.0.0.1", 1337)) { - _history.push_back("Connection successful."); - } else { - _history.push_back("Connection failed. Please restart."); - _prompt = "error>"; - } } Terminal::~Terminal(void) {} void Terminal::update(void) { - std::string server_msg; - while(_network->poll_message(server_msg)) { - if(server_msg == "__CLOSE_CONNECTION__") { - _history.push_back("Connection closed by server."); - _should_close = true; - return; - } - /* Server will send "output\nprompt". Split them. */ - size_t last_newline = server_msg.find_last_of('\n'); - if(last_newline != std::string::npos) { - _prompt = server_msg.substr(last_newline+1); - std::string output = server_msg.substr(0, last_newline); - if(!output.empty()) { - /* Split multiline output and push each line to history. */ - std::stringstream ss(output); - std::string line; - while(std::getline(ss, line, '\n')) { - /* Replace tabs. */ - std::string line_with_spaces; - for(char ch : line) { - if(ch == '\t') { - line_with_spaces += " "; - } else { - line_with_spaces += ch; - } - } - _history.push_back(line_with_spaces); - } - } + +} + +void Terminal::add_history(const std::string& line) { + std::string line_with_spaces; + for(char ch : line) { + if(ch == '\t') { + line_with_spaces += " "; } else { - /* - * If there's no newline, it might be the initial welcome message, - * or some other non-standard message, just it to history. - */ - _history.push_back(server_msg); + line_with_spaces += ch; } } + _history.push_back(line_with_spaces); + + if(line == "__CLOSE_CONNECTION__") { + _history.back() = "Connection closed by server."; + _should_close = true; + } +} + +void Terminal::set_prompt(const std::string& prompt) { + _prompt = prompt; } bool Terminal::close(void) { return _should_close; } diff --git a/client/src/terminal.h b/client/src/terminal.h index 5df9451..7224683 100644 --- a/client/src/terminal.h +++ b/client/src/terminal.h @@ -1,5 +1,4 @@ #pragma once -#include #include #include #include @@ -9,13 +8,15 @@ class Terminal { public: - Terminal(void); + Terminal(ClientNetwork* network); ~Terminal(void); void update(void); void handle_input(SDL_Event* event); void render(TextRenderer* renderer, int x, int y, int width, int height, bool show_cursor); void scroll(int amount, int content_height); + void add_history(const std::string& line); + void set_prompt(const std::string& prompt); bool close(void); private: @@ -26,5 +27,5 @@ private: std::vector _history; int _scroll_offset; std::string _prompt; - std::unique_ptr _network; + ClientNetwork* _network; }; diff --git a/client/src/ui/desktop.cpp b/client/src/ui/desktop.cpp index fab0cc8..4ab45f7 100644 --- a/client/src/ui/desktop.cpp +++ b/client/src/ui/desktop.cpp @@ -55,14 +55,7 @@ void Desktop::handle_event(SDL_Event* event) { } void Desktop::update(void) { - /* Poll all windows for network updates. */ - for(auto& window : _windows) { - Terminal* term = window->get_content(); - if(term) { - term->update(); - } - } - + /* Remove closed windows. */ _windows.erase(std::remove_if(_windows.begin(), _windows.end(), [](const std::unique_ptr& window) { Terminal* term = window->get_content(); @@ -71,6 +64,10 @@ void Desktop::update(void) { _windows.end()); } +UIWindow* Desktop::get_focused_window(void) { + return _focused_window; +} + void Desktop::render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, int screen_height, bool show_cursor) { for(const auto& win : _windows) { diff --git a/client/src/ui/desktop.h b/client/src/ui/desktop.h index 9a32ca6..3b8925f 100644 --- a/client/src/ui/desktop.h +++ b/client/src/ui/desktop.h @@ -19,6 +19,8 @@ public: void render(ShapeRenderer* shape_renderer, TextRenderer* txt_renderer, int screen_height, bool show_cursor); + UIWindow* get_focused_window(void); + private: std::vector> _windows; UIWindow* _focused_window;