diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ef1377..a94059e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,33 +22,8 @@ add_subdirectory("include/glfw") add_subdirectory("include/glm") add_subdirectory("include/enet") add_subdirectory("include/zstd") -set(LINKED_LIBS glfw pthread dl - glm::glm_static enet::enet_static zstd::zstd_static) -file(GLOB_RECURSE SOURCES "src/*/*.cpp") -file(GLOB INCLUDE_SOURCES - "include/imgui/*.cpp" - "include/FastNoiseSIMD/*.cpp" - "include/tracy/TracyClient.cpp" - "include/meshoptimizer/*.cpp" - "include/gl3w/gl3w.c" -) -set(INCLUDE_LIBS - "include/imgui" - "include/FastNoiseSIMD" - "include/toml++" - "include/robin_hood" - "include/libguarded" - "include/tracy" - "include/meshoptimizer" - "include/gl3w" -) - -add_executable(univerxel "src/main.cpp" ${SOURCES} ${INCLUDE_SOURCES}) -target_compile_features(univerxel PUBLIC cxx_std_17) -target_link_libraries(univerxel ${LINKED_LIBS}) -target_include_directories(univerxel PRIVATE ${INCLUDE_LIBS}) -target_compile_definitions(univerxel PRIVATE FIXED_WINDOW=${FIXED_WINDOW} HN_USE_FILESYSTEM=1) +add_compile_definitions(FIXED_WINDOW=${FIXED_WINDOW} HN_USE_FILESYSTEM=1) if(PROFILING) add_compile_definitions(TRACY_ENABLE=1) endif(PROFILING) @@ -62,7 +37,37 @@ if(USE_FMA) add_definitions(-mfma) endif(USE_FMA) +file(GLOB_RECURSE CORE_SOURCES "src/core/*.cpp" "include/tracy/TracyClient.cpp") +set(CORE_HEADERS "include/toml++" "include/robin_hood" "include/libguarded" "include/tracy") +set(CORE_LIBS pthread dl glm::glm_static enet::enet_static zstd::zstd_static) +file(GLOB_RECURSE CLIENT_SOURCES "src/client/*.cpp" "include/imgui/*.cpp" "include/meshoptimizer/*.cpp" "include/gl3w/gl3w.c") +set(CLIENT_HEADERS "include/imgui" "include/meshoptimizer" "include/gl3w") +set(CLIENT_LIBS glfw) + +file(GLOB_RECURSE SERVER_SOURCES "src/server/*.cpp" "include/FastNoiseSIMD/*.cpp") +set(SERVER_HEADERS "include/FastNoiseSIMD") +set(SERVER_LINKED) + +# All in one exec +add_executable(univerxel "src/main.cpp" ${CORE_SOURCES} ${CLIENT_SOURCES} ${SERVER_SOURCES}) +target_compile_features(univerxel PUBLIC cxx_std_17) +target_link_libraries(univerxel ${CORE_LIBS} ${CLIENT_LIBS} ${SERVER_LIBS}) +target_include_directories(univerxel PRIVATE ${CORE_HEADERS} ${CLIENT_HEADERS} ${SERVER_HEADERS}) + +# Standalone server +add_executable(univerxel-server EXCLUDE_FROM_ALL "src/server.cpp" ${CORE_SOURCES} ${SERVER_SOURCES}) +target_compile_features(univerxel-server PUBLIC cxx_std_17) +target_link_libraries(univerxel-server ${CORE_LIBS} ${SERVER_LIBS}) +target_include_directories(univerxel-server PRIVATE ${CORE_HEADERS} ${SERVER_HEADERS}) + +# Dumb client +add_executable(univerxel-client EXCLUDE_FROM_ALL "src/client.cpp" ${CORE_SOURCES} ${CLIENT_SOURCES}) +target_compile_features(univerxel-client PUBLIC cxx_std_17) +target_link_libraries(univerxel-client ${CORE_LIBS} ${CLIENT_LIBS}) +target_include_directories(univerxel-client PRIVATE ${CORE_HEADERS} ${CLIENT_HEADERS}) + +# Resource client files + default zstd.dict file(COPY resource/content DESTINATION ${CMAKE_BINARY_DIR}) # Docs @@ -71,14 +76,3 @@ add_custom_target(docs WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "Build doc." ) - -# Builtin models -file(GLOB_RECURSE MCT_SOURCES "src/model_contouring.cpp" "src/*/*.cpp") -add_executable(model_contouring EXCLUDE_FROM_ALL ${MCT_SOURCES} ${INCLUDE_SOURCES}) -target_compile_features(model_contouring PUBLIC cxx_std_17) -target_link_libraries(model_contouring ${LINKED_LIBS}) -target_include_directories(model_contouring PRIVATE ${INCLUDE_LIBS}) - -add_custom_command(OUTPUT "${CMAKE_BINARY_DIR}/content/model.ivb" - COMMAND "${CMAKE_BINARY_DIR}/model_contouring" DEPENDS model_contouring) -add_custom_target(render_models DEPENDS "${CMAKE_BINARY_DIR}/content/model.ivb") diff --git a/TODO.md b/TODO.md index 58042c3..d3facec 100644 --- a/TODO.md +++ b/TODO.md @@ -14,7 +14,7 @@ - [x] Compression - [ ] Encryption - [x] Embedded - - [ ] Standalone + - [x] Standalone ## Hello world diff --git a/include/glfw/CMakeLists.txt b/include/glfw/CMakeLists.txt index 1ded78b..14b9e9c 100644 --- a/include/glfw/CMakeLists.txt +++ b/include/glfw/CMakeLists.txt @@ -14,12 +14,12 @@ endif() set_property(GLOBAL PROPERTY USE_FOLDERS ON) -option(BUILD_SHARED_LIBS "Build shared libraries" OFF) -option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) -option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) -option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) -option(GLFW_INSTALL "Generate installation target" OFF) -option(GLFW_VULKAN_STATIC "Assume the Vulkan loader is linked with the application" OFF) +set(BUILD_SHARED_LIBS OFF) +set(GLFW_BUILD_EXAMPLES OFF) +set(GLFW_BUILD_TESTS OFF) +set(GLFW_BUILD_DOCS OFF) +set(GLFW_INSTALL OFF) +set(GLFW_VULKAN_STATIC OFF) include(GNUInstallDirs) include(CMakeDependentOption) diff --git a/include/imgui/impl_vk/imgui_impl_vulkan.cpp b/include/imgui/impl_vk/imgui_impl_vulkan.opp similarity index 100% rename from include/imgui/impl_vk/imgui_impl_vulkan.cpp rename to include/imgui/impl_vk/imgui_impl_vulkan.opp diff --git a/include/imgui/impl_vk/impl_glfw_gl.cpp b/include/imgui/impl_vk/impl_glfw_gl.opp similarity index 100% rename from include/imgui/impl_vk/impl_glfw_gl.cpp rename to include/imgui/impl_vk/impl_glfw_gl.opp diff --git a/include/imgui/impl_vk/main.cpp b/include/imgui/impl_vk/main.opp similarity index 100% rename from include/imgui/impl_vk/main.cpp rename to include/imgui/impl_vk/main.opp diff --git a/include/toml++/toml.h b/include/toml++/toml.h index bea5002..fde10be 100644 --- a/include/toml++/toml.h +++ b/include/toml++/toml.h @@ -1,3 +1,4 @@ +#define TOML_HEADER_ONLY 0 //# This file is a part of toml++ and is subject to the the terms of the MIT license. //# Copyright (c) 2019-2020 Mark Gillard //# See https://github.com/marzer/tomlplusplus/blob/master/LICENSE for the full license text. diff --git a/src/client.cpp b/src/client.cpp new file mode 100644 index 0000000..243de25 --- /dev/null +++ b/src/client.cpp @@ -0,0 +1,40 @@ +/** + * \file server.cpp + * \brief Univerxel client + * \author Maelys Bois + * \version 0.0.1 + * + * Univerxel standalone client program. + */ + +#define STANDALONE 1 +#include "client/Client.hpp" +#include "core/standalone_config.hpp" +#include "core/utils/tracy.hpp" + +/// Entry point +int main(int argc, char *argv[]){ + LOG("Univerxel client"); + +#if TRACY_ENABLE + LOG("Profiling !"); +#endif + + auto options = config::standalone_options(argc > 1 ? argv[1] : config::DEFAULT_FILE); + options.save(); + +#if TRACY_ENABLE + tracy::SetThreadName("Main"); +#endif + + net::Setup(); + + auto client = Client(options.get()); + client.run(nullptr); + + net::Destroy(); + + options.save(); + + return 0; +} \ No newline at end of file diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 5cfbbf2..f800806 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -180,7 +180,7 @@ void Client::run(server_handle* const localHandle) { ZoneScopedN("Swap"); pipeline->swapBuffer(window.getPtr()); inputs.poll(); - FrameMark; + FrameMarkNamed("Client"); } window.waitTargetFPS(); diff --git a/src/client/config.hpp b/src/client/config.hpp index 6653113..27e6aec 100644 --- a/src/client/config.hpp +++ b/src/client/config.hpp @@ -65,7 +65,13 @@ public: world.keepDistance = config["world"]["keep_distance"].value_or(world.keepDistance); voxel_density = config["world"]["voxel_density"].value_or(voxel_density); - if(!config["connection"]["use_local"].value_or(true)) { +#ifndef STANDALONE + const auto useLocal = config["connection"]["use_local"].value_or(true); +#else + const auto useLocal = false; +#endif + + if(!useLocal) { world::client::Universe::connection ct; ct.address = config["connection"]["address"].value_or(ct.address); ct.port = config["connection"]["port"].value_or(ct.port); @@ -138,9 +144,11 @@ public: if(connection.has_value()) { const auto &ct = connection.value(); config.insert_or_assign("connection", toml::table({ +#ifndef STANDALONE {"use_local", false}, +#endif {"address", ct.address}, - {"start_port", ct.port} + {"port", ct.port} })); } else { config.insert_or_assign("connection", toml::table({{"use_local", true}})); diff --git a/src/client/render/gl/UI.cpp b/src/client/render/gl/UI.cpp index 78cee26..a8619ca 100644 --- a/src/client/render/gl/UI.cpp +++ b/src/client/render/gl/UI.cpp @@ -1,5 +1,6 @@ #include "UI.hpp" +#include #include #include #include "Texture.hpp" diff --git a/src/client/world/DistantUniverse.cpp b/src/client/world/DistantUniverse.cpp index 883cd86..6dc0675 100644 --- a/src/client/world/DistantUniverse.cpp +++ b/src/client/world/DistantUniverse.cpp @@ -20,7 +20,7 @@ void DistantUniverse::update(voxel_pos pos, float deltaTime) { const auto chunkChange = cur_chunk != last_chunk; last_chunk = cur_chunk; - pullNetwork(); + pullNetwork(pos); { // Update alive areas ZoneScopedN("World"); @@ -38,19 +38,39 @@ void DistantUniverse::update(voxel_pos pos, float deltaTime) { } else { if(const auto neighbors = std::dynamic_pointer_cast(it_c->second)->update(deltaTime, true /*FIXME: rnd from contouring*/)) { contouring->onUpdate(std::make_pair(area.first, it_c->first), diff, chunks, neighbors.value()); - } else if(chunkChangeArea) { - contouring->onNotify(std::make_pair(area.first, it_c->first), diff, chunks); } ++it_c; } } + if (chunkChangeArea) { // Request missing chunks + ZoneScopedN("Missing"); + std::vector missing; + //TODO: use easy sphere fill + for (int x = -loadDistance; x <= loadDistance; x++) { + for (int y = -loadDistance; y <= loadDistance; y++) { + for (int z = -loadDistance; z <= loadDistance; z++) { + const auto dist2 = x * x + y * y + z * z; + if (dist2 <= loadDistance * loadDistance) { + const auto p = diff + chunk_pos(x, y, z); + if (chunks.inRange(p) && chunks.find(p) == chunks.end()) { + missing.push_back(p); + } + } + }}} + if(!missing.empty()) { + auto packet = net::Client::makePacket(net::client_packet_type::MISSING_CHUNKS, NULL, sizeof(area_id) + missing.size() * sizeof(chunk_pos), ENET_PACKET_FLAG_RELIABLE, peer.getSalt()); + packet.write(area.first); + packet.write(missing.data(), missing.size() * sizeof(chunk_pos)); + peer.send(packet.get(), net::channel_type::RELIABLE); + } + } } } } contouring->update(pos, areas); } -void DistantUniverse::pullNetwork() { +void DistantUniverse::pullNetwork(voxel_pos pos) { ZoneScopedN("Pull"); using namespace net; @@ -82,7 +102,6 @@ void DistantUniverse::pullNetwork() { } else { areas.emplace(id, std::make_shared(p)); } - LOG_D("Area " << id.index); } break; } diff --git a/src/client/world/DistantUniverse.hpp b/src/client/world/DistantUniverse.hpp index c18fc7b..761a518 100644 --- a/src/client/world/DistantUniverse.hpp +++ b/src/client/world/DistantUniverse.hpp @@ -19,7 +19,7 @@ namespace world::client { ray_result raycast(const geometry::Ray &) const override; protected: - void pullNetwork(); + void pullNetwork(voxel_pos); /// Alive areas containing chunks area_map areas; diff --git a/src/client/world/index.cpp b/src/client/world/index.cpp index 5ac7d17..f6629f3 100644 --- a/src/client/world/index.cpp +++ b/src/client/world/index.cpp @@ -1,5 +1,7 @@ #include "index.hpp" +#ifndef STANDALONE #include "LocalUniverse.hpp" +#endif #include "DistantUniverse.hpp" #include "../../core/utils/logger.hpp" @@ -7,12 +9,12 @@ namespace world::client { std::unique_ptr Load(const std::optional& ct, server_handle *const localHandle, const Universe::options &distOpts) { if(ct.has_value()) { return std::make_unique(ct.value(), distOpts); +#ifndef STANDALONE + } else if(localHandle != nullptr) { + return std::make_unique(localHandle); +#endif } else { - if(localHandle != nullptr) { - return std::make_unique(localHandle); - } else { - FATAL("Must enable server.allow_local or define client.connection"); - } + FATAL("Must enable server.allow_local or define client.connection"); } } } \ No newline at end of file diff --git a/src/core/config.hpp b/src/core/config.hpp index 3aee085..e9636e8 100644 --- a/src/core/config.hpp +++ b/src/core/config.hpp @@ -4,16 +4,16 @@ #include #include #include -#include "../client/config.hpp" -#include "../server/config.hpp" namespace config { +constexpr auto DEFAULT_FILE = "config.toml"; + /// Savable game options struct options { public: /// Load from path - options(const std::string &path = "config.toml"): path(path) { + options(const std::string &path): path(path) { auto config = [&] { if(std::filesystem::exists(path)) return toml::parse_file(path); @@ -51,4 +51,5 @@ private: std::optional _server; std::optional _client; }; + } \ No newline at end of file diff --git a/src/core/data/toml.cpp b/src/core/data/toml.cpp new file mode 100644 index 0000000..199bd2f --- /dev/null +++ b/src/core/data/toml.cpp @@ -0,0 +1,2 @@ +#define TOML_HEADER_ONLY 0 +#include \ No newline at end of file diff --git a/src/core/net/Client.hpp b/src/core/net/Client.hpp index c9ba218..d118e49 100644 --- a/src/core/net/Client.hpp +++ b/src/core/net/Client.hpp @@ -123,6 +123,7 @@ public: } constexpr bool isReady() const { return ready; } + constexpr salt_t getSalt() const { return salt; } protected: ENetHost *host; diff --git a/src/core/net/data.hpp b/src/core/net/data.hpp index dd32c35..e6aa352 100644 --- a/src/core/net/data.hpp +++ b/src/core/net/data.hpp @@ -50,6 +50,10 @@ enum class client_packet_type: enet_uint8 { /// actions::FillCube realable FILL_CUBE = 0, + /// Request missing chunks + /// area_id, chunk_pos[] realable + MISSING_CHUNKS = 8, + /// Position update /// voxel_pos notify MOVE = 16, diff --git a/src/core/standalone_config.hpp b/src/core/standalone_config.hpp new file mode 100644 index 0000000..29eb48f --- /dev/null +++ b/src/core/standalone_config.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include +#include + +namespace config { + +constexpr auto DEFAULT_FILE = "config.toml"; + +/// Standalone options +template +struct standalone_options { +public: + /// Load from path + standalone_options(const std::string &path): path(path) { + auto config = toml::table({{"c", [&] { + if(std::filesystem::exists(path)) + return toml::parse_file(path); + + LOG_E("Config file " << path << " not found. Creating default"); + return toml::table(); + }()}}); + val = new O(config["c"]); + } + ~standalone_options() { + delete val; + } + /// Write to path + void save() { + std::ofstream out; + out.open(path, std::ios::out | std::ios::trunc); + out << val->save() << "\n\n"; + out.close(); + } + + O &get() { return *val; } + +private: + std::string path; + O* val; +}; +} \ No newline at end of file diff --git a/src/core/utils/tracy.hpp b/src/core/utils/tracy.hpp new file mode 100644 index 0000000..79ebdfc --- /dev/null +++ b/src/core/utils/tracy.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +#if TRACY_MEMORY +void *operator new(std::size_t count) +{ + auto ptr = malloc(count); + TracyAlloc(ptr, count); + return ptr; +} +void operator delete(void *ptr) noexcept +{ + TracyFree(ptr); + free(ptr); +} +#endif diff --git a/src/core/world/Universe.cpp b/src/core/world/Universe.cpp index 3f10d9c..d5f56ba 100644 --- a/src/core/world/Universe.cpp +++ b/src/core/world/Universe.cpp @@ -26,5 +26,5 @@ bool Universe::collide(const glm::ifvec3 &pos, const glm::vec3 &vel, int density const auto dir = glm::normalize(vel); const auto velocity = vel * glm::vec3(density); const auto from = pos * density + dir; - return std::holds_alternative(raycast(Ray(from, dir, glm::length(velocity) + radius))); + return !std::holds_alternative(raycast(Ray(from, dir, glm::length(velocity) + radius))); } \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index fdb19de..5b3c2f1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,22 +10,7 @@ #include "client/Client.hpp" #include "server/Server.hpp" #include "core/config.hpp" -#include "core/net/data.hpp" -#include - -#if TRACY_MEMORY -void *operator new(std::size_t count) -{ - auto ptr = malloc(count); - TracyAlloc(ptr, count); - return ptr; -} -void operator delete(void *ptr) noexcept -{ - TracyFree(ptr); - free(ptr); -} -#endif +#include "core/utils/tracy.hpp" /// Entry point int main(int argc, char *argv[]){ @@ -35,7 +20,7 @@ int main(int argc, char *argv[]){ LOG("Profiling !"); #endif - config::options options = config::options(argc > 1 ? argv[1] : "config.toml"); + auto options = config::options(argc > 1 ? argv[1] : config::DEFAULT_FILE); options.save(); std::optional server = options.hasServer() ? std::make_optional(options.getServer()) : std::nullopt; @@ -69,7 +54,6 @@ int main(int argc, char *argv[]){ } } else { if (client.has_value()) { - //MAYBE: check not local clientTask(nullptr); } else { options.save(); diff --git a/src/server.cpp b/src/server.cpp new file mode 100644 index 0000000..f2debb2 --- /dev/null +++ b/src/server.cpp @@ -0,0 +1,40 @@ +/** + * \file server.cpp + * \brief Univerxel server + * \author Maelys Bois + * \version 0.0.1 + * + * Univerxel standalone server program. + */ + +#define STANDALONE 1 +#include "server/Server.hpp" +#include "core/standalone_config.hpp" +#include "core/utils/tracy.hpp" + +/// Entry point +int main(int argc, char *argv[]){ + LOG("Univerxel server"); + +#if TRACY_ENABLE + LOG("Profiling !"); +#endif + + auto options = config::standalone_options(argc > 1 ? argv[1] : config::DEFAULT_FILE); + options.save(); + +#if TRACY_ENABLE + tracy::SetThreadName("Main"); +#endif + + net::Setup(); + + auto server = Server(options.get()); + server.run(); + + net::Destroy(); + + options.save(); + + return 0; +} \ No newline at end of file diff --git a/src/server/Server.cpp b/src/server/Server.cpp index d95e8b7..fba5016 100644 --- a/src/server/Server.cpp +++ b/src/server/Server.cpp @@ -1,6 +1,8 @@ #include "Server.hpp" #include "world/StandaloneUniverse.hpp" +#ifndef STANDALONE #include "world/SharedUniverse.hpp" +#endif #include Server::Server(config::server::options& options): options(options) { @@ -16,8 +18,10 @@ void handle_signal(int) { running = false; } void Server::run() { universe = [&]() -> std::unique_ptr { +#ifndef STANDALONE if(options.allowLocal) return std::make_unique(options.world, localHandle); +#endif return std::make_unique(options.world); }(); @@ -27,6 +31,7 @@ void Server::run() { while(running && (localHandle == nullptr || localHandle->running)) { universe->update(1. / TPS); //FIXME: use chrono + FrameMarkNamed("Server"); std::this_thread::sleep_for(std::chrono::milliseconds(1000 / TPS)); } } \ No newline at end of file diff --git a/src/server/config.hpp b/src/server/config.hpp index 33f14e5..c9ea5bc 100644 --- a/src/server/config.hpp +++ b/src/server/config.hpp @@ -7,9 +7,17 @@ namespace config::server { struct options { public: - options(toml::node_view config) { + options(toml::node_view config): world() { assert(config["enabled"]); +#ifndef STANDALONE allowLocal = config["allow_local"].value_or(allowLocal); +#else + allowLocal = false; +#endif + + world.connection.address = config["connection"]["address"].value_or(world.connection.address); + world.connection.port = config["connection"]["port"].value_or(world.connection.port); + world.maxPlayers = config["max_players"].value_or(world.maxPlayers); world.loadDistance = config["world"]["load_distance"].value_or(world.loadDistance); world.keepDistance = config["world"]["keep_distance"].value_or(world.keepDistance); @@ -19,7 +27,14 @@ public: toml::table save() { return toml::table({ {"enabled", true}, +#ifndef STANDALONE {"allow_local", allowLocal}, +#endif + {"connection", toml::table({ + {"address", world.connection.address}, + {"port", world.connection.port} + })}, + {"max_players", world.maxPlayers}, {"world", toml::table({ {"load_distance", world.loadDistance}, {"keep_distance", world.keepDistance}, diff --git a/src/server/world/Universe.cpp b/src/server/world/Universe.cpp index 1516637..9a86583 100644 --- a/src/server/world/Universe.cpp +++ b/src/server/world/Universe.cpp @@ -14,7 +14,7 @@ using namespace world::server; const auto AREAS_FILE = "/areas.idx"; -Universe::Universe(const Universe::options &options): host(net::connection{"localhost", 4242}, 4), +Universe::Universe(const Universe::options &options): host(options.connection, options.maxPlayers), dict_content({options.folderPath + "/zstd.dict", "content/zstd.dict"}), dicts(dict_content), dict_write_ctx(dicts.make_writer()) { setOptions(options); folderPath = options.folderPath; @@ -314,7 +314,8 @@ void Universe::update(float deltaTime) { it->second->setChunks().emplace(loaded.first.second, loaded.second); const chunk_pos diff = glm::divide(pos - it->second->getOffset().as_voxel()); loadChunk(loaded.first, diff, it->second->getChunks()); - broadcastChunk(loaded); + // MAYBE: limit chunks per update + host.broadcast(serializeChunk(loaded), net::channel_type::RELIABLE); } } } @@ -375,6 +376,29 @@ void Universe::pullNetwork() { } break; } + case client_packet_type::MISSING_CHUNKS: { + const auto pos = entities.at(PLAYER_ENTITY_ID).instances.at(Server::GetPeerData(peer)->instanceId).pos.as_voxel(); + + auto reader = PacketReader(packet); + area_id id = *reader.read(); + if(auto area = areas.find(id); area != areas.end()) { + auto &chunks = area->second->getChunks(); + const chunk_pos diff = glm::divide(pos - area->second->getOffset().as_voxel()); + while(!reader.isFull()) { + chunk_pos cpos = *reader.read(); + if(glm::length2(diff - cpos) <= glm::pow2(loadDistance) && chunks.inRange(cpos)) { + if(auto chunk = chunks.find(cpos); chunk != chunks.end()) { + host.send(peer, serializeChunk({std::make_pair(id, cpos), std::dynamic_pointer_cast(chunk->second)}), net::channel_type::RELIABLE); + } + } else { + LOG_D("Request out of range chunk"); + } + } + } else { + LOG_D("Bad chunk request"); + } + break; + } default: LOG_D("Bad packet from " << peer->address); break; @@ -394,8 +418,7 @@ void Universe::broadcastAreas() { assert(packet.isFull()); host.broadcast(packet.get(), net::channel_type::RELIABLE); } -void Universe::broadcastChunk(const robin_hood::pair, std::shared_ptr> &pair) { - // MAYBE: limit chunks per update +net::packet_t* Universe::serializeChunk(const robin_hood::pair, std::shared_ptr> &pair) { std::ostringstream out; pair.second->write(out); std::vector buffer; @@ -404,7 +427,7 @@ void Universe::broadcastChunk(const robin_hood::pair, std::shar packet.write(pair.first); packet.write(buffer.data(), buffer.size()); assert(packet.isFull()); - host.broadcast(packet.get(), net::channel_type::RELIABLE); + return packet.get(); } void Universe::updateChunk(area_map::iterator &, world::ChunkContainer::iterator &, chunk_pos, float deltaTime) {} diff --git a/src/server/world/Universe.hpp b/src/server/world/Universe.hpp index 67e3d7a..cc7966f 100644 --- a/src/server/world/Universe.hpp +++ b/src/server/world/Universe.hpp @@ -26,6 +26,9 @@ namespace world::server { struct options: world::Universe::options { /// Storage path std::string folderPath = "world"; + + net::connection connection = net::connection{"localhost", 4242}; + int maxPlayers = 1; }; Universe(const options &); @@ -64,7 +67,7 @@ namespace world::server { /// Handle networking requests void pullNetwork(); void broadcastAreas(); - void broadcastChunk(const robin_hood::pair, std::shared_ptr> &); + net::packet_t* serializeChunk(const robin_hood::pair, std::shared_ptr> &); using area_map = robin_hood::unordered_map>;