mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
refactor: argument (#33)
* refactor(config): remove TOML config loading and replace is_client with host_game * feat(network): add net_error_message helper and use for error logging
This commit is contained in:
@@ -68,7 +68,6 @@ private:
|
|||||||
|
|
||||||
void init(int argc, char** argv);
|
void init(int argc, char** argv);
|
||||||
void handle_argument(int argc, char** argv);
|
void handle_argument(int argc, char** argv);
|
||||||
void handle_toml();
|
|
||||||
auto init_camera();
|
auto init_camera();
|
||||||
auto init_texture();
|
auto init_texture();
|
||||||
auto init_world();
|
auto init_world();
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
struct Argument {
|
struct Argument {
|
||||||
bool is_client = false;
|
std::optional<int> port;
|
||||||
int port = 25530;
|
std::optional<std::string> ip;
|
||||||
std::string ip{"127.0.0.1"};
|
std::optional<std::string> player;
|
||||||
std::string player{"Unknown"};
|
std::optional<bool> debug_on;
|
||||||
bool debug_on = true;
|
std::optional<std::string> language;
|
||||||
};
|
};
|
||||||
} // namespace Cubed
|
} // namespace Cubed
|
||||||
78
include/Cubed/tools/net_error.hpp
Normal file
78
include/Cubed/tools/net_error.hpp
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <asio/error.hpp>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
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
|
||||||
50
src/app.cpp
50
src/app.cpp
@@ -38,9 +38,12 @@ void App::cursor_position_callback(GLFWwindow* window, double xpos,
|
|||||||
MouseMoveEvent{static_cast<float>(xpos), static_cast<float>(ypos)});
|
MouseMoveEvent{static_cast<float>(xpos), static_cast<float>(ypos)});
|
||||||
}
|
}
|
||||||
void App::init(int argc, char** argv) {
|
void App::init(int argc, char** argv) {
|
||||||
handle_toml();
|
|
||||||
handle_argument(argc, argv);
|
handle_argument(argc, argv);
|
||||||
|
|
||||||
|
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();
|
auto locate = get_system_locale();
|
||||||
std::string default_value = "en_US";
|
std::string default_value = "en_US";
|
||||||
if (locate.country == "CN") {
|
if (locate.country == "CN") {
|
||||||
@@ -48,6 +51,7 @@ void App::init(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
Localization::instance().load_language(
|
Localization::instance().load_language(
|
||||||
m_game_config.get("language", default_value));
|
m_game_config.get("language", default_value));
|
||||||
|
}
|
||||||
|
|
||||||
m_window.init();
|
m_window.init();
|
||||||
m_window.imgui_init();
|
m_window.imgui_init();
|
||||||
@@ -74,7 +78,9 @@ void App::init(int argc, char** argv) {
|
|||||||
|
|
||||||
m_audio.init();
|
m_audio.init();
|
||||||
BlockManager::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");
|
Logger::info("Renderer Init Success");
|
||||||
// MapTable::init_map();
|
// MapTable::init_map();
|
||||||
m_texture_manager.init_texture();
|
m_texture_manager.init_texture();
|
||||||
@@ -101,17 +107,13 @@ void App::handle_argument(int argc, char** argv) {
|
|||||||
std::function<void(ArgParser&)>>
|
std::function<void(ArgParser&)>>
|
||||||
HANDLERS{
|
HANDLERS{
|
||||||
|
|
||||||
{"--client", [&](ArgParser&) { m_argument.is_client = true; }},
|
|
||||||
|
|
||||||
{"--host", [&](ArgParser&) { m_argument.is_client = false; }},
|
|
||||||
|
|
||||||
{"-p",
|
{"-p",
|
||||||
[&](ArgParser& p) {
|
[&](ArgParser& p) {
|
||||||
auto arg = p.require_next("-p");
|
auto arg = p.require_next("-p");
|
||||||
|
int port;
|
||||||
auto r = std::from_chars(arg.data(), arg.data() + arg.size(),
|
auto r =
|
||||||
m_argument.port);
|
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()) {
|
if (r.ec != std::errc{} || r.ptr != arg.data() + arg.size()) {
|
||||||
throw std::runtime_error(
|
throw std::runtime_error(
|
||||||
std::format("Invalid port: {}", arg));
|
std::format("Invalid port: {}", arg));
|
||||||
@@ -119,7 +121,7 @@ void App::handle_argument(int argc, char** argv) {
|
|||||||
|
|
||||||
if (m_argument.port > 65535) {
|
if (m_argument.port > 65535) {
|
||||||
throw std::runtime_error(
|
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) {
|
[&](ArgParser) {
|
||||||
m_argument.debug_on = false;
|
m_argument.debug_on = false;
|
||||||
Logger::info("Switch off opengl debug out put");
|
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);
|
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,
|
void App::key_callback(GLFWwindow* window, int key, int scancode, int action,
|
||||||
int mods) {
|
int mods) {
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
@@ -749,7 +743,7 @@ int App::start_cubed_application(int argc, char** argv) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
app.init(argc, argv);
|
app.init(argc, argv);
|
||||||
Logger::info("Game Init Finish Start Run...");
|
Logger::info("Init Finish Start Run...");
|
||||||
app.run();
|
app.run();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -434,7 +434,8 @@ void DevPanel::show_world_tab_item() {
|
|||||||
if (ImGui::BeginTabItem("world")) {
|
if (ImGui::BeginTabItem("world")) {
|
||||||
|
|
||||||
if (ImGui::BeginTabBar("World Kind")) {
|
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")) {
|
if (ImGui::BeginTabItem("ServerWorld")) {
|
||||||
show_server_world_table_bar();
|
show_server_world_table_bar();
|
||||||
ImGui::EndTabItem();
|
ImGui::EndTabItem();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "Cubed/gameplay/client_world.hpp"
|
#include "Cubed/gameplay/client_world.hpp"
|
||||||
#include "Cubed/tools/log.hpp"
|
#include "Cubed/tools/log.hpp"
|
||||||
|
#include "Cubed/tools/net_error.hpp"
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -44,8 +45,12 @@ asio::awaitable<void> NetworkClient::connect(std::string ip, int port) {
|
|||||||
Logger::info("NetworkClient Read Loop Started");
|
Logger::info("NetworkClient Read Loop Started");
|
||||||
m_connected = true;
|
m_connected = true;
|
||||||
co_return;
|
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) {
|
} catch (const std::exception& e) {
|
||||||
|
|
||||||
Logger::error("Client Error {}", e.what());
|
Logger::error("Client Error {}", e.what());
|
||||||
set_error(e.what());
|
set_error(e.what());
|
||||||
}
|
}
|
||||||
@@ -133,21 +138,17 @@ asio::awaitable<void> NetworkClient::read_loop() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const asio::system_error& e) {
|
} catch (const asio::system_error& e) {
|
||||||
auto ec = e.code();
|
std::string_view error = net_error_message(e.code());
|
||||||
set_error(e.what());
|
Logger::error("Client Error: {}, code {}", error, e.code().value());
|
||||||
if (ec == asio::error::eof || ec == asio::error::operation_aborted) {
|
set_error(error);
|
||||||
Logger::info("Client disconnected");
|
|
||||||
} else {
|
|
||||||
Logger::warn("Asio Error {}", e.what());
|
|
||||||
}
|
|
||||||
close();
|
close();
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
Logger::error("Session Error {}", e.what());
|
Logger::error("Client Error {}", e.what());
|
||||||
set_error(e.what());
|
set_error(e.what());
|
||||||
close();
|
close();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
Logger::error("Unknown Error");
|
Logger::error("Unknown Error");
|
||||||
set_error("Unhnown Error");
|
set_error("Unknown Error");
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
co_return;
|
co_return;
|
||||||
@@ -179,7 +180,10 @@ void NetworkClient::do_write() {
|
|||||||
m_socket, asio::buffer(*packet),
|
m_socket, asio::buffer(*packet),
|
||||||
asio::bind_executor(m_strand, [self](std::error_code ec, size_t) {
|
asio::bind_executor(m_strand, [self](std::error_code ec, size_t) {
|
||||||
if (ec) {
|
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();
|
self->close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "Cubed/gameplay/network_server.hpp"
|
#include "Cubed/gameplay/network_server.hpp"
|
||||||
|
|
||||||
#include "Cubed/tools/log.hpp"
|
#include "Cubed/tools/log.hpp"
|
||||||
|
#include "Cubed/tools/net_error.hpp"
|
||||||
using asio::ip::tcp;
|
using asio::ip::tcp;
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
@@ -61,6 +62,12 @@ asio::awaitable<void> NetworkServer::listen() {
|
|||||||
}
|
}
|
||||||
s->start();
|
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) {
|
} catch (const std::exception& e) {
|
||||||
if (!m_stopped) {
|
if (!m_stopped) {
|
||||||
Logger::error("accept error {}", e.what());
|
Logger::error("accept error {}", e.what());
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "Cubed/gameplay/server_world.hpp"
|
#include "Cubed/gameplay/server_world.hpp"
|
||||||
#include "Cubed/tools/log.hpp"
|
#include "Cubed/tools/log.hpp"
|
||||||
|
#include "Cubed/tools/net_error.hpp"
|
||||||
#include "Cubed/tools/uuid.hpp"
|
#include "Cubed/tools/uuid.hpp"
|
||||||
using asio::ip::tcp;
|
using asio::ip::tcp;
|
||||||
using namespace google::protobuf;
|
using namespace google::protobuf;
|
||||||
@@ -103,10 +104,10 @@ asio::awaitable<void> Session::read_loop() {
|
|||||||
auto ec = e.code();
|
auto ec = e.code();
|
||||||
|
|
||||||
if (ec == asio::error::eof || ec == asio::error::operation_aborted) {
|
if (ec == asio::error::eof || ec == asio::error::operation_aborted) {
|
||||||
|
|
||||||
Logger::info("Client disconnected");
|
Logger::info("Client disconnected");
|
||||||
} else {
|
} 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();
|
close();
|
||||||
@@ -128,7 +129,8 @@ void Session::do_write() {
|
|||||||
m_socket, asio::buffer(*packet),
|
m_socket, asio::buffer(*packet),
|
||||||
asio::bind_executor(m_strand, [self](std::error_code ec, size_t) {
|
asio::bind_executor(m_strand, [self](std::error_code ec, size_t) {
|
||||||
if (ec) {
|
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();
|
self->close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -109,7 +109,9 @@ bool WorldScene::handle_event(const Event& e) {
|
|||||||
}
|
}
|
||||||
void WorldScene::on_enter() {
|
void WorldScene::on_enter() {
|
||||||
auto& param = m_scene_manager.world_scene_param();
|
auto& param = m_scene_manager.world_scene_param();
|
||||||
|
|
||||||
m_error_ui.init();
|
m_error_ui.init();
|
||||||
|
|
||||||
if (param.host_game) {
|
if (param.host_game) {
|
||||||
if (param.seed) {
|
if (param.seed) {
|
||||||
ChunkGenerator::init(*param.seed);
|
ChunkGenerator::init(*param.seed);
|
||||||
@@ -124,7 +126,8 @@ void WorldScene::on_enter() {
|
|||||||
m_client->start(param.ip, param.port);
|
m_client->start(param.ip, param.port);
|
||||||
// init will send packet
|
// init will send packet
|
||||||
try {
|
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");
|
Logger::info("World Init Success");
|
||||||
m_camera.camera_init(&m_client_world.get_player());
|
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_camera(nullptr);
|
||||||
m_scene_manager.app().window().set_game_running(false);
|
m_scene_manager.app().window().set_game_running(false);
|
||||||
|
auto& param = m_scene_manager.world_scene_param();
|
||||||
if (!m_argument.is_client) {
|
if (param.host_game) {
|
||||||
m_server.server_world().stop();
|
m_server.server_world().stop();
|
||||||
}
|
}
|
||||||
m_scene_manager.app().audio().stop_bgm();
|
m_scene_manager.app().audio().stop_bgm();
|
||||||
|
|||||||
@@ -98,7 +98,9 @@ void MainMenuUIManager::init() {
|
|||||||
|
|
||||||
player_name.set_text(
|
player_name.set_text(
|
||||||
tr("menu.main.player_name",
|
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<Label>();
|
auto& version = info_layout.add_child<Label>();
|
||||||
version.set_scale(SCALE);
|
version.set_scale(SCALE);
|
||||||
|
|||||||
Reference in New Issue
Block a user