diff --git a/include/Cubed/app.hpp b/include/Cubed/app.hpp index 2aef875..cd4a506 100644 --- a/include/Cubed/app.hpp +++ b/include/Cubed/app.hpp @@ -68,7 +68,6 @@ private: void init(int argc, char** argv); void handle_argument(int argc, char** argv); - void handle_toml(); auto init_camera(); auto init_texture(); auto init_world(); diff --git a/include/Cubed/argument.hpp b/include/Cubed/argument.hpp index 88a1ee0..2b0c4fd 100644 --- a/include/Cubed/argument.hpp +++ b/include/Cubed/argument.hpp @@ -1,11 +1,12 @@ #pragma once +#include #include namespace Cubed { struct Argument { - bool is_client = false; - int port = 25530; - std::string ip{"127.0.0.1"}; - std::string player{"Unknown"}; - bool debug_on = true; + std::optional port; + std::optional ip; + std::optional player; + std::optional debug_on; + std::optional language; }; } // namespace Cubed \ No newline at end of file diff --git a/include/Cubed/tools/net_error.hpp b/include/Cubed/tools/net_error.hpp new file mode 100644 index 0000000..454235b --- /dev/null +++ b/include/Cubed/tools/net_error.hpp @@ -0,0 +1,78 @@ +#pragma once + +#include +#include + +namespace Cubed { + +inline std::string_view net_error_message(const asio::error_code& ec) { + if (!ec) + return "No error."; + +#define NET_CASE(err, msg) \ + if (ec == asio::error::err) { \ + return msg; \ + } + + // ===== basic_errors ===== + + NET_CASE(access_denied, "Access denied.") + NET_CASE(address_family_not_supported, "Address family is not supported.") + NET_CASE(address_in_use, "Address is already in use.") + NET_CASE(already_connected, "Already connected.") + NET_CASE(already_started, "Operation already in progress.") + NET_CASE(broken_pipe, "Broken pipe.") + NET_CASE(connection_aborted, "Connection aborted.") + NET_CASE(connection_refused, "Connection refused by the remote host.") + NET_CASE(connection_reset, "Connection reset by the remote host.") + NET_CASE(bad_descriptor, "Invalid socket or file descriptor.") + NET_CASE(fault, "Bad memory address.") + NET_CASE(host_unreachable, "Host is unreachable.") + NET_CASE(in_progress, "Operation is in progress.") + NET_CASE(interrupted, "Operation interrupted.") + NET_CASE(invalid_argument, "Invalid argument.") + NET_CASE(message_size, "Message is too large.") + NET_CASE(name_too_long, "Name is too long.") + NET_CASE(network_down, "Network is down.") + NET_CASE(network_reset, "Network connection was reset.") + NET_CASE(network_unreachable, "Network is unreachable.") + NET_CASE(no_descriptors, "Too many open sockets or files.") + NET_CASE(no_buffer_space, "No buffer space available.") + NET_CASE(no_memory, "Out of memory.") + NET_CASE(no_permission, "Operation not permitted.") + NET_CASE(no_protocol_option, "Protocol option is unavailable.") + NET_CASE(no_such_device, "No such device.") + NET_CASE(not_connected, "Socket is not connected.") + NET_CASE(not_socket, "Object is not a socket.") + NET_CASE(operation_aborted, "Operation cancelled.") + NET_CASE(operation_not_supported, "Operation is not supported.") + NET_CASE(shut_down, "Connection has been shut down.") + NET_CASE(timed_out, "Operation timed out.") + NET_CASE(try_again, "Temporary failure. Please try again.") + NET_CASE(would_block, "Operation would block.") + + // ===== netdb_errors ===== + + NET_CASE(host_not_found, "Host could not be resolved.") + NET_CASE(host_not_found_try_again, "Temporary DNS resolution failure.") + NET_CASE(no_data, "No address data available.") + NET_CASE(no_recovery, "Non-recoverable DNS error.") + + // ===== addrinfo_errors ===== + + NET_CASE(service_not_found, "Requested service was not found.") + NET_CASE(socket_type_not_supported, "Socket type is not supported.") + + // ===== misc_errors ===== + + NET_CASE(already_open, "Resource is already open.") + NET_CASE(eof, "Connection closed by the remote host.") + NET_CASE(not_found, "Requested item was not found.") + NET_CASE(fd_set_failure, "Too many descriptors for select().") + +#undef NET_CASE + + return "Unknown network error."; +} + +} // namespace Cubed \ No newline at end of file diff --git a/src/app.cpp b/src/app.cpp index ca7eb09..326dc72 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -38,16 +38,20 @@ void App::cursor_position_callback(GLFWwindow* window, double xpos, MouseMoveEvent{static_cast(xpos), static_cast(ypos)}); } void App::init(int argc, char** argv) { - handle_toml(); handle_argument(argc, argv); - auto locate = get_system_locale(); - std::string default_value = "en_US"; - if (locate.country == "CN") { - default_value = "zh_CN"; + if (m_argument.language) { + Localization::instance().load_language(*m_argument.language); + m_game_config.set("language", *m_argument.language); + } else { + auto locate = get_system_locale(); + std::string default_value = "en_US"; + if (locate.country == "CN") { + default_value = "zh_CN"; + } + Localization::instance().load_language( + m_game_config.get("language", default_value)); } - Localization::instance().load_language( - m_game_config.get("language", default_value)); m_window.init(); m_window.imgui_init(); @@ -74,7 +78,9 @@ void App::init(int argc, char** argv) { m_audio.init(); BlockManager::init(); - m_renderer.init(m_argument.debug_on); + if (m_argument.debug_on) { + m_renderer.init(*m_argument.debug_on); + } Logger::info("Renderer Init Success"); // MapTable::init_map(); m_texture_manager.init_texture(); @@ -101,17 +107,13 @@ void App::handle_argument(int argc, char** argv) { std::function> HANDLERS{ - {"--client", [&](ArgParser&) { m_argument.is_client = true; }}, - - {"--host", [&](ArgParser&) { m_argument.is_client = false; }}, - {"-p", [&](ArgParser& p) { auto arg = p.require_next("-p"); - - auto r = std::from_chars(arg.data(), arg.data() + arg.size(), - m_argument.port); - + int port; + auto r = + std::from_chars(arg.data(), arg.data() + arg.size(), port); + m_argument.port = port; if (r.ec != std::errc{} || r.ptr != arg.data() + arg.size()) { throw std::runtime_error( std::format("Invalid port: {}", arg)); @@ -119,7 +121,7 @@ void App::handle_argument(int argc, char** argv) { if (m_argument.port > 65535) { throw std::runtime_error( - std::format("Port {} out of range", m_argument.port)); + std::format("Port {} out of range", *m_argument.port)); } }}, @@ -143,7 +145,14 @@ void App::handle_argument(int argc, char** argv) { [&](ArgParser) { m_argument.debug_on = false; Logger::info("Switch off opengl debug out put"); - }} + }}, + {"--language", + [&](ArgParser& p) { + auto arg = p.require_next("--language"); + m_argument.language = arg; + } + + } }; ArgParser parser(argc, argv); @@ -158,21 +167,6 @@ void App::handle_argument(int argc, char** argv) { } } -void App::handle_toml() { - toml::table server; - try { - server = toml::parse_file("server.toml"); - } catch (const toml::parse_error& e) { - // Logger::warn("Ip toml parse error {}", e.what()); - return; - } - - m_argument.ip = - *TOML::safe_get_value(server, "ip", std::string("127.0.01")); - m_argument.port = *TOML::safe_get_value(server, "port", 25530); - m_argument.is_client = *TOML::safe_get_value(server, "client", false); -} - void App::key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { ImGuiIO& io = ImGui::GetIO(); @@ -749,7 +743,7 @@ int App::start_cubed_application(int argc, char** argv) { try { app.init(argc, argv); - Logger::info("Game Init Finish Start Run..."); + Logger::info("Init Finish Start Run..."); app.run(); return 0; diff --git a/src/dev_panel.cpp b/src/dev_panel.cpp index f14ed92..fb89be9 100644 --- a/src/dev_panel.cpp +++ b/src/dev_panel.cpp @@ -434,7 +434,8 @@ void DevPanel::show_world_tab_item() { if (ImGui::BeginTabItem("world")) { if (ImGui::BeginTabBar("World Kind")) { - if (!m_app.argument().is_client) { + auto& param = m_world_scene.scene_manager().world_scene_param(); + if (param.host_game) { if (ImGui::BeginTabItem("ServerWorld")) { show_server_world_table_bar(); ImGui::EndTabItem(); diff --git a/src/gameplay/network_client.cpp b/src/gameplay/network_client.cpp index 923203c..3192917 100644 --- a/src/gameplay/network_client.cpp +++ b/src/gameplay/network_client.cpp @@ -2,6 +2,7 @@ #include "Cubed/gameplay/client_world.hpp" #include "Cubed/tools/log.hpp" +#include "Cubed/tools/net_error.hpp" #include @@ -44,8 +45,12 @@ asio::awaitable NetworkClient::connect(std::string ip, int port) { Logger::info("NetworkClient Read Loop Started"); m_connected = true; co_return; - + } catch (const asio::system_error& e) { + std::string_view error = net_error_message(e.code()); + Logger::error("Client Error: {}, code {}", error, e.code().value()); + set_error(error); } catch (const std::exception& e) { + Logger::error("Client Error {}", e.what()); set_error(e.what()); } @@ -133,21 +138,17 @@ asio::awaitable NetworkClient::read_loop() { } } } catch (const asio::system_error& e) { - auto ec = e.code(); - set_error(e.what()); - if (ec == asio::error::eof || ec == asio::error::operation_aborted) { - Logger::info("Client disconnected"); - } else { - Logger::warn("Asio Error {}", e.what()); - } + std::string_view error = net_error_message(e.code()); + Logger::error("Client Error: {}, code {}", error, e.code().value()); + set_error(error); close(); } catch (const std::exception& e) { - Logger::error("Session Error {}", e.what()); + Logger::error("Client Error {}", e.what()); set_error(e.what()); close(); } catch (...) { Logger::error("Unknown Error"); - set_error("Unhnown Error"); + set_error("Unknown Error"); close(); } co_return; @@ -179,7 +180,10 @@ void NetworkClient::do_write() { m_socket, asio::buffer(*packet), asio::bind_executor(m_strand, [self](std::error_code ec, size_t) { if (ec) { - Logger::warn("Write Ec {}", ec.message()); + std::string_view error = net_error_message(ec); + Logger::error("Cleint Write Error: {}, code {}", error, + ec.value()); + self->set_error(error); self->close(); return; } diff --git a/src/gameplay/network_server.cpp b/src/gameplay/network_server.cpp index 39d1ca5..d024470 100644 --- a/src/gameplay/network_server.cpp +++ b/src/gameplay/network_server.cpp @@ -1,6 +1,7 @@ #include "Cubed/gameplay/network_server.hpp" #include "Cubed/tools/log.hpp" +#include "Cubed/tools/net_error.hpp" using asio::ip::tcp; namespace Cubed { @@ -61,6 +62,12 @@ asio::awaitable NetworkServer::listen() { } s->start(); } + } catch (const asio::system_error& e) { + if (!m_stopped) { + std::string_view error = net_error_message(e.code()); + Logger::error("Server Error: {}, code {}", error, e.code().value()); + } + } catch (const std::exception& e) { if (!m_stopped) { Logger::error("accept error {}", e.what()); diff --git a/src/gameplay/session.cpp b/src/gameplay/session.cpp index de8f481..c3a3872 100644 --- a/src/gameplay/session.cpp +++ b/src/gameplay/session.cpp @@ -2,6 +2,7 @@ #include "Cubed/gameplay/server_world.hpp" #include "Cubed/tools/log.hpp" +#include "Cubed/tools/net_error.hpp" #include "Cubed/tools/uuid.hpp" using asio::ip::tcp; using namespace google::protobuf; @@ -103,10 +104,10 @@ asio::awaitable Session::read_loop() { auto ec = e.code(); if (ec == asio::error::eof || ec == asio::error::operation_aborted) { - Logger::info("Client disconnected"); } else { - Logger::warn("Asio Error {}", e.what()); + std::string_view error = net_error_message(e.code()); + Logger::error("Server Error: {}, code {}", error, e.code().value()); } close(); @@ -128,7 +129,8 @@ void Session::do_write() { m_socket, asio::buffer(*packet), asio::bind_executor(m_strand, [self](std::error_code ec, size_t) { if (ec) { - Logger::warn("Write Ec {}", ec.message()); + std::string_view error = net_error_message(ec); + Logger::error("Server Error: {}, code {}", error, ec.value()); self->close(); return; } diff --git a/src/scene/world_scene.cpp b/src/scene/world_scene.cpp index aaf86e5..9824ba5 100644 --- a/src/scene/world_scene.cpp +++ b/src/scene/world_scene.cpp @@ -109,7 +109,9 @@ bool WorldScene::handle_event(const Event& e) { } void WorldScene::on_enter() { auto& param = m_scene_manager.world_scene_param(); + m_error_ui.init(); + if (param.host_game) { if (param.seed) { ChunkGenerator::init(*param.seed); @@ -124,7 +126,8 @@ void WorldScene::on_enter() { m_client->start(param.ip, param.port); // init will send packet try { - m_client_world.init(m_argument.player, m_client); + + m_client_world.init(m_argument.player.value_or("Unknown"), m_client); Logger::info("World Init Success"); m_camera.camera_init(&m_client_world.get_player()); @@ -143,8 +146,8 @@ void WorldScene::on_leave() { m_scene_manager.app().window().set_camera(nullptr); m_scene_manager.app().window().set_game_running(false); - - if (!m_argument.is_client) { + auto& param = m_scene_manager.world_scene_param(); + if (param.host_game) { m_server.server_world().stop(); } m_scene_manager.app().audio().stop_bgm(); diff --git a/src/ui/main_menu_ui_manager.cpp b/src/ui/main_menu_ui_manager.cpp index 90363e5..736b2ac 100644 --- a/src/ui/main_menu_ui_manager.cpp +++ b/src/ui/main_menu_ui_manager.cpp @@ -98,7 +98,9 @@ void MainMenuUIManager::init() { player_name.set_text( tr("menu.main.player_name", - arg("name", m_scene.scene_manager().app().argument().player))); + arg("name", + m_scene.scene_manager().app().argument().player.value_or( + "Unknown")))); auto& version = info_layout.add_child