aboutsummaryrefslogtreecommitdiff
path: root/src/main.cc
diff options
context:
space:
mode:
authorNicolas James <Eele1Ephe7uZahRie@tutanota.com>2025-02-12 21:57:46 +1100
committerNicolas James <Eele1Ephe7uZahRie@tutanota.com>2025-02-12 21:57:46 +1100
commite4483eca01b48b943cd0461e24a74ae1a3139ed4 (patch)
treeed58c3c246e3af1af337697695d780aa31f6ad9a /src/main.cc
parent1cc08c51eb4b0f95c30c0a98ad1fc5ad3459b2df (diff)
Update to most recent version (old initial commit)
Diffstat (limited to 'src/main.cc')
-rw-r--r--src/main.cc193
1 files changed, 0 insertions, 193 deletions
diff --git a/src/main.cc b/src/main.cc
deleted file mode 100644
index 56efb55..0000000
--- a/src/main.cc
+++ /dev/null
@@ -1,193 +0,0 @@
-#include "main.hh"
-
-static void set_signal(const decltype(SIGINT) signal,
- void (*const callback)(int)) {
- struct sigaction sa {};
- sa.sa_handler = callback;
- sa.sa_flags = 0;
- if (sigaction(signal, &sa, nullptr) == -1) {
- throw std::runtime_error("failed to set signal handler for signal " +
- std::to_string(signal));
- }
-}
-
-// Parse arg, store result in dest after casting with boost::lexical_cast.
-template <typename T>
-static bool maybe_parse_arg(std::vector<std::string_view>& args,
- const std::initializer_list<std::string_view>& keys,
- T& dest) noexcept {
- const auto find_it = std::ranges::find_if(args, [&keys](const auto& arg) {
- return std::ranges::find(keys, arg) != std::end(keys);
- });
-
- if (find_it == std::end(args)) {
- return false;
- }
-
- try {
- const auto i = static_cast<unsigned int>(find_it - std::begin(args));
- dest = boost::lexical_cast<T>(args.at(i + 1u));
- } catch (const boost::bad_lexical_cast& e) {
- shared::print::fault("bad type conversion for \"" +
- std::string{*find_it} + "\" arg\n");
- std::exit(EXIT_FAILURE);
- } catch (const std::out_of_range& e) {
- shared::print::fault("missing \"" + std::string{*find_it} + "\" arg\n");
- std::exit(EXIT_FAILURE);
- }
-
- args.erase(find_it, std::next(find_it, 2));
-
- return true;
-}
-
-// Parse arg, return true or false if arg exists.
-static bool
-maybe_parse_arg(std::vector<std::string_view>& args,
- const std::initializer_list<std::string_view>& keys) noexcept {
-
- const auto find_it = std::ranges::find_if(args, [&keys](const auto& arg) {
- return std::ranges::find(keys, arg) != std::end(keys);
- });
-
- if (find_it == std::end(args)) {
- return false;
- }
-
- args.erase(find_it);
- return true;
-}
-
-static void do_server(const std::string_view address,
- const std::string_view port) noexcept {
- try {
- server::main(address, port);
- } catch (const std::exception& e) {
- shared::print::fault(std::string{"exception in server!\n"} +
- " what: " + e.what() + '\n');
- std::exit(EXIT_FAILURE);
- }
-}
-
-static void do_client(const std::string_view address,
- const std::string_view port) noexcept {
- try {
- client::main(address, port);
- } catch (const std::exception& e) {
- shared::print::fault(std::string{"exception in client!\n"} +
- " what: " + e.what() + '\n');
- std::exit(EXIT_FAILURE);
- }
-}
-
-static void init() noexcept {
- // Because we use noexcept liberally, exceptions are often not unwound.
- std::set_terminate([]() {
- try {
- throw;
- } catch (const std::exception& e) {
- shared::print::fault(std::string{"unhandled exception!\n"} +
- " what: " + e.what() + '\n');
-
- constexpr std::size_t BACKTRACE_BUF_SIZE = 64;
- std::array<void*, BACKTRACE_BUF_SIZE> bt_buffer{};
- const int nptrs =
- backtrace(std::data(bt_buffer), std::size(bt_buffer));
- char** strings = backtrace_symbols(std::data(bt_buffer), nptrs);
-
- shared::print::message("\n backtrace:\n", false);
- for (int i = 0; i < nptrs; ++i) {
- shared::print::message(" " + std::string{strings[i]} + '\n',
- false);
- }
- free(strings); // controversial
-
- } catch (...) {
- }
- std::exit(EXIT_FAILURE);
- });
-
- set_signal(SIGPIPE, SIG_IGN);
- set_signal(SIGINT, []([[maybe_unused]] const int signum) {
- shared::print::warn(" interrupt signal received\n", false);
- shared::should_exit = true; // graceful cleanup
- });
-
-#ifndef NDEBUG
- shared::print::debug(
- "This binary is a debug build and should not be used in production.\n",
- false);
-#endif
-}
-
-int main(const int argc, const char* const argv[]) {
- GOOGLE_PROTOBUF_VERIFY_VERSION;
-
- // Default argument values, which starts a multiplayer server with a client.
- std::string address = "0.0.0.0";
- std::string port = "8191";
- bool has_address = false;
- bool has_headless = false;
- {
- std::vector<std::string_view> args;
- for (auto i = 1; i < argc; ++i) {
- args.emplace_back(argv[i]);
- }
-
- if (maybe_parse_arg(args, {"--help", "-h"})) {
- // clang-format off
- std::cout << " --help -h : display this, quit\n"
- " --address -a <string> : connect elsewhere\n"
- " --port -p <int> : override the default port\n"
- " --headless -H : run without a client\n"
- " --singleplayer -s : avoid hosting a lan server\n"
- " --seed -S <int> : manually set the worldseed\n"
- " --directory -d <string> : manually set the directory\n"
- " --tickrate -t <int> : override the default tickrate\n"
- " --distance -D <int> : set the max chunk distance the server provides\n";
- // clang-format on
- std::exit(EXIT_SUCCESS);
- }
-
- has_address = maybe_parse_arg(args, {"--address", "-a"}, address);
- has_headless = maybe_parse_arg(args, {"--headless", "-H"});
-
- maybe_parse_arg(args, {"--port", "-p"}, port);
- maybe_parse_arg(args, {"--seed", "-S"}, server::state.seed);
- maybe_parse_arg(args, {"--directory", "-d"}, server::state.directory);
- maybe_parse_arg(args, {"--tickrate", "-t"}, server::state.tickrate);
- maybe_parse_arg(args, {"--distance", "-D"},
- server::state.draw_distance);
-
- if (maybe_parse_arg(args, {"--singleplayer", "-s"})) {
- if (has_address) {
- shared::print::warn("singleplayer argument ignored due "
- "to conflicting address argument\n");
- }
- address = "localhost";
- }
-
- std::ranges::for_each(args, [](const auto& arg) {
- shared::print::warn("unused argument \"" + std::string{arg} +
- "\"\n");
- });
- }
-
- init();
-
- // Split server/client execution, while waiting for server to boot before
- // running the client.
- std::jthread server_thread;
- if (!has_address) {
- if (has_headless) {
- do_server(address, port);
- std::exit(EXIT_SUCCESS);
- }
- server_thread = std::jthread{do_server, address, port};
- while (!server::has_initialised) {
- continue;
- }
- }
-
- do_client(address, port);
-}