From f3e2f6783088aa208facb8816c068bfe208c0c0b Mon Sep 17 00:00:00 2001 From: Mark Gross Date: Sun, 9 Feb 2020 15:40:37 -0800 Subject: [PATCH 1/7] Rework config files Summary: Simplify parsing of configuration files, reading them into a plain old unordered_map and splitting server and client into two config files. obd_parser: * Remove DataBlock struct and helper functions in obd_parser.cpp and obd_parser.h * Rename readObdData to parseObdData and simplify it to only take a string and return an unordered_map of key/value pairs obd_parser_test: * simplify test to ensure integrity of 3 values, including excess whitespace and newlines in string input main: * read from two files, client.obd and server.obd, rather than a single configuration file with CLIENT and SERVER sections * include file_io header to read the contents of the config files as strings, and then pass the strings to parseObdData --- src/common/common/obd_parser.cpp | 54 ++++++----------------------- src/common/common/obd_parser.h | 8 +---- src/main.cpp | 6 ++-- tests/common/obd_parser_test.cpp | 58 ++++++++++---------------------- 4 files changed, 32 insertions(+), 94 deletions(-) diff --git a/src/common/common/obd_parser.cpp b/src/common/common/obd_parser.cpp index ebc8b2d6..6052538f 100644 --- a/src/common/common/obd_parser.cpp +++ b/src/common/common/obd_parser.cpp @@ -6,51 +6,17 @@ #include #include -namespace { -/** - Removes trailing/ leading whitespace from a string -*/ -std::string cleanString(const std::string& line) +std::unordered_map parseObdData(const std::string& obdData) { - const char* WhiteSpace = " \t\v\r\n"; - std::size_t start = line.find_first_not_of(WhiteSpace); - std::size_t end = line.find_last_not_of(WhiteSpace); - return start == end ? std::string() : line.substr(start, end - start + 1); -} -} // namespace + std::istringstream contents(obdData); + std::string key; + std::string value; + std::unordered_map data; -std::vector getObdDataRaw(const std::string& obd) -{ - std::vector data; - std::istringstream stream(obd); - std::string line; + while (contents >> key) { + contents >> value; + data.insert(std::make_pair(key, value)); + } - while (std::getline(stream, line)) { - line = cleanString(line); - if (line.empty()) { - continue; - } - DataBlock block; - block.type = line; - while (stream >> line) { - if (line.empty()) { - continue; - } - if (line == "end") { - break; - } - else { - std::string value; - stream >> value; - block.data.emplace(line, value); - } - } - data.push_back(std::move(block)); - } - return data; + return data; } - -std::vector getObdData(const std::string& filename) -{ - return getObdDataRaw(loadFileContents(filename)); -} \ No newline at end of file diff --git a/src/common/common/obd_parser.h b/src/common/common/obd_parser.h index a06d474e..250813ed 100644 --- a/src/common/common/obd_parser.h +++ b/src/common/common/obd_parser.h @@ -4,10 +4,4 @@ #include #include -struct DataBlock { - std::string type; - std::unordered_map data; -}; - -std::vector getObdData(const std::string& filename); -std::vector getObdDataRaw(const std::string& obd); \ No newline at end of file +std::unordered_map parseObdData(const std::string& filename); diff --git a/src/main.cpp b/src/main.cpp index 0152b57b..c04a8031 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,6 +15,7 @@ #include #include +#include // Enable nvidia #ifdef _WIN32 @@ -49,9 +50,8 @@ struct Config { */ void loadFromConfigFile(Config& config) { - auto data = getObdData("config.obd"); - auto clientData = data[0].data; - auto serverData = data[1].data; + auto clientData = parseObdData(loadFileContents("client.obd")); + auto serverData = parseObdData(loadFileContents("server.obd")); config.client.fullScreen = std::stoi(clientData["fullscreen"]); config.client.windowWidth = std::stoi(clientData["window_width"]); diff --git a/tests/common/obd_parser_test.cpp b/tests/common/obd_parser_test.cpp index 5ad83af3..6cd85579 100644 --- a/tests/common/obd_parser_test.cpp +++ b/tests/common/obd_parser_test.cpp @@ -1,54 +1,32 @@ #include #include - -const std::string dataObd = " \n\ -block \n\ - name grass \n\ - texture_top pack:grass \n\ - texture_side pack:grasside \n\ - texture_bottom pack:dirt \n\ - mesh block \n\ - state solid \n\ -end \n\ - \n\ -block \n\ - name dirt \n\ - \n\ - texture_top pack:dirt \n\ - mesh cross \n\ - state flora \n\ -end \n\ -"; +#include + +const std::string dataObd = +"\n\ +cap_fps 0 \n\ +\n\ +fullscreen 0 \n\ +\n\ + \n\ +\n\ +key1 value1 \n\ +"; TEST_CASE("OBD files can be read from correctly") { - auto data = getObdDataRaw(dataObd); + auto data = parseObdData(dataObd); SECTION("There are a correct number of parsed blocks") { - REQUIRE(data.size() == 2); - - REQUIRE(data[0].data.size() == 6); - REQUIRE(data[1].data.size() == 4); + REQUIRE(data.size() == 3); } SECTION("It correctly has data") { - auto block = data[0]; - - REQUIRE(block.data["name"] == "grass"); - REQUIRE(block.data["texture_top"] == "pack:grass"); - REQUIRE(block.data["texture_side"] == "pack:grasside"); - REQUIRE(block.data["texture_bottom"] == "pack:dirt"); - REQUIRE(block.data["mesh"] == "block"); - REQUIRE(block.data["state"] == "solid"); - - auto block2 = data[1]; - - REQUIRE(block2.data["name"] == "dirt"); - REQUIRE(block2.data["texture_top"] == "pack:dirt"); - REQUIRE(block2.data["mesh"] == "cross"); - REQUIRE(block2.data["state"] == "flora"); + REQUIRE(data["cap_fps"] == "0"); + REQUIRE(data["fullscreen"] == "0"); + REQUIRE(data["key1"] == "value1"); } -} \ No newline at end of file +} From 2294e3cac4e11ce9c6b8547d20cc4427863124a4 Mon Sep 17 00:00:00 2001 From: Mark Gross Date: Sun, 9 Feb 2020 19:17:42 -0800 Subject: [PATCH 2/7] Generate default config Summary: Check if config files exist. If a given config file does not exist, write the default values to a new config file. Also, remove LOCAL_HOST constant as 127.0.0.1 is a standard for the local host. file_io: Add new fileExists() function to check if a file exists net_constants: Remove LOCAL_HOST constant net_host_tests: Replace LOCAL_HOST with "127.0.0.1" obd_parser: Add serializeObdData() function to serialize a key-value collection to the obd format main: Rewrite loadFromConfigFile() function to handle a non-present config file. --- config.obd | 19 ------ src/client/client_config.h | 2 +- src/common/common/file_io.cpp | 6 ++ src/common/common/file_io.h | 1 + src/common/common/network/net_constants.h | 3 - src/common/common/obd_parser.cpp | 9 +++ src/common/common/obd_parser.h | 1 + src/main.cpp | 73 ++++++++++++++++------- tests/common/network/net_host_test.cpp | 6 +- 9 files changed, 74 insertions(+), 46 deletions(-) delete mode 100644 config.obd diff --git a/config.obd b/config.obd deleted file mode 100644 index 12fcd737..00000000 --- a/config.obd +++ /dev/null @@ -1,19 +0,0 @@ -CLIENT_DATA - cap_fps 0 - fps_limit 60 - fov 90 - - fullscreen 0 - window_width 1600 - window_height 900 - - skin player - texture_pack default - shouldShowInstructions 1 - - server_ip LOCAL -end - -SERVER_DATA - world_size 8 -end \ No newline at end of file diff --git a/src/client/client_config.h b/src/client/client_config.h index bb963428..00e87be6 100644 --- a/src/client/client_config.h +++ b/src/client/client_config.h @@ -22,5 +22,5 @@ struct ClientConfig { std::string skinName = "player"; std::string texturePack = "default"; - std::string serverIp = LOCAL_HOST; + std::string serverIp = "127.0.0.1"; }; diff --git a/src/common/common/file_io.cpp b/src/common/common/file_io.cpp index fceb5744..54cf374a 100644 --- a/src/common/common/file_io.cpp +++ b/src/common/common/file_io.cpp @@ -15,3 +15,9 @@ std::string loadFileContents(const std::string& path) stream << inFile.rdbuf(); return stream.str(); } + +bool fileExists(const std::string& path) +{ + std::ifstream inFile(path); + return !!inFile; +} diff --git a/src/common/common/file_io.h b/src/common/common/file_io.h index ce54d499..3cbc4a1a 100644 --- a/src/common/common/file_io.h +++ b/src/common/common/file_io.h @@ -8,3 +8,4 @@ * @return std::string Contents of the file */ std::string loadFileContents(const std::string& path); +bool fileExists(const std::string& path); diff --git a/src/common/common/network/net_constants.h b/src/common/common/network/net_constants.h index 764d2956..b4f8aae8 100644 --- a/src/common/common/network/net_constants.h +++ b/src/common/common/network/net_constants.h @@ -12,6 +12,3 @@ constexpr int MIN_CONNECTIONS = 1; // The maximum number of connections the server can hold simultaneously constexpr int MAX_CONNECTIONS = 8; - -// Localhost -const std::string LOCAL_HOST = "127.0.0.1"; \ No newline at end of file diff --git a/src/common/common/obd_parser.cpp b/src/common/common/obd_parser.cpp index 6052538f..f2ad94a0 100644 --- a/src/common/common/obd_parser.cpp +++ b/src/common/common/obd_parser.cpp @@ -20,3 +20,12 @@ std::unordered_map parseObdData(const std::string& obd return data; } + +std::string serializeObdData(const std::unordered_map& obdData) +{ + std::ostringstream output; + for (auto const& pair : obdData) { + output << pair.first << " " << pair.second << "\n"; + } + return output.str(); +} diff --git a/src/common/common/obd_parser.h b/src/common/common/obd_parser.h index 250813ed..40b34b47 100644 --- a/src/common/common/obd_parser.h +++ b/src/common/common/obd_parser.h @@ -5,3 +5,4 @@ #include std::unordered_map parseObdData(const std::string& filename); +std::string serializeObdData(const std::unordered_map& obdData); diff --git a/src/main.cpp b/src/main.cpp index c04a8031..694d766f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -50,26 +50,59 @@ struct Config { */ void loadFromConfigFile(Config& config) { - auto clientData = parseObdData(loadFileContents("client.obd")); - auto serverData = parseObdData(loadFileContents("server.obd")); - - config.client.fullScreen = std::stoi(clientData["fullscreen"]); - config.client.windowWidth = std::stoi(clientData["window_width"]); - config.client.windowHeight = std::stoi(clientData["window_height"]); - config.client.isFpsCapped = std::stoi(clientData["cap_fps"]); - config.client.shouldShowInstructions = - std::stoi(clientData["shouldShowInstructions"]); - config.client.fpsLimit = std::stoi(clientData["fps_limit"]); - config.client.fov = std::stoi(clientData["fov"]); - config.client.fpsLimit = std::stoi(clientData["fps_limit"]); - config.client.skinName = clientData["skin"]; - config.client.texturePack = clientData["texture_pack"]; - config.client.serverIp = clientData["server_ip"]; - if (config.client.serverIp == "LOCAL") { - config.client.serverIp = LOCAL_HOST; - } - - config.server.worldSize = std::stoi(serverData["world_size"]); + if (fileExists("client.obd")) { + auto clientData = parseObdData(loadFileContents("client.obd")); + + config.client.fullScreen = std::stoi(clientData["fullscreen"]); + config.client.windowWidth = std::stoi(clientData["window_width"]); + config.client.windowHeight = std::stoi(clientData["window_height"]); + config.client.isFpsCapped = std::stoi(clientData["cap_fps"]); + config.client.shouldShowInstructions = + std::stoi(clientData["shouldShowInstructions"]); + config.client.fpsLimit = std::stoi(clientData["fps_limit"]); + config.client.fov = std::stoi(clientData["fov"]); + config.client.fpsLimit = std::stoi(clientData["fps_limit"]); + config.client.skinName = clientData["skin"]; + config.client.texturePack = clientData["texture_pack"]; + config.client.serverIp = clientData["server_ip"]; + } + else { + std::unordered_map clientData; + clientData.insert(std::make_pair("fullscreen", config.client.fullScreen ? "1" : "0")); + clientData.insert(std::make_pair("window_width", std::to_string(config.client.windowWidth))); + clientData.insert(std::make_pair("window_height", std::to_string(config.client.windowHeight))); + clientData.insert(std::make_pair("cap_fps", config.client.isFpsCapped ? "1" : "0")); + clientData.insert(std::make_pair("shouldShowInstructions", config.client.shouldShowInstructions ? "1" : "0")); + clientData.insert(std::make_pair("fps_limit", std::to_string(config.client.fpsLimit))); + clientData.insert(std::make_pair("fov", std::to_string(config.client.fov))); + clientData.insert(std::make_pair("fps_limit", std::to_string(config.client.fpsLimit))); + clientData.insert(std::make_pair("skin", config.client.skinName)); + clientData.insert(std::make_pair("texture_pack", config.client.texturePack)); + clientData.insert(std::make_pair("server_ip", config.client.serverIp)); + + std::string clientDataSerialized = serializeObdData(clientData); + std::ofstream clientFile("client.obd"); + if (!clientFile) { + std::cerr << "Cannot open client.obd for writing\n"; + } + clientFile << clientDataSerialized << std::endl; + } + + if (fileExists("server.obd")) { + auto serverData = parseObdData(loadFileContents("server.obd")); + config.server.worldSize = std::stoi(serverData["world_size"]); + } + else { + std::unordered_map serverData; + serverData.insert(std::make_pair("world_size", std::to_string(config.server.worldSize))); + + std::string serverDataSerialized = serializeObdData(serverData); + std::ofstream serverFile("server.obd"); + if (!serverFile) { + std::cerr << "Cannot open server.obd for writing\n"; + } + serverFile << serverDataSerialized << std::endl; + } } /** diff --git a/tests/common/network/net_host_test.cpp b/tests/common/network/net_host_test.cpp index e03e7887..70008806 100644 --- a/tests/common/network/net_host_test.cpp +++ b/tests/common/network/net_host_test.cpp @@ -83,7 +83,7 @@ TEST_CASE("The client can interact with the server.") }); TestClient client; - auto serverConnection = client.createAsClient(LOCAL_HOST); + auto serverConnection = client.createAsClient("127.0.0.1"); REQUIRE(serverConnection.has_value() == true); REQUIRE(server.getConnectedPeerCount() == 1); @@ -104,7 +104,7 @@ TEST_CASE("The client can interact with the server.") }); TestClient client; - auto serverConnection = client.createAsClient(LOCAL_HOST); + auto serverConnection = client.createAsClient("127.0.0.1"); client.disconnectFromPeer(*serverConnection); REQUIRE(server.getConnectedPeerCount() == 0); @@ -114,4 +114,4 @@ TEST_CASE("The client can interact with the server.") serverThread.join(); } -} \ No newline at end of file +} From 060813bd204c0c5b0b0573b6c0c56e8cf751691b Mon Sep 17 00:00:00 2001 From: Mark Gross Date: Sun, 9 Feb 2020 19:43:41 -0800 Subject: [PATCH 3/7] gitignore: ignore *.obd --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 4ceafeec..0d9be58f 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,8 @@ texture_packs/ElijahHyper custom_run.sh +*.obd + # # Linux # From faca4153d816b4067fe64822c47880737a33361d Mon Sep 17 00:00:00 2001 From: Mark Gross Date: Mon, 10 Feb 2020 11:08:24 -0800 Subject: [PATCH 4/7] Hopson97 code review Summary: Modernize code by using C++17 features and unordered_map::emplace() rather than unordered_map::insert(std::make_pair(...)) file_io: * Remove fileExists() function obd_parser: * Replace calls to unordered_map::insert() with calls to main: * Replace calls to unordered_map::insert() with calls to unorderd_map::emplace() * Use std::filesystem::exists() instead of fileExists helper function --- src/common/common/file_io.cpp | 6 ------ src/common/common/obd_parser.cpp | 2 +- src/main.cpp | 29 +++++++++++++++-------------- 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/common/common/file_io.cpp b/src/common/common/file_io.cpp index 54cf374a..fceb5744 100644 --- a/src/common/common/file_io.cpp +++ b/src/common/common/file_io.cpp @@ -15,9 +15,3 @@ std::string loadFileContents(const std::string& path) stream << inFile.rdbuf(); return stream.str(); } - -bool fileExists(const std::string& path) -{ - std::ifstream inFile(path); - return !!inFile; -} diff --git a/src/common/common/obd_parser.cpp b/src/common/common/obd_parser.cpp index f2ad94a0..247cc1f4 100644 --- a/src/common/common/obd_parser.cpp +++ b/src/common/common/obd_parser.cpp @@ -15,7 +15,7 @@ std::unordered_map parseObdData(const std::string& obd while (contents >> key) { contents >> value; - data.insert(std::make_pair(key, value)); + data.emplace(key, value); } return data; diff --git a/src/main.cpp b/src/main.cpp index 694d766f..0ce5101b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "client/client_engine.h" #include "server/server_engine.h" @@ -50,7 +51,7 @@ struct Config { */ void loadFromConfigFile(Config& config) { - if (fileExists("client.obd")) { + if (std::filesystem::exists("client.obd")) { auto clientData = parseObdData(loadFileContents("client.obd")); config.client.fullScreen = std::stoi(clientData["fullscreen"]); @@ -68,17 +69,17 @@ void loadFromConfigFile(Config& config) } else { std::unordered_map clientData; - clientData.insert(std::make_pair("fullscreen", config.client.fullScreen ? "1" : "0")); - clientData.insert(std::make_pair("window_width", std::to_string(config.client.windowWidth))); - clientData.insert(std::make_pair("window_height", std::to_string(config.client.windowHeight))); - clientData.insert(std::make_pair("cap_fps", config.client.isFpsCapped ? "1" : "0")); - clientData.insert(std::make_pair("shouldShowInstructions", config.client.shouldShowInstructions ? "1" : "0")); - clientData.insert(std::make_pair("fps_limit", std::to_string(config.client.fpsLimit))); - clientData.insert(std::make_pair("fov", std::to_string(config.client.fov))); - clientData.insert(std::make_pair("fps_limit", std::to_string(config.client.fpsLimit))); - clientData.insert(std::make_pair("skin", config.client.skinName)); - clientData.insert(std::make_pair("texture_pack", config.client.texturePack)); - clientData.insert(std::make_pair("server_ip", config.client.serverIp)); + clientData.emplace("fullscreen", config.client.fullScreen ? "1" : "0"); + clientData.emplace("window_width", std::to_string(config.client.windowWidth)); + clientData.emplace("window_height", std::to_string(config.client.windowHeight)); + clientData.emplace("cap_fps", config.client.isFpsCapped ? "1" : "0"); + clientData.emplace("shouldShowInstructions", config.client.shouldShowInstructions ? "1" : "0"); + clientData.emplace("fps_limit", std::to_string(config.client.fpsLimit)); + clientData.emplace("fov", std::to_string(config.client.fov)); + clientData.emplace("fps_limit", std::to_string(config.client.fpsLimit)); + clientData.emplace("skin", config.client.skinName); + clientData.emplace("texture_pack", config.client.texturePack); + clientData.emplace("server_ip", config.client.serverIp); std::string clientDataSerialized = serializeObdData(clientData); std::ofstream clientFile("client.obd"); @@ -88,13 +89,13 @@ void loadFromConfigFile(Config& config) clientFile << clientDataSerialized << std::endl; } - if (fileExists("server.obd")) { + if (std::filesystem::exists("server.obd")) { auto serverData = parseObdData(loadFileContents("server.obd")); config.server.worldSize = std::stoi(serverData["world_size"]); } else { std::unordered_map serverData; - serverData.insert(std::make_pair("world_size", std::to_string(config.server.worldSize))); + serverData.emplace("world_size", std::to_string(config.server.worldSize)); std::string serverDataSerialized = serializeObdData(serverData); std::ofstream serverFile("server.obd"); From 797a40da099fd79b63470c991face4854fb641ed Mon Sep 17 00:00:00 2001 From: Mark Gross Date: Mon, 10 Feb 2020 19:00:26 -0800 Subject: [PATCH 5/7] Config overhaul Summary: Introduce three new classes: ObdConfig, ClientConfig, and ServerConfig. ObdConfig provides a protected field of key-value pairs that are read in from the configuration file on object construction and written on object destruction. ClientConfig and ServerConfig derive from ObdConfig and map the key-value pairs to their fields in their constructors and destructors. New config classes use private fields and get_value() and set_value() accessors in accordance with C++ best practices. These three new classes replace the previously used Config, ClientConfig, and ServerConfig structs. All files: * Update references to old config files (e.g. config.client.field) for new config classes (e.g. client.get_field()) * Replace references to old Config struct with references to both the ClientConfig and ServerConfig objects obd_parser: * Move functions previously located in obd_parser to obd_config main: * Remove Config struct * Remove loadFromConfigFile() function * Simplify parseArgs() function to only handle parsing options, leaving validation elsewhere in main() * Reference ClientConfig, ServerConfig, and LaunchType individually instead of the old Config struct --- src/client/CMakeLists.txt | 1 + src/client/client.cpp | 10 +- src/client/client_config.cpp | 46 +++++++++ src/client/client_config.h | 61 ++++++++---- src/client/window.cpp | 10 +- src/common/common/CMakeLists.txt | 4 +- src/common/common/obd_config.cpp | 60 ++++++++++++ src/common/common/obd_config.h | 17 ++++ src/common/common/obd_parser.cpp | 31 ------ src/common/common/obd_parser.h | 8 -- src/main.cpp | 162 +++++++++---------------------- src/server/CMakeLists.txt | 3 +- src/server/network/server.cpp | 4 +- src/server/server_config.cpp | 18 ++++ src/server/server_config.h | 19 +++- src/server/server_engine.cpp | 4 +- tests/common/obd_parser_test.cpp | 2 +- 17 files changed, 264 insertions(+), 196 deletions(-) create mode 100644 src/client/client_config.cpp create mode 100644 src/common/common/obd_config.cpp create mode 100644 src/common/common/obd_config.h delete mode 100644 src/common/common/obd_parser.cpp delete mode 100644 src/common/common/obd_parser.h create mode 100644 src/server/server_config.cpp diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index ecb5f585..d0fc51b6 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(ob-client renderer/chunk_renderer.cpp network/client_commands.cpp client.cpp + client_config.cpp maths.cpp client_engine.cpp window.cpp diff --git a/src/client/client.cpp b/src/client/client.cpp index 487a0433..314e1379 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -23,7 +23,7 @@ bool isVoxelSelectable(VoxelType voxelType) Client::Client(const ClientConfig& config) : NetworkHost("Client") - , m_gui(config.windowWidth, config.windowHeight) + , m_gui(config.get_windowWidth(), config.get_windowHeight()) { // clang-format off m_commandDispatcher.addCommand(ClientCommand::BlockUpdate, &Client::onBlockUpdate); @@ -70,10 +70,10 @@ bool Client::init(const ClientConfig& config, float aspect) m_errorSkinTexture.create("skins/error"); m_errorSkinTexture.bind(); - m_texturePack = config.texturePack; + m_texturePack = config.get_texturePack(); // Set up the server connection - auto peer = NetworkHost::createAsClient(config.serverIp); + auto peer = NetworkHost::createAsClient(config.get_serverIp()); if (!peer) { return false; } @@ -83,14 +83,14 @@ bool Client::init(const ClientConfig& config, float aspect) mp_player = &m_entities[NetworkHost::getPeerId()]; mp_player->position = {CHUNK_SIZE * 2, CHUNK_SIZE * 2 + 1, CHUNK_SIZE * 2}; - m_rawPlayerSkin = gl::loadRawImageFile("skins/" + config.skinName); + m_rawPlayerSkin = gl::loadRawImageFile("skins/" + config.get_skinName()); sendPlayerSkin(m_rawPlayerSkin); m_projectionMatrix = glm::perspective(3.14f / 2.0f, aspect, 0.01f, 2000.0f); // Font and text m_debugTextFont.init("res/VeraMono-Bold.ttf", 512); - m_debugText.setPosition({2, config.windowHeight - 16, 0}); + m_debugText.setPosition({2, config.get_windowHeight() - 16, 0}); m_debugText.setCharSize(16); m_debugText.setFont(m_debugTextFont); m_debugText.setText("Current FPS: 60"); diff --git a/src/client/client_config.cpp b/src/client/client_config.cpp new file mode 100644 index 00000000..dbcb7c61 --- /dev/null +++ b/src/client/client_config.cpp @@ -0,0 +1,46 @@ +#include + +#include "client_config.h" + +ClientConfig::ClientConfig(const std::string& fileName) + : ObdConfig(fileName) +{ + if (m_keyvalues.count("isFpsCapped")) + m_isFpsCapped = m_keyvalues["isFpsCapped"] == "true" ? true : false; + if (m_keyvalues.count("shouldShowInstructions")) + m_shouldShowInstructions = m_keyvalues["shouldShowInstructions"] == "true" ? true : false; + if (m_keyvalues.count("fullScreen")) + m_fullScreen = m_keyvalues["fullScreen"] == "true" ? true : false; + + if (m_keyvalues.count("windowWidth")) + m_windowWidth = std::stoi(m_keyvalues["windowWidth"]); + if (m_keyvalues.count("windowHeight")) + m_windowHeight = std::stoi(m_keyvalues["windowHeight"]); + if (m_keyvalues.count("fpsLimit")) + m_fpsLimit = std::stoi(m_keyvalues["fpsLimit"]); + if (m_keyvalues.count("fov")) + m_fov = std::stoi(m_keyvalues["fov"]); + + if (m_keyvalues.count("skinName")) + m_skinName = m_keyvalues["skinName"]; + if (m_keyvalues.count("texturePack")) + m_texturePack = m_keyvalues["texturePack"]; + if (m_keyvalues.count("serverIp")) + m_serverIp = m_keyvalues["serverIp"]; +} + +ClientConfig::~ClientConfig() +{ + m_keyvalues["isFpsCapped"] = m_isFpsCapped ? "true" : "false"; + m_keyvalues["shouldShowInstructions"] = m_shouldShowInstructions ? "true" : "false"; + m_keyvalues["fullScreen"] = m_fullScreen ? "true" : "false"; + + m_keyvalues["windowWidth"] = std::to_string(m_windowWidth); + m_keyvalues["windowHeight"] = std::to_string(m_windowHeight); + m_keyvalues["fpsLimit"] = std::to_string(m_fpsLimit); + m_keyvalues["fov"] = std::to_string(m_fov); + + m_keyvalues["skinName"] = m_skinName; + m_keyvalues["texturePack"] = m_texturePack; + m_keyvalues["serverIp"] = m_serverIp; +} diff --git a/src/client/client_config.h b/src/client/client_config.h index 00e87be6..d74f7229 100644 --- a/src/client/client_config.h +++ b/src/client/client_config.h @@ -1,26 +1,53 @@ #pragma once -#include #include +#include -#include +class ClientConfig : public ObdConfig { + bool m_fullScreen = false; + int m_windowWidth = 1280; + int m_windowHeight = 720; + int m_fpsLimit = 60; + int m_fov = 65; -/** - * @brief Config options for client - * Mostly for the window and general graphics options - */ -struct ClientConfig { - bool fullScreen = false; - int windowWidth = 1280; - int windowHeight = 720; - int fpsLimit = 60; - int fov = 65; + bool m_isFpsCapped = true; + bool m_shouldShowInstructions = true; - bool isFpsCapped = true; - bool shouldShowInstructions = true; + std::string m_skinName = "player"; + std::string m_texturePack = "default"; - std::string skinName = "player"; - std::string texturePack = "default"; + std::string m_serverIp = "127.0.0.1"; + public: + ClientConfig(const std::string& fileName); + ~ClientConfig(); - std::string serverIp = "127.0.0.1"; + bool get_fullScreen() const { return m_fullScreen; } + void set_fullScreen(const bool value) { m_fullScreen = value; } + + bool get_isFpsCapped() const { return m_isFpsCapped; } + void set_isFpsCapped(const bool value) { m_isFpsCapped = value; } + + bool get_shouldShowInstructions() const { return m_shouldShowInstructions; } + void set_shouldShowInstructions(const bool value) { m_shouldShowInstructions = value; } + + int get_windowWidth() const { return m_windowWidth; } + void set_windowWidth(const int value) { m_windowWidth = value; } + + int get_windowHeight() const { return m_windowHeight; } + void set_windowHeight(const int value) { m_windowHeight = value; } + + int get_fpsLimit() const { return m_fpsLimit; } + void set_fpsLimit(const int value) { m_fpsLimit = value; } + + int get_fov() const { return m_fov; } + void set_fov(const int value) { m_fov = value; } + + std::string get_skinName() const { return m_skinName; } + void set_skinName(const std::string& value) { m_skinName = value; } + + std::string get_texturePack() const { return m_texturePack; } + void set_texturePack(const std::string& value) { m_texturePack = value; } + + std::string get_serverIp() const { return m_serverIp; } + void set_serverIp(const std::string& value) { m_serverIp = value; } }; diff --git a/src/client/window.cpp b/src/client/window.cpp index 232deb52..e1dfdb24 100644 --- a/src/client/window.cpp +++ b/src/client/window.cpp @@ -7,20 +7,20 @@ Window::Window(const ClientConfig& config) { window.setKeyRepeatEnabled(false); - if (config.fullScreen) { + if (config.get_fullScreen()) { create(sf::VideoMode::getDesktopMode(), sf::Style::Fullscreen); width = window.getSize().x; height = window.getSize().y; aspect = static_cast(width) / static_cast(height); } else { - width = static_cast(config.windowWidth); - height = static_cast(config.windowHeight); + width = static_cast(config.get_windowWidth()); + height = static_cast(config.get_windowHeight()); aspect = static_cast(width) / static_cast(height); create({width, height}, sf::Style::Close); } - if (config.isFpsCapped) { - window.setFramerateLimit(config.fpsLimit); + if (config.get_isFpsCapped()) { + window.setFramerateLimit(config.get_fpsLimit()); } } diff --git a/src/common/common/CMakeLists.txt b/src/common/common/CMakeLists.txt index 1e3eaac3..32a144fb 100644 --- a/src/common/common/CMakeLists.txt +++ b/src/common/common/CMakeLists.txt @@ -1,7 +1,7 @@ add_library(ob-common file_io.cpp - obd_parser.cpp + obd_config.cpp debug.cpp network/net_host.cpp scripting/script_engine.cpp @@ -21,4 +21,4 @@ target_link_libraries(ob-common ${SFML_LIBRARIES} ${SFML_DEPENDENCIES} ${CMAKE_DL_LIBS} -) \ No newline at end of file +) diff --git a/src/common/common/obd_config.cpp b/src/common/common/obd_config.cpp new file mode 100644 index 00000000..11ee2572 --- /dev/null +++ b/src/common/common/obd_config.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include + +#include "obd_config.h" + +// member definitions for ObdConfig +ObdConfig::ObdConfig(const std::string& filePath) + : m_filePath(filePath) +{ + if (std::filesystem::exists(filePath)) { + m_filePath = filePath; + std::ifstream file(m_filePath); + if (!file.is_open()) { + std::cerr << "Could not open file " << m_filePath << std::endl; + return; + } + std::stringstream stream; + stream << file.rdbuf(); + + m_keyvalues = parseObdData(stream.str()); + } +} + +ObdConfig::~ObdConfig() +{ + std::ofstream file(m_filePath); + if (!file.is_open()) { + std::cerr << "Could not write to " << m_filePath << std::endl; + return; + } + file << serializeObdData(m_keyvalues); +} + +// helper functions +std::unordered_map parseObdData(const std::string& obdData) +{ + std::istringstream contents(obdData); + std::string key; + std::string value; + std::unordered_map data; + + while (contents >> key) { + contents >> value; + data.emplace(key, value); + } + + return data; +} + +std::string serializeObdData(const std::unordered_map& obdData) +{ + std::ostringstream output; + for (auto const& pair : obdData) { + output << pair.first << " " << pair.second << "\n"; + } + return output.str(); +} diff --git a/src/common/common/obd_config.h b/src/common/common/obd_config.h new file mode 100644 index 00000000..8bc584a2 --- /dev/null +++ b/src/common/common/obd_config.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +std::unordered_map parseObdData(const std::string& obdData); +std::string serializeObdData(const std::unordered_map& obdData); + +class ObdConfig +{ + std::string m_filePath; + public: + ObdConfig(const std::string& filePath); // implicitly read config file + ~ObdConfig(); // write back to file when the config goes out of scope + protected: + std::unordered_map m_keyvalues; +}; diff --git a/src/common/common/obd_parser.cpp b/src/common/common/obd_parser.cpp deleted file mode 100644 index 247cc1f4..00000000 --- a/src/common/common/obd_parser.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "obd_parser.h" - -#include "file_io.h" -#include -#include -#include -#include - -std::unordered_map parseObdData(const std::string& obdData) -{ - std::istringstream contents(obdData); - std::string key; - std::string value; - std::unordered_map data; - - while (contents >> key) { - contents >> value; - data.emplace(key, value); - } - - return data; -} - -std::string serializeObdData(const std::unordered_map& obdData) -{ - std::ostringstream output; - for (auto const& pair : obdData) { - output << pair.first << " " << pair.second << "\n"; - } - return output.str(); -} diff --git a/src/common/common/obd_parser.h b/src/common/common/obd_parser.h deleted file mode 100644 index 40b34b47..00000000 --- a/src/common/common/obd_parser.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include -#include -#include - -std::unordered_map parseObdData(const std::string& filename); -std::string serializeObdData(const std::unordered_map& obdData); diff --git a/src/main.cpp b/src/main.cpp index 0ce5101b..c637591f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,7 +15,6 @@ #include "server/server_config.h" #include -#include #include // Enable nvidia @@ -35,114 +34,24 @@ enum class LaunchType { TwoPlayer, }; -/** - * @brief Holds config for both client and server - */ -struct Config { - LaunchType launchType = LaunchType::Both; - - ServerConfig server; - ClientConfig client; -}; - -/** - * @brief Loads config eg window size from the config.txt file - * @param config The config object to put the data into - */ -void loadFromConfigFile(Config& config) -{ - if (std::filesystem::exists("client.obd")) { - auto clientData = parseObdData(loadFileContents("client.obd")); - - config.client.fullScreen = std::stoi(clientData["fullscreen"]); - config.client.windowWidth = std::stoi(clientData["window_width"]); - config.client.windowHeight = std::stoi(clientData["window_height"]); - config.client.isFpsCapped = std::stoi(clientData["cap_fps"]); - config.client.shouldShowInstructions = - std::stoi(clientData["shouldShowInstructions"]); - config.client.fpsLimit = std::stoi(clientData["fps_limit"]); - config.client.fov = std::stoi(clientData["fov"]); - config.client.fpsLimit = std::stoi(clientData["fps_limit"]); - config.client.skinName = clientData["skin"]; - config.client.texturePack = clientData["texture_pack"]; - config.client.serverIp = clientData["server_ip"]; - } - else { - std::unordered_map clientData; - clientData.emplace("fullscreen", config.client.fullScreen ? "1" : "0"); - clientData.emplace("window_width", std::to_string(config.client.windowWidth)); - clientData.emplace("window_height", std::to_string(config.client.windowHeight)); - clientData.emplace("cap_fps", config.client.isFpsCapped ? "1" : "0"); - clientData.emplace("shouldShowInstructions", config.client.shouldShowInstructions ? "1" : "0"); - clientData.emplace("fps_limit", std::to_string(config.client.fpsLimit)); - clientData.emplace("fov", std::to_string(config.client.fov)); - clientData.emplace("fps_limit", std::to_string(config.client.fpsLimit)); - clientData.emplace("skin", config.client.skinName); - clientData.emplace("texture_pack", config.client.texturePack); - clientData.emplace("server_ip", config.client.serverIp); - - std::string clientDataSerialized = serializeObdData(clientData); - std::ofstream clientFile("client.obd"); - if (!clientFile) { - std::cerr << "Cannot open client.obd for writing\n"; - } - clientFile << clientDataSerialized << std::endl; - } - - if (std::filesystem::exists("server.obd")) { - auto serverData = parseObdData(loadFileContents("server.obd")); - config.server.worldSize = std::stoi(serverData["world_size"]); - } - else { - std::unordered_map serverData; - serverData.emplace("world_size", std::to_string(config.server.worldSize)); - - std::string serverDataSerialized = serializeObdData(serverData); - std::ofstream serverFile("server.obd"); - if (!serverFile) { - std::cerr << "Cannot open server.obd for writing\n"; - } - serverFile << serverDataSerialized << std::endl; - } -} - /** * @brief Parses the CLI arguments from the user * @param config The config to load data into * @param args CLI arguments paired as */ -void parseArgs(Config& config, +void parseArgs(ClientConfig& config, LaunchType& launchType, const std::vector>& args) { + // set launch type for (const auto& option : args) { - // Set launch type to be server. - // Option: MAX_CONNECTIONS 2-16 if (option.first == "-server") { - config.launchType = LaunchType::Server; - try { - int maxConnections = std::stoi(option.second); - if (maxConnections < 2) { - throw std::invalid_argument("Max connections must be at least " + - std::to_string(MIN_CONNECTIONS) + ".\n"); - } - else if (maxConnections > 16) { - throw std::invalid_argument("Max connections must be " + - std::to_string(MAX_CONNECTIONS) + - " or below.\n"); - } - } - catch (std::invalid_argument& e) { - std::cout << "Unable to set max connections, defaulting to " - "4. Reason: " - << e.what() << "\n"; - config.server.maxConnections = 4; - } + launchType = LaunchType::Server; } else if (option.first == "-client") { - config.launchType = LaunchType::Client; + launchType = LaunchType::Client; } else if (option.first == "-skin") { - config.client.skinName = option.second; + config.set_skinName(option.second); } } } @@ -221,7 +130,7 @@ void printInstructions() */ int launchClient(const ClientConfig& config, bool launchingJustClient) { - if (launchingJustClient && config.shouldShowInstructions) { + if (launchingJustClient && config.get_shouldShowInstructions()) { printInstructions(); } LOG("Launcher", "Launching client"); @@ -251,15 +160,15 @@ int launchClient(const ClientConfig& config, bool launchingJustClient) * @param config The config to be used by client/server engines * @return int Exit flag (Success, or Failure) */ -int launchBoth(const Config& config) +int launchBoth(const ClientConfig& clientConfig, const ServerConfig& serverConfig) { - ServerLauncher server(config.server, sf::milliseconds(5000)); + ServerLauncher server(serverConfig, sf::milliseconds(5000)); std::thread serverThread([&server]() { LOG("Launcher", "Launching server"); server.runServerEngine(); }); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - int exit = launchClient(config.client, false); + int exit = launchClient(clientConfig, false); serverThread.join(); return exit; } @@ -269,18 +178,18 @@ int launchBoth(const Config& config) * @param config The config to be used by client/server engines * @return int Exit flag (Success, or Failure) */ -int launchServerAnd2Players(const Config& config) +int launchServerAnd2Players(const ClientConfig& clientConfig, const ServerConfig& serverConfig) { - ServerLauncher server(config.server, sf::milliseconds(5000)); + ServerLauncher server(serverConfig, sf::milliseconds(5000)); std::thread serverThread([&server]() { LOG("Launcher", "Launching server"); server.runServerEngine(); }); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - std::thread client2(launchClient, config.client, false); + std::thread client2(launchClient, clientConfig, false); - int exit = launchClient(config.client, false); + int exit = launchClient(clientConfig, false); client2.join(); serverThread.join(); @@ -290,12 +199,11 @@ int launchServerAnd2Players(const Config& config) int main(int argc, char** argv) { - Config config; - - if (enet_initialize() != 0) { - return exitFailure("Failed to initialise enet"); - } + // read config files + ClientConfig clientConfig("client.obd"); + ServerConfig serverConfig("server.obd"); + // parse command line arguments std::vector> args; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-' && argc > i + 1) { @@ -303,21 +211,43 @@ int main(int argc, char** argv) } } - loadFromConfigFile(config); - parseArgs(config, args); + LaunchType launchType; + parseArgs(clientConfig, launchType, args); + + try { + if (serverConfig.get_maxConnections() < 2) { + throw std::invalid_argument("Max connections must be at least " + + std::to_string(MIN_CONNECTIONS) + ".\n"); + } + else if (serverConfig.get_maxConnections() > 16) { + throw std::invalid_argument("Max connections must be " + + std::to_string(MAX_CONNECTIONS) + + " or below.\n"); + } + } + catch (std::invalid_argument& e) { + std::cout << "Unable to set max connections, defaulting to " + "4. Reason: " + << e.what() << "\n"; + serverConfig.set_maxConnections(4); + } + + if (enet_initialize() != 0) { + return exitFailure("Failed to initialise enet"); + } - switch (config.launchType) { + switch (launchType) { case LaunchType::Both: - return launchBoth(config); + return launchBoth(clientConfig, serverConfig); case LaunchType::Server: - return launchServer(config.server); + return launchServer(serverConfig); case LaunchType::Client: - return launchClient(config.client, true); + return launchClient(clientConfig, true); case LaunchType::TwoPlayer: - return launchServerAnd2Players(config); + return launchServerAnd2Players(clientConfig, serverConfig); } enet_deinitialize(); diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 1ca8a487..7511e1fc 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(ob-server server_engine.cpp + server_config.cpp network/server.cpp world/terrain_generation.cpp lua/data_api.cpp @@ -19,4 +20,4 @@ target_link_libraries(ob-server ${SFML_LIBRARIES} ${SFML_DEPENDENCIES} ${CMAKE_DL_LIBS} -) \ No newline at end of file +) diff --git a/src/server/network/server.cpp b/src/server/network/server.cpp index 7cfe58af..922b302d 100644 --- a/src/server/network/server.cpp +++ b/src/server/network/server.cpp @@ -11,11 +11,9 @@ #include "../world/terrain_generation.h" -#include - Server::Server(const ServerConfig& config) : NetworkHost("Server") - , m_worldSize(config.worldSize) + , m_worldSize(config.get_worldSize()) { // clang-format off m_commandDispatcher.addCommand(ServerCommand::BlockEdit, &Server::onBlockEdit); diff --git a/src/server/server_config.cpp b/src/server/server_config.cpp new file mode 100644 index 00000000..b9d8b581 --- /dev/null +++ b/src/server/server_config.cpp @@ -0,0 +1,18 @@ +#include + +#include "server_config.h" + +ServerConfig::ServerConfig(const std::string& fileName) + : ObdConfig(fileName) +{ + if (m_keyvalues.count("maxConnections")) + m_maxConnections = std::stoi(m_keyvalues["maxConnections"]); + if (m_keyvalues.count("worldSize")) + m_maxConnections = std::stoi(m_keyvalues["worldSize"]); +} + +ServerConfig::~ServerConfig() +{ + m_keyvalues["maxConnections"] = std::to_string(m_maxConnections); + m_keyvalues["worldSize"] = std::to_string(m_worldSize); +} diff --git a/src/server/server_config.h b/src/server/server_config.h index 91e2126d..ecf3b609 100644 --- a/src/server/server_config.h +++ b/src/server/server_config.h @@ -1,8 +1,17 @@ #pragma once -#include +#include -struct ServerConfig { - int maxConnections = 4; - int worldSize = 16; -}; \ No newline at end of file +class ServerConfig : public ObdConfig { + int m_maxConnections = 4; + int m_worldSize = 4; + public: + ServerConfig(const std::string& filePath); + ~ServerConfig(); + + int get_maxConnections() const { return m_maxConnections; } + void set_maxConnections(const int value) { m_maxConnections = value; } + + int get_worldSize() const { return m_worldSize; } + void set_worldSize(const int value) { m_worldSize = value; } +}; diff --git a/src/server/server_engine.cpp b/src/server/server_engine.cpp index 4f372a60..9c814a29 100644 --- a/src/server/server_engine.cpp +++ b/src/server/server_engine.cpp @@ -16,7 +16,7 @@ ServerLauncher::ServerLauncher(const ServerConfig& config, sf::Time timeout) void ServerLauncher::runServerEngine() { - if (!m_server.createAsServer(m_config.maxConnections)) { + if (!m_server.createAsServer(m_config.get_maxConnections())) { std::cout << "Failed to create server.\n"; return; } @@ -61,4 +61,4 @@ void ServerLauncher::runServerEngine() << std::endl; } console.join(); -} \ No newline at end of file +} diff --git a/tests/common/obd_parser_test.cpp b/tests/common/obd_parser_test.cpp index 6cd85579..bb51f303 100644 --- a/tests/common/obd_parser_test.cpp +++ b/tests/common/obd_parser_test.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include const std::string dataObd = From b4e3f5da247bd88a0ecea5d86436e3ad310d1982 Mon Sep 17 00:00:00 2001 From: Mark Gross Date: Mon, 10 Feb 2020 19:22:40 -0800 Subject: [PATCH 6/7] Revert "Config overhaul" Did I break something or did the unit tests break??? --- src/client/CMakeLists.txt | 1 - src/client/client.cpp | 10 +- src/client/client_config.cpp | 46 --------- src/client/client_config.h | 61 ++++-------- src/client/window.cpp | 10 +- src/common/common/CMakeLists.txt | 4 +- src/common/common/obd_config.cpp | 60 ------------ src/common/common/obd_config.h | 17 ---- src/common/common/obd_parser.cpp | 31 ++++++ src/common/common/obd_parser.h | 8 ++ src/main.cpp | 162 ++++++++++++++++++++++--------- src/server/CMakeLists.txt | 3 +- src/server/network/server.cpp | 4 +- src/server/server_config.cpp | 18 ---- src/server/server_config.h | 19 +--- src/server/server_engine.cpp | 4 +- tests/common/obd_parser_test.cpp | 2 +- 17 files changed, 196 insertions(+), 264 deletions(-) delete mode 100644 src/client/client_config.cpp delete mode 100644 src/common/common/obd_config.cpp delete mode 100644 src/common/common/obd_config.h create mode 100644 src/common/common/obd_parser.cpp create mode 100644 src/common/common/obd_parser.h delete mode 100644 src/server/server_config.cpp diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index d0fc51b6..ecb5f585 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -11,7 +11,6 @@ add_library(ob-client renderer/chunk_renderer.cpp network/client_commands.cpp client.cpp - client_config.cpp maths.cpp client_engine.cpp window.cpp diff --git a/src/client/client.cpp b/src/client/client.cpp index 314e1379..487a0433 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -23,7 +23,7 @@ bool isVoxelSelectable(VoxelType voxelType) Client::Client(const ClientConfig& config) : NetworkHost("Client") - , m_gui(config.get_windowWidth(), config.get_windowHeight()) + , m_gui(config.windowWidth, config.windowHeight) { // clang-format off m_commandDispatcher.addCommand(ClientCommand::BlockUpdate, &Client::onBlockUpdate); @@ -70,10 +70,10 @@ bool Client::init(const ClientConfig& config, float aspect) m_errorSkinTexture.create("skins/error"); m_errorSkinTexture.bind(); - m_texturePack = config.get_texturePack(); + m_texturePack = config.texturePack; // Set up the server connection - auto peer = NetworkHost::createAsClient(config.get_serverIp()); + auto peer = NetworkHost::createAsClient(config.serverIp); if (!peer) { return false; } @@ -83,14 +83,14 @@ bool Client::init(const ClientConfig& config, float aspect) mp_player = &m_entities[NetworkHost::getPeerId()]; mp_player->position = {CHUNK_SIZE * 2, CHUNK_SIZE * 2 + 1, CHUNK_SIZE * 2}; - m_rawPlayerSkin = gl::loadRawImageFile("skins/" + config.get_skinName()); + m_rawPlayerSkin = gl::loadRawImageFile("skins/" + config.skinName); sendPlayerSkin(m_rawPlayerSkin); m_projectionMatrix = glm::perspective(3.14f / 2.0f, aspect, 0.01f, 2000.0f); // Font and text m_debugTextFont.init("res/VeraMono-Bold.ttf", 512); - m_debugText.setPosition({2, config.get_windowHeight() - 16, 0}); + m_debugText.setPosition({2, config.windowHeight - 16, 0}); m_debugText.setCharSize(16); m_debugText.setFont(m_debugTextFont); m_debugText.setText("Current FPS: 60"); diff --git a/src/client/client_config.cpp b/src/client/client_config.cpp deleted file mode 100644 index dbcb7c61..00000000 --- a/src/client/client_config.cpp +++ /dev/null @@ -1,46 +0,0 @@ -#include - -#include "client_config.h" - -ClientConfig::ClientConfig(const std::string& fileName) - : ObdConfig(fileName) -{ - if (m_keyvalues.count("isFpsCapped")) - m_isFpsCapped = m_keyvalues["isFpsCapped"] == "true" ? true : false; - if (m_keyvalues.count("shouldShowInstructions")) - m_shouldShowInstructions = m_keyvalues["shouldShowInstructions"] == "true" ? true : false; - if (m_keyvalues.count("fullScreen")) - m_fullScreen = m_keyvalues["fullScreen"] == "true" ? true : false; - - if (m_keyvalues.count("windowWidth")) - m_windowWidth = std::stoi(m_keyvalues["windowWidth"]); - if (m_keyvalues.count("windowHeight")) - m_windowHeight = std::stoi(m_keyvalues["windowHeight"]); - if (m_keyvalues.count("fpsLimit")) - m_fpsLimit = std::stoi(m_keyvalues["fpsLimit"]); - if (m_keyvalues.count("fov")) - m_fov = std::stoi(m_keyvalues["fov"]); - - if (m_keyvalues.count("skinName")) - m_skinName = m_keyvalues["skinName"]; - if (m_keyvalues.count("texturePack")) - m_texturePack = m_keyvalues["texturePack"]; - if (m_keyvalues.count("serverIp")) - m_serverIp = m_keyvalues["serverIp"]; -} - -ClientConfig::~ClientConfig() -{ - m_keyvalues["isFpsCapped"] = m_isFpsCapped ? "true" : "false"; - m_keyvalues["shouldShowInstructions"] = m_shouldShowInstructions ? "true" : "false"; - m_keyvalues["fullScreen"] = m_fullScreen ? "true" : "false"; - - m_keyvalues["windowWidth"] = std::to_string(m_windowWidth); - m_keyvalues["windowHeight"] = std::to_string(m_windowHeight); - m_keyvalues["fpsLimit"] = std::to_string(m_fpsLimit); - m_keyvalues["fov"] = std::to_string(m_fov); - - m_keyvalues["skinName"] = m_skinName; - m_keyvalues["texturePack"] = m_texturePack; - m_keyvalues["serverIp"] = m_serverIp; -} diff --git a/src/client/client_config.h b/src/client/client_config.h index d74f7229..00e87be6 100644 --- a/src/client/client_config.h +++ b/src/client/client_config.h @@ -1,53 +1,26 @@ #pragma once +#include #include -#include -class ClientConfig : public ObdConfig { - bool m_fullScreen = false; - int m_windowWidth = 1280; - int m_windowHeight = 720; - int m_fpsLimit = 60; - int m_fov = 65; +#include - bool m_isFpsCapped = true; - bool m_shouldShowInstructions = true; +/** + * @brief Config options for client + * Mostly for the window and general graphics options + */ +struct ClientConfig { + bool fullScreen = false; + int windowWidth = 1280; + int windowHeight = 720; + int fpsLimit = 60; + int fov = 65; - std::string m_skinName = "player"; - std::string m_texturePack = "default"; + bool isFpsCapped = true; + bool shouldShowInstructions = true; - std::string m_serverIp = "127.0.0.1"; - public: - ClientConfig(const std::string& fileName); - ~ClientConfig(); + std::string skinName = "player"; + std::string texturePack = "default"; - bool get_fullScreen() const { return m_fullScreen; } - void set_fullScreen(const bool value) { m_fullScreen = value; } - - bool get_isFpsCapped() const { return m_isFpsCapped; } - void set_isFpsCapped(const bool value) { m_isFpsCapped = value; } - - bool get_shouldShowInstructions() const { return m_shouldShowInstructions; } - void set_shouldShowInstructions(const bool value) { m_shouldShowInstructions = value; } - - int get_windowWidth() const { return m_windowWidth; } - void set_windowWidth(const int value) { m_windowWidth = value; } - - int get_windowHeight() const { return m_windowHeight; } - void set_windowHeight(const int value) { m_windowHeight = value; } - - int get_fpsLimit() const { return m_fpsLimit; } - void set_fpsLimit(const int value) { m_fpsLimit = value; } - - int get_fov() const { return m_fov; } - void set_fov(const int value) { m_fov = value; } - - std::string get_skinName() const { return m_skinName; } - void set_skinName(const std::string& value) { m_skinName = value; } - - std::string get_texturePack() const { return m_texturePack; } - void set_texturePack(const std::string& value) { m_texturePack = value; } - - std::string get_serverIp() const { return m_serverIp; } - void set_serverIp(const std::string& value) { m_serverIp = value; } + std::string serverIp = "127.0.0.1"; }; diff --git a/src/client/window.cpp b/src/client/window.cpp index e1dfdb24..232deb52 100644 --- a/src/client/window.cpp +++ b/src/client/window.cpp @@ -7,20 +7,20 @@ Window::Window(const ClientConfig& config) { window.setKeyRepeatEnabled(false); - if (config.get_fullScreen()) { + if (config.fullScreen) { create(sf::VideoMode::getDesktopMode(), sf::Style::Fullscreen); width = window.getSize().x; height = window.getSize().y; aspect = static_cast(width) / static_cast(height); } else { - width = static_cast(config.get_windowWidth()); - height = static_cast(config.get_windowHeight()); + width = static_cast(config.windowWidth); + height = static_cast(config.windowHeight); aspect = static_cast(width) / static_cast(height); create({width, height}, sf::Style::Close); } - if (config.get_isFpsCapped()) { - window.setFramerateLimit(config.get_fpsLimit()); + if (config.isFpsCapped) { + window.setFramerateLimit(config.fpsLimit); } } diff --git a/src/common/common/CMakeLists.txt b/src/common/common/CMakeLists.txt index 32a144fb..1e3eaac3 100644 --- a/src/common/common/CMakeLists.txt +++ b/src/common/common/CMakeLists.txt @@ -1,7 +1,7 @@ add_library(ob-common file_io.cpp - obd_config.cpp + obd_parser.cpp debug.cpp network/net_host.cpp scripting/script_engine.cpp @@ -21,4 +21,4 @@ target_link_libraries(ob-common ${SFML_LIBRARIES} ${SFML_DEPENDENCIES} ${CMAKE_DL_LIBS} -) +) \ No newline at end of file diff --git a/src/common/common/obd_config.cpp b/src/common/common/obd_config.cpp deleted file mode 100644 index 11ee2572..00000000 --- a/src/common/common/obd_config.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include -#include -#include -#include - -#include "obd_config.h" - -// member definitions for ObdConfig -ObdConfig::ObdConfig(const std::string& filePath) - : m_filePath(filePath) -{ - if (std::filesystem::exists(filePath)) { - m_filePath = filePath; - std::ifstream file(m_filePath); - if (!file.is_open()) { - std::cerr << "Could not open file " << m_filePath << std::endl; - return; - } - std::stringstream stream; - stream << file.rdbuf(); - - m_keyvalues = parseObdData(stream.str()); - } -} - -ObdConfig::~ObdConfig() -{ - std::ofstream file(m_filePath); - if (!file.is_open()) { - std::cerr << "Could not write to " << m_filePath << std::endl; - return; - } - file << serializeObdData(m_keyvalues); -} - -// helper functions -std::unordered_map parseObdData(const std::string& obdData) -{ - std::istringstream contents(obdData); - std::string key; - std::string value; - std::unordered_map data; - - while (contents >> key) { - contents >> value; - data.emplace(key, value); - } - - return data; -} - -std::string serializeObdData(const std::unordered_map& obdData) -{ - std::ostringstream output; - for (auto const& pair : obdData) { - output << pair.first << " " << pair.second << "\n"; - } - return output.str(); -} diff --git a/src/common/common/obd_config.h b/src/common/common/obd_config.h deleted file mode 100644 index 8bc584a2..00000000 --- a/src/common/common/obd_config.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include -#include - -std::unordered_map parseObdData(const std::string& obdData); -std::string serializeObdData(const std::unordered_map& obdData); - -class ObdConfig -{ - std::string m_filePath; - public: - ObdConfig(const std::string& filePath); // implicitly read config file - ~ObdConfig(); // write back to file when the config goes out of scope - protected: - std::unordered_map m_keyvalues; -}; diff --git a/src/common/common/obd_parser.cpp b/src/common/common/obd_parser.cpp new file mode 100644 index 00000000..247cc1f4 --- /dev/null +++ b/src/common/common/obd_parser.cpp @@ -0,0 +1,31 @@ +#include "obd_parser.h" + +#include "file_io.h" +#include +#include +#include +#include + +std::unordered_map parseObdData(const std::string& obdData) +{ + std::istringstream contents(obdData); + std::string key; + std::string value; + std::unordered_map data; + + while (contents >> key) { + contents >> value; + data.emplace(key, value); + } + + return data; +} + +std::string serializeObdData(const std::unordered_map& obdData) +{ + std::ostringstream output; + for (auto const& pair : obdData) { + output << pair.first << " " << pair.second << "\n"; + } + return output.str(); +} diff --git a/src/common/common/obd_parser.h b/src/common/common/obd_parser.h new file mode 100644 index 00000000..40b34b47 --- /dev/null +++ b/src/common/common/obd_parser.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include +#include + +std::unordered_map parseObdData(const std::string& filename); +std::string serializeObdData(const std::unordered_map& obdData); diff --git a/src/main.cpp b/src/main.cpp index c637591f..0ce5101b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,6 +15,7 @@ #include "server/server_config.h" #include +#include #include // Enable nvidia @@ -34,24 +35,114 @@ enum class LaunchType { TwoPlayer, }; +/** + * @brief Holds config for both client and server + */ +struct Config { + LaunchType launchType = LaunchType::Both; + + ServerConfig server; + ClientConfig client; +}; + +/** + * @brief Loads config eg window size from the config.txt file + * @param config The config object to put the data into + */ +void loadFromConfigFile(Config& config) +{ + if (std::filesystem::exists("client.obd")) { + auto clientData = parseObdData(loadFileContents("client.obd")); + + config.client.fullScreen = std::stoi(clientData["fullscreen"]); + config.client.windowWidth = std::stoi(clientData["window_width"]); + config.client.windowHeight = std::stoi(clientData["window_height"]); + config.client.isFpsCapped = std::stoi(clientData["cap_fps"]); + config.client.shouldShowInstructions = + std::stoi(clientData["shouldShowInstructions"]); + config.client.fpsLimit = std::stoi(clientData["fps_limit"]); + config.client.fov = std::stoi(clientData["fov"]); + config.client.fpsLimit = std::stoi(clientData["fps_limit"]); + config.client.skinName = clientData["skin"]; + config.client.texturePack = clientData["texture_pack"]; + config.client.serverIp = clientData["server_ip"]; + } + else { + std::unordered_map clientData; + clientData.emplace("fullscreen", config.client.fullScreen ? "1" : "0"); + clientData.emplace("window_width", std::to_string(config.client.windowWidth)); + clientData.emplace("window_height", std::to_string(config.client.windowHeight)); + clientData.emplace("cap_fps", config.client.isFpsCapped ? "1" : "0"); + clientData.emplace("shouldShowInstructions", config.client.shouldShowInstructions ? "1" : "0"); + clientData.emplace("fps_limit", std::to_string(config.client.fpsLimit)); + clientData.emplace("fov", std::to_string(config.client.fov)); + clientData.emplace("fps_limit", std::to_string(config.client.fpsLimit)); + clientData.emplace("skin", config.client.skinName); + clientData.emplace("texture_pack", config.client.texturePack); + clientData.emplace("server_ip", config.client.serverIp); + + std::string clientDataSerialized = serializeObdData(clientData); + std::ofstream clientFile("client.obd"); + if (!clientFile) { + std::cerr << "Cannot open client.obd for writing\n"; + } + clientFile << clientDataSerialized << std::endl; + } + + if (std::filesystem::exists("server.obd")) { + auto serverData = parseObdData(loadFileContents("server.obd")); + config.server.worldSize = std::stoi(serverData["world_size"]); + } + else { + std::unordered_map serverData; + serverData.emplace("world_size", std::to_string(config.server.worldSize)); + + std::string serverDataSerialized = serializeObdData(serverData); + std::ofstream serverFile("server.obd"); + if (!serverFile) { + std::cerr << "Cannot open server.obd for writing\n"; + } + serverFile << serverDataSerialized << std::endl; + } +} + /** * @brief Parses the CLI arguments from the user * @param config The config to load data into * @param args CLI arguments paired as */ -void parseArgs(ClientConfig& config, LaunchType& launchType, +void parseArgs(Config& config, const std::vector>& args) { - // set launch type for (const auto& option : args) { + // Set launch type to be server. + // Option: MAX_CONNECTIONS 2-16 if (option.first == "-server") { - launchType = LaunchType::Server; + config.launchType = LaunchType::Server; + try { + int maxConnections = std::stoi(option.second); + if (maxConnections < 2) { + throw std::invalid_argument("Max connections must be at least " + + std::to_string(MIN_CONNECTIONS) + ".\n"); + } + else if (maxConnections > 16) { + throw std::invalid_argument("Max connections must be " + + std::to_string(MAX_CONNECTIONS) + + " or below.\n"); + } + } + catch (std::invalid_argument& e) { + std::cout << "Unable to set max connections, defaulting to " + "4. Reason: " + << e.what() << "\n"; + config.server.maxConnections = 4; + } } else if (option.first == "-client") { - launchType = LaunchType::Client; + config.launchType = LaunchType::Client; } else if (option.first == "-skin") { - config.set_skinName(option.second); + config.client.skinName = option.second; } } } @@ -130,7 +221,7 @@ void printInstructions() */ int launchClient(const ClientConfig& config, bool launchingJustClient) { - if (launchingJustClient && config.get_shouldShowInstructions()) { + if (launchingJustClient && config.shouldShowInstructions) { printInstructions(); } LOG("Launcher", "Launching client"); @@ -160,15 +251,15 @@ int launchClient(const ClientConfig& config, bool launchingJustClient) * @param config The config to be used by client/server engines * @return int Exit flag (Success, or Failure) */ -int launchBoth(const ClientConfig& clientConfig, const ServerConfig& serverConfig) +int launchBoth(const Config& config) { - ServerLauncher server(serverConfig, sf::milliseconds(5000)); + ServerLauncher server(config.server, sf::milliseconds(5000)); std::thread serverThread([&server]() { LOG("Launcher", "Launching server"); server.runServerEngine(); }); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - int exit = launchClient(clientConfig, false); + int exit = launchClient(config.client, false); serverThread.join(); return exit; } @@ -178,18 +269,18 @@ int launchBoth(const ClientConfig& clientConfig, const ServerConfig& serverConfi * @param config The config to be used by client/server engines * @return int Exit flag (Success, or Failure) */ -int launchServerAnd2Players(const ClientConfig& clientConfig, const ServerConfig& serverConfig) +int launchServerAnd2Players(const Config& config) { - ServerLauncher server(serverConfig, sf::milliseconds(5000)); + ServerLauncher server(config.server, sf::milliseconds(5000)); std::thread serverThread([&server]() { LOG("Launcher", "Launching server"); server.runServerEngine(); }); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - std::thread client2(launchClient, clientConfig, false); + std::thread client2(launchClient, config.client, false); - int exit = launchClient(clientConfig, false); + int exit = launchClient(config.client, false); client2.join(); serverThread.join(); @@ -199,11 +290,12 @@ int launchServerAnd2Players(const ClientConfig& clientConfig, const ServerConfig int main(int argc, char** argv) { - // read config files - ClientConfig clientConfig("client.obd"); - ServerConfig serverConfig("server.obd"); + Config config; + + if (enet_initialize() != 0) { + return exitFailure("Failed to initialise enet"); + } - // parse command line arguments std::vector> args; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-' && argc > i + 1) { @@ -211,43 +303,21 @@ int main(int argc, char** argv) } } - LaunchType launchType; - parseArgs(clientConfig, launchType, args); - - try { - if (serverConfig.get_maxConnections() < 2) { - throw std::invalid_argument("Max connections must be at least " + - std::to_string(MIN_CONNECTIONS) + ".\n"); - } - else if (serverConfig.get_maxConnections() > 16) { - throw std::invalid_argument("Max connections must be " + - std::to_string(MAX_CONNECTIONS) + - " or below.\n"); - } - } - catch (std::invalid_argument& e) { - std::cout << "Unable to set max connections, defaulting to " - "4. Reason: " - << e.what() << "\n"; - serverConfig.set_maxConnections(4); - } - - if (enet_initialize() != 0) { - return exitFailure("Failed to initialise enet"); - } + loadFromConfigFile(config); + parseArgs(config, args); - switch (launchType) { + switch (config.launchType) { case LaunchType::Both: - return launchBoth(clientConfig, serverConfig); + return launchBoth(config); case LaunchType::Server: - return launchServer(serverConfig); + return launchServer(config.server); case LaunchType::Client: - return launchClient(clientConfig, true); + return launchClient(config.client, true); case LaunchType::TwoPlayer: - return launchServerAnd2Players(clientConfig, serverConfig); + return launchServerAnd2Players(config); } enet_deinitialize(); diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 7511e1fc..1ca8a487 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -1,7 +1,6 @@ add_library(ob-server server_engine.cpp - server_config.cpp network/server.cpp world/terrain_generation.cpp lua/data_api.cpp @@ -20,4 +19,4 @@ target_link_libraries(ob-server ${SFML_LIBRARIES} ${SFML_DEPENDENCIES} ${CMAKE_DL_LIBS} -) +) \ No newline at end of file diff --git a/src/server/network/server.cpp b/src/server/network/server.cpp index 922b302d..7cfe58af 100644 --- a/src/server/network/server.cpp +++ b/src/server/network/server.cpp @@ -11,9 +11,11 @@ #include "../world/terrain_generation.h" +#include + Server::Server(const ServerConfig& config) : NetworkHost("Server") - , m_worldSize(config.get_worldSize()) + , m_worldSize(config.worldSize) { // clang-format off m_commandDispatcher.addCommand(ServerCommand::BlockEdit, &Server::onBlockEdit); diff --git a/src/server/server_config.cpp b/src/server/server_config.cpp deleted file mode 100644 index b9d8b581..00000000 --- a/src/server/server_config.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include - -#include "server_config.h" - -ServerConfig::ServerConfig(const std::string& fileName) - : ObdConfig(fileName) -{ - if (m_keyvalues.count("maxConnections")) - m_maxConnections = std::stoi(m_keyvalues["maxConnections"]); - if (m_keyvalues.count("worldSize")) - m_maxConnections = std::stoi(m_keyvalues["worldSize"]); -} - -ServerConfig::~ServerConfig() -{ - m_keyvalues["maxConnections"] = std::to_string(m_maxConnections); - m_keyvalues["worldSize"] = std::to_string(m_worldSize); -} diff --git a/src/server/server_config.h b/src/server/server_config.h index ecf3b609..91e2126d 100644 --- a/src/server/server_config.h +++ b/src/server/server_config.h @@ -1,17 +1,8 @@ #pragma once -#include +#include -class ServerConfig : public ObdConfig { - int m_maxConnections = 4; - int m_worldSize = 4; - public: - ServerConfig(const std::string& filePath); - ~ServerConfig(); - - int get_maxConnections() const { return m_maxConnections; } - void set_maxConnections(const int value) { m_maxConnections = value; } - - int get_worldSize() const { return m_worldSize; } - void set_worldSize(const int value) { m_worldSize = value; } -}; +struct ServerConfig { + int maxConnections = 4; + int worldSize = 16; +}; \ No newline at end of file diff --git a/src/server/server_engine.cpp b/src/server/server_engine.cpp index 9c814a29..4f372a60 100644 --- a/src/server/server_engine.cpp +++ b/src/server/server_engine.cpp @@ -16,7 +16,7 @@ ServerLauncher::ServerLauncher(const ServerConfig& config, sf::Time timeout) void ServerLauncher::runServerEngine() { - if (!m_server.createAsServer(m_config.get_maxConnections())) { + if (!m_server.createAsServer(m_config.maxConnections)) { std::cout << "Failed to create server.\n"; return; } @@ -61,4 +61,4 @@ void ServerLauncher::runServerEngine() << std::endl; } console.join(); -} +} \ No newline at end of file diff --git a/tests/common/obd_parser_test.cpp b/tests/common/obd_parser_test.cpp index bb51f303..6cd85579 100644 --- a/tests/common/obd_parser_test.cpp +++ b/tests/common/obd_parser_test.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include const std::string dataObd = From 6e13235b742d2a0403e9e8faec90394f1db69627 Mon Sep 17 00:00:00 2001 From: Mark Gross Date: Mon, 10 Feb 2020 19:26:19 -0800 Subject: [PATCH 7/7] Revert "Revert "Config overhaul"" Yep I broke something. --- src/client/CMakeLists.txt | 1 + src/client/client.cpp | 10 +- src/client/client_config.cpp | 46 +++++++++ src/client/client_config.h | 61 ++++++++---- src/client/window.cpp | 10 +- src/common/common/CMakeLists.txt | 4 +- src/common/common/obd_config.cpp | 60 ++++++++++++ src/common/common/obd_config.h | 17 ++++ src/common/common/obd_parser.cpp | 31 ------ src/common/common/obd_parser.h | 8 -- src/main.cpp | 162 +++++++++---------------------- src/server/CMakeLists.txt | 3 +- src/server/network/server.cpp | 4 +- src/server/server_config.cpp | 18 ++++ src/server/server_config.h | 19 +++- src/server/server_engine.cpp | 4 +- tests/common/obd_parser_test.cpp | 2 +- 17 files changed, 264 insertions(+), 196 deletions(-) create mode 100644 src/client/client_config.cpp create mode 100644 src/common/common/obd_config.cpp create mode 100644 src/common/common/obd_config.h delete mode 100644 src/common/common/obd_parser.cpp delete mode 100644 src/common/common/obd_parser.h create mode 100644 src/server/server_config.cpp diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index ecb5f585..d0fc51b6 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -11,6 +11,7 @@ add_library(ob-client renderer/chunk_renderer.cpp network/client_commands.cpp client.cpp + client_config.cpp maths.cpp client_engine.cpp window.cpp diff --git a/src/client/client.cpp b/src/client/client.cpp index 487a0433..314e1379 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -23,7 +23,7 @@ bool isVoxelSelectable(VoxelType voxelType) Client::Client(const ClientConfig& config) : NetworkHost("Client") - , m_gui(config.windowWidth, config.windowHeight) + , m_gui(config.get_windowWidth(), config.get_windowHeight()) { // clang-format off m_commandDispatcher.addCommand(ClientCommand::BlockUpdate, &Client::onBlockUpdate); @@ -70,10 +70,10 @@ bool Client::init(const ClientConfig& config, float aspect) m_errorSkinTexture.create("skins/error"); m_errorSkinTexture.bind(); - m_texturePack = config.texturePack; + m_texturePack = config.get_texturePack(); // Set up the server connection - auto peer = NetworkHost::createAsClient(config.serverIp); + auto peer = NetworkHost::createAsClient(config.get_serverIp()); if (!peer) { return false; } @@ -83,14 +83,14 @@ bool Client::init(const ClientConfig& config, float aspect) mp_player = &m_entities[NetworkHost::getPeerId()]; mp_player->position = {CHUNK_SIZE * 2, CHUNK_SIZE * 2 + 1, CHUNK_SIZE * 2}; - m_rawPlayerSkin = gl::loadRawImageFile("skins/" + config.skinName); + m_rawPlayerSkin = gl::loadRawImageFile("skins/" + config.get_skinName()); sendPlayerSkin(m_rawPlayerSkin); m_projectionMatrix = glm::perspective(3.14f / 2.0f, aspect, 0.01f, 2000.0f); // Font and text m_debugTextFont.init("res/VeraMono-Bold.ttf", 512); - m_debugText.setPosition({2, config.windowHeight - 16, 0}); + m_debugText.setPosition({2, config.get_windowHeight() - 16, 0}); m_debugText.setCharSize(16); m_debugText.setFont(m_debugTextFont); m_debugText.setText("Current FPS: 60"); diff --git a/src/client/client_config.cpp b/src/client/client_config.cpp new file mode 100644 index 00000000..dbcb7c61 --- /dev/null +++ b/src/client/client_config.cpp @@ -0,0 +1,46 @@ +#include + +#include "client_config.h" + +ClientConfig::ClientConfig(const std::string& fileName) + : ObdConfig(fileName) +{ + if (m_keyvalues.count("isFpsCapped")) + m_isFpsCapped = m_keyvalues["isFpsCapped"] == "true" ? true : false; + if (m_keyvalues.count("shouldShowInstructions")) + m_shouldShowInstructions = m_keyvalues["shouldShowInstructions"] == "true" ? true : false; + if (m_keyvalues.count("fullScreen")) + m_fullScreen = m_keyvalues["fullScreen"] == "true" ? true : false; + + if (m_keyvalues.count("windowWidth")) + m_windowWidth = std::stoi(m_keyvalues["windowWidth"]); + if (m_keyvalues.count("windowHeight")) + m_windowHeight = std::stoi(m_keyvalues["windowHeight"]); + if (m_keyvalues.count("fpsLimit")) + m_fpsLimit = std::stoi(m_keyvalues["fpsLimit"]); + if (m_keyvalues.count("fov")) + m_fov = std::stoi(m_keyvalues["fov"]); + + if (m_keyvalues.count("skinName")) + m_skinName = m_keyvalues["skinName"]; + if (m_keyvalues.count("texturePack")) + m_texturePack = m_keyvalues["texturePack"]; + if (m_keyvalues.count("serverIp")) + m_serverIp = m_keyvalues["serverIp"]; +} + +ClientConfig::~ClientConfig() +{ + m_keyvalues["isFpsCapped"] = m_isFpsCapped ? "true" : "false"; + m_keyvalues["shouldShowInstructions"] = m_shouldShowInstructions ? "true" : "false"; + m_keyvalues["fullScreen"] = m_fullScreen ? "true" : "false"; + + m_keyvalues["windowWidth"] = std::to_string(m_windowWidth); + m_keyvalues["windowHeight"] = std::to_string(m_windowHeight); + m_keyvalues["fpsLimit"] = std::to_string(m_fpsLimit); + m_keyvalues["fov"] = std::to_string(m_fov); + + m_keyvalues["skinName"] = m_skinName; + m_keyvalues["texturePack"] = m_texturePack; + m_keyvalues["serverIp"] = m_serverIp; +} diff --git a/src/client/client_config.h b/src/client/client_config.h index 00e87be6..d74f7229 100644 --- a/src/client/client_config.h +++ b/src/client/client_config.h @@ -1,26 +1,53 @@ #pragma once -#include #include +#include -#include +class ClientConfig : public ObdConfig { + bool m_fullScreen = false; + int m_windowWidth = 1280; + int m_windowHeight = 720; + int m_fpsLimit = 60; + int m_fov = 65; -/** - * @brief Config options for client - * Mostly for the window and general graphics options - */ -struct ClientConfig { - bool fullScreen = false; - int windowWidth = 1280; - int windowHeight = 720; - int fpsLimit = 60; - int fov = 65; + bool m_isFpsCapped = true; + bool m_shouldShowInstructions = true; - bool isFpsCapped = true; - bool shouldShowInstructions = true; + std::string m_skinName = "player"; + std::string m_texturePack = "default"; - std::string skinName = "player"; - std::string texturePack = "default"; + std::string m_serverIp = "127.0.0.1"; + public: + ClientConfig(const std::string& fileName); + ~ClientConfig(); - std::string serverIp = "127.0.0.1"; + bool get_fullScreen() const { return m_fullScreen; } + void set_fullScreen(const bool value) { m_fullScreen = value; } + + bool get_isFpsCapped() const { return m_isFpsCapped; } + void set_isFpsCapped(const bool value) { m_isFpsCapped = value; } + + bool get_shouldShowInstructions() const { return m_shouldShowInstructions; } + void set_shouldShowInstructions(const bool value) { m_shouldShowInstructions = value; } + + int get_windowWidth() const { return m_windowWidth; } + void set_windowWidth(const int value) { m_windowWidth = value; } + + int get_windowHeight() const { return m_windowHeight; } + void set_windowHeight(const int value) { m_windowHeight = value; } + + int get_fpsLimit() const { return m_fpsLimit; } + void set_fpsLimit(const int value) { m_fpsLimit = value; } + + int get_fov() const { return m_fov; } + void set_fov(const int value) { m_fov = value; } + + std::string get_skinName() const { return m_skinName; } + void set_skinName(const std::string& value) { m_skinName = value; } + + std::string get_texturePack() const { return m_texturePack; } + void set_texturePack(const std::string& value) { m_texturePack = value; } + + std::string get_serverIp() const { return m_serverIp; } + void set_serverIp(const std::string& value) { m_serverIp = value; } }; diff --git a/src/client/window.cpp b/src/client/window.cpp index 232deb52..e1dfdb24 100644 --- a/src/client/window.cpp +++ b/src/client/window.cpp @@ -7,20 +7,20 @@ Window::Window(const ClientConfig& config) { window.setKeyRepeatEnabled(false); - if (config.fullScreen) { + if (config.get_fullScreen()) { create(sf::VideoMode::getDesktopMode(), sf::Style::Fullscreen); width = window.getSize().x; height = window.getSize().y; aspect = static_cast(width) / static_cast(height); } else { - width = static_cast(config.windowWidth); - height = static_cast(config.windowHeight); + width = static_cast(config.get_windowWidth()); + height = static_cast(config.get_windowHeight()); aspect = static_cast(width) / static_cast(height); create({width, height}, sf::Style::Close); } - if (config.isFpsCapped) { - window.setFramerateLimit(config.fpsLimit); + if (config.get_isFpsCapped()) { + window.setFramerateLimit(config.get_fpsLimit()); } } diff --git a/src/common/common/CMakeLists.txt b/src/common/common/CMakeLists.txt index 1e3eaac3..32a144fb 100644 --- a/src/common/common/CMakeLists.txt +++ b/src/common/common/CMakeLists.txt @@ -1,7 +1,7 @@ add_library(ob-common file_io.cpp - obd_parser.cpp + obd_config.cpp debug.cpp network/net_host.cpp scripting/script_engine.cpp @@ -21,4 +21,4 @@ target_link_libraries(ob-common ${SFML_LIBRARIES} ${SFML_DEPENDENCIES} ${CMAKE_DL_LIBS} -) \ No newline at end of file +) diff --git a/src/common/common/obd_config.cpp b/src/common/common/obd_config.cpp new file mode 100644 index 00000000..11ee2572 --- /dev/null +++ b/src/common/common/obd_config.cpp @@ -0,0 +1,60 @@ +#include +#include +#include +#include +#include + +#include "obd_config.h" + +// member definitions for ObdConfig +ObdConfig::ObdConfig(const std::string& filePath) + : m_filePath(filePath) +{ + if (std::filesystem::exists(filePath)) { + m_filePath = filePath; + std::ifstream file(m_filePath); + if (!file.is_open()) { + std::cerr << "Could not open file " << m_filePath << std::endl; + return; + } + std::stringstream stream; + stream << file.rdbuf(); + + m_keyvalues = parseObdData(stream.str()); + } +} + +ObdConfig::~ObdConfig() +{ + std::ofstream file(m_filePath); + if (!file.is_open()) { + std::cerr << "Could not write to " << m_filePath << std::endl; + return; + } + file << serializeObdData(m_keyvalues); +} + +// helper functions +std::unordered_map parseObdData(const std::string& obdData) +{ + std::istringstream contents(obdData); + std::string key; + std::string value; + std::unordered_map data; + + while (contents >> key) { + contents >> value; + data.emplace(key, value); + } + + return data; +} + +std::string serializeObdData(const std::unordered_map& obdData) +{ + std::ostringstream output; + for (auto const& pair : obdData) { + output << pair.first << " " << pair.second << "\n"; + } + return output.str(); +} diff --git a/src/common/common/obd_config.h b/src/common/common/obd_config.h new file mode 100644 index 00000000..8bc584a2 --- /dev/null +++ b/src/common/common/obd_config.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +std::unordered_map parseObdData(const std::string& obdData); +std::string serializeObdData(const std::unordered_map& obdData); + +class ObdConfig +{ + std::string m_filePath; + public: + ObdConfig(const std::string& filePath); // implicitly read config file + ~ObdConfig(); // write back to file when the config goes out of scope + protected: + std::unordered_map m_keyvalues; +}; diff --git a/src/common/common/obd_parser.cpp b/src/common/common/obd_parser.cpp deleted file mode 100644 index 247cc1f4..00000000 --- a/src/common/common/obd_parser.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include "obd_parser.h" - -#include "file_io.h" -#include -#include -#include -#include - -std::unordered_map parseObdData(const std::string& obdData) -{ - std::istringstream contents(obdData); - std::string key; - std::string value; - std::unordered_map data; - - while (contents >> key) { - contents >> value; - data.emplace(key, value); - } - - return data; -} - -std::string serializeObdData(const std::unordered_map& obdData) -{ - std::ostringstream output; - for (auto const& pair : obdData) { - output << pair.first << " " << pair.second << "\n"; - } - return output.str(); -} diff --git a/src/common/common/obd_parser.h b/src/common/common/obd_parser.h deleted file mode 100644 index 40b34b47..00000000 --- a/src/common/common/obd_parser.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -#include -#include -#include - -std::unordered_map parseObdData(const std::string& filename); -std::string serializeObdData(const std::unordered_map& obdData); diff --git a/src/main.cpp b/src/main.cpp index 0ce5101b..c637591f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,7 +15,6 @@ #include "server/server_config.h" #include -#include #include // Enable nvidia @@ -35,114 +34,24 @@ enum class LaunchType { TwoPlayer, }; -/** - * @brief Holds config for both client and server - */ -struct Config { - LaunchType launchType = LaunchType::Both; - - ServerConfig server; - ClientConfig client; -}; - -/** - * @brief Loads config eg window size from the config.txt file - * @param config The config object to put the data into - */ -void loadFromConfigFile(Config& config) -{ - if (std::filesystem::exists("client.obd")) { - auto clientData = parseObdData(loadFileContents("client.obd")); - - config.client.fullScreen = std::stoi(clientData["fullscreen"]); - config.client.windowWidth = std::stoi(clientData["window_width"]); - config.client.windowHeight = std::stoi(clientData["window_height"]); - config.client.isFpsCapped = std::stoi(clientData["cap_fps"]); - config.client.shouldShowInstructions = - std::stoi(clientData["shouldShowInstructions"]); - config.client.fpsLimit = std::stoi(clientData["fps_limit"]); - config.client.fov = std::stoi(clientData["fov"]); - config.client.fpsLimit = std::stoi(clientData["fps_limit"]); - config.client.skinName = clientData["skin"]; - config.client.texturePack = clientData["texture_pack"]; - config.client.serverIp = clientData["server_ip"]; - } - else { - std::unordered_map clientData; - clientData.emplace("fullscreen", config.client.fullScreen ? "1" : "0"); - clientData.emplace("window_width", std::to_string(config.client.windowWidth)); - clientData.emplace("window_height", std::to_string(config.client.windowHeight)); - clientData.emplace("cap_fps", config.client.isFpsCapped ? "1" : "0"); - clientData.emplace("shouldShowInstructions", config.client.shouldShowInstructions ? "1" : "0"); - clientData.emplace("fps_limit", std::to_string(config.client.fpsLimit)); - clientData.emplace("fov", std::to_string(config.client.fov)); - clientData.emplace("fps_limit", std::to_string(config.client.fpsLimit)); - clientData.emplace("skin", config.client.skinName); - clientData.emplace("texture_pack", config.client.texturePack); - clientData.emplace("server_ip", config.client.serverIp); - - std::string clientDataSerialized = serializeObdData(clientData); - std::ofstream clientFile("client.obd"); - if (!clientFile) { - std::cerr << "Cannot open client.obd for writing\n"; - } - clientFile << clientDataSerialized << std::endl; - } - - if (std::filesystem::exists("server.obd")) { - auto serverData = parseObdData(loadFileContents("server.obd")); - config.server.worldSize = std::stoi(serverData["world_size"]); - } - else { - std::unordered_map serverData; - serverData.emplace("world_size", std::to_string(config.server.worldSize)); - - std::string serverDataSerialized = serializeObdData(serverData); - std::ofstream serverFile("server.obd"); - if (!serverFile) { - std::cerr << "Cannot open server.obd for writing\n"; - } - serverFile << serverDataSerialized << std::endl; - } -} - /** * @brief Parses the CLI arguments from the user * @param config The config to load data into * @param args CLI arguments paired as */ -void parseArgs(Config& config, +void parseArgs(ClientConfig& config, LaunchType& launchType, const std::vector>& args) { + // set launch type for (const auto& option : args) { - // Set launch type to be server. - // Option: MAX_CONNECTIONS 2-16 if (option.first == "-server") { - config.launchType = LaunchType::Server; - try { - int maxConnections = std::stoi(option.second); - if (maxConnections < 2) { - throw std::invalid_argument("Max connections must be at least " + - std::to_string(MIN_CONNECTIONS) + ".\n"); - } - else if (maxConnections > 16) { - throw std::invalid_argument("Max connections must be " + - std::to_string(MAX_CONNECTIONS) + - " or below.\n"); - } - } - catch (std::invalid_argument& e) { - std::cout << "Unable to set max connections, defaulting to " - "4. Reason: " - << e.what() << "\n"; - config.server.maxConnections = 4; - } + launchType = LaunchType::Server; } else if (option.first == "-client") { - config.launchType = LaunchType::Client; + launchType = LaunchType::Client; } else if (option.first == "-skin") { - config.client.skinName = option.second; + config.set_skinName(option.second); } } } @@ -221,7 +130,7 @@ void printInstructions() */ int launchClient(const ClientConfig& config, bool launchingJustClient) { - if (launchingJustClient && config.shouldShowInstructions) { + if (launchingJustClient && config.get_shouldShowInstructions()) { printInstructions(); } LOG("Launcher", "Launching client"); @@ -251,15 +160,15 @@ int launchClient(const ClientConfig& config, bool launchingJustClient) * @param config The config to be used by client/server engines * @return int Exit flag (Success, or Failure) */ -int launchBoth(const Config& config) +int launchBoth(const ClientConfig& clientConfig, const ServerConfig& serverConfig) { - ServerLauncher server(config.server, sf::milliseconds(5000)); + ServerLauncher server(serverConfig, sf::milliseconds(5000)); std::thread serverThread([&server]() { LOG("Launcher", "Launching server"); server.runServerEngine(); }); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - int exit = launchClient(config.client, false); + int exit = launchClient(clientConfig, false); serverThread.join(); return exit; } @@ -269,18 +178,18 @@ int launchBoth(const Config& config) * @param config The config to be used by client/server engines * @return int Exit flag (Success, or Failure) */ -int launchServerAnd2Players(const Config& config) +int launchServerAnd2Players(const ClientConfig& clientConfig, const ServerConfig& serverConfig) { - ServerLauncher server(config.server, sf::milliseconds(5000)); + ServerLauncher server(serverConfig, sf::milliseconds(5000)); std::thread serverThread([&server]() { LOG("Launcher", "Launching server"); server.runServerEngine(); }); std::this_thread::sleep_for(std::chrono::milliseconds(100)); - std::thread client2(launchClient, config.client, false); + std::thread client2(launchClient, clientConfig, false); - int exit = launchClient(config.client, false); + int exit = launchClient(clientConfig, false); client2.join(); serverThread.join(); @@ -290,12 +199,11 @@ int launchServerAnd2Players(const Config& config) int main(int argc, char** argv) { - Config config; - - if (enet_initialize() != 0) { - return exitFailure("Failed to initialise enet"); - } + // read config files + ClientConfig clientConfig("client.obd"); + ServerConfig serverConfig("server.obd"); + // parse command line arguments std::vector> args; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-' && argc > i + 1) { @@ -303,21 +211,43 @@ int main(int argc, char** argv) } } - loadFromConfigFile(config); - parseArgs(config, args); + LaunchType launchType; + parseArgs(clientConfig, launchType, args); + + try { + if (serverConfig.get_maxConnections() < 2) { + throw std::invalid_argument("Max connections must be at least " + + std::to_string(MIN_CONNECTIONS) + ".\n"); + } + else if (serverConfig.get_maxConnections() > 16) { + throw std::invalid_argument("Max connections must be " + + std::to_string(MAX_CONNECTIONS) + + " or below.\n"); + } + } + catch (std::invalid_argument& e) { + std::cout << "Unable to set max connections, defaulting to " + "4. Reason: " + << e.what() << "\n"; + serverConfig.set_maxConnections(4); + } + + if (enet_initialize() != 0) { + return exitFailure("Failed to initialise enet"); + } - switch (config.launchType) { + switch (launchType) { case LaunchType::Both: - return launchBoth(config); + return launchBoth(clientConfig, serverConfig); case LaunchType::Server: - return launchServer(config.server); + return launchServer(serverConfig); case LaunchType::Client: - return launchClient(config.client, true); + return launchClient(clientConfig, true); case LaunchType::TwoPlayer: - return launchServerAnd2Players(config); + return launchServerAnd2Players(clientConfig, serverConfig); } enet_deinitialize(); diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 1ca8a487..7511e1fc 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(ob-server server_engine.cpp + server_config.cpp network/server.cpp world/terrain_generation.cpp lua/data_api.cpp @@ -19,4 +20,4 @@ target_link_libraries(ob-server ${SFML_LIBRARIES} ${SFML_DEPENDENCIES} ${CMAKE_DL_LIBS} -) \ No newline at end of file +) diff --git a/src/server/network/server.cpp b/src/server/network/server.cpp index 7cfe58af..922b302d 100644 --- a/src/server/network/server.cpp +++ b/src/server/network/server.cpp @@ -11,11 +11,9 @@ #include "../world/terrain_generation.h" -#include - Server::Server(const ServerConfig& config) : NetworkHost("Server") - , m_worldSize(config.worldSize) + , m_worldSize(config.get_worldSize()) { // clang-format off m_commandDispatcher.addCommand(ServerCommand::BlockEdit, &Server::onBlockEdit); diff --git a/src/server/server_config.cpp b/src/server/server_config.cpp new file mode 100644 index 00000000..b9d8b581 --- /dev/null +++ b/src/server/server_config.cpp @@ -0,0 +1,18 @@ +#include + +#include "server_config.h" + +ServerConfig::ServerConfig(const std::string& fileName) + : ObdConfig(fileName) +{ + if (m_keyvalues.count("maxConnections")) + m_maxConnections = std::stoi(m_keyvalues["maxConnections"]); + if (m_keyvalues.count("worldSize")) + m_maxConnections = std::stoi(m_keyvalues["worldSize"]); +} + +ServerConfig::~ServerConfig() +{ + m_keyvalues["maxConnections"] = std::to_string(m_maxConnections); + m_keyvalues["worldSize"] = std::to_string(m_worldSize); +} diff --git a/src/server/server_config.h b/src/server/server_config.h index 91e2126d..ecf3b609 100644 --- a/src/server/server_config.h +++ b/src/server/server_config.h @@ -1,8 +1,17 @@ #pragma once -#include +#include -struct ServerConfig { - int maxConnections = 4; - int worldSize = 16; -}; \ No newline at end of file +class ServerConfig : public ObdConfig { + int m_maxConnections = 4; + int m_worldSize = 4; + public: + ServerConfig(const std::string& filePath); + ~ServerConfig(); + + int get_maxConnections() const { return m_maxConnections; } + void set_maxConnections(const int value) { m_maxConnections = value; } + + int get_worldSize() const { return m_worldSize; } + void set_worldSize(const int value) { m_worldSize = value; } +}; diff --git a/src/server/server_engine.cpp b/src/server/server_engine.cpp index 4f372a60..9c814a29 100644 --- a/src/server/server_engine.cpp +++ b/src/server/server_engine.cpp @@ -16,7 +16,7 @@ ServerLauncher::ServerLauncher(const ServerConfig& config, sf::Time timeout) void ServerLauncher::runServerEngine() { - if (!m_server.createAsServer(m_config.maxConnections)) { + if (!m_server.createAsServer(m_config.get_maxConnections())) { std::cout << "Failed to create server.\n"; return; } @@ -61,4 +61,4 @@ void ServerLauncher::runServerEngine() << std::endl; } console.join(); -} \ No newline at end of file +} diff --git a/tests/common/obd_parser_test.cpp b/tests/common/obd_parser_test.cpp index 6cd85579..bb51f303 100644 --- a/tests/common/obd_parser_test.cpp +++ b/tests/common/obd_parser_test.cpp @@ -1,6 +1,6 @@ #include -#include +#include #include const std::string dataObd =