diff --git a/src/client/Client.cpp b/src/client/Client.cpp index 03509db..396c44f 100644 --- a/src/client/Client.cpp +++ b/src/client/Client.cpp @@ -13,12 +13,9 @@ Client::Client(config::client::options& options): options(options) { } Client::~Client() { } void Client::run(server_handle* const localHandle) { - if (!render::Load(window, options.preferVulkan, options.renderer, options.window.getSamples())) + if (!render::Load(window, options.preferVulkan, options.renderer, options.window)) return; - window.setTargetFPS(options.window.targetFPS); - window.setFullscreen(options.window.fullscreen); - InputMap inputs(window.getPtr()); Controllable player(window.getPtr(), inputs, options.control); Camera camera(&player, options.camera); @@ -91,6 +88,7 @@ void Client::run(server_handle* const localHandle) { const auto actions = render::UI::Get()->draw(options, state, reports); if (actions && render::UI::Actions::FPS) { window.setTargetFPS(options.window.targetFPS); + pipeline->setVSync(options.window.targetFPS < Window::MIN_FPS); } if (actions && render::UI::Actions::FullScreen) { window.setFullscreen(options.window.fullscreen); diff --git a/src/client/Window.cpp b/src/client/Window.cpp index 0f561a1..2bf72c3 100644 --- a/src/client/Window.cpp +++ b/src/client/Window.cpp @@ -81,6 +81,9 @@ bool Window::create(const CreateInfo &opt) { glfwSetWindowTitle(ptr, APP_NAME); glfwSetWindowAttrib(ptr, GLFW_RESIZABLE, true); + setTargetFPS(opt.fps); + setFullscreen(opt.fullscreen); + return true; } @@ -88,7 +91,6 @@ bool Window::isReady() const { return ptr != nullptr; } void Window::setTargetFPS(int val) { targetFPS = val; - glfwSwapInterval(static_cast(val < MIN_FPS)); } double Window::getTime() const { diff --git a/src/client/Window.hpp b/src/client/Window.hpp index cbea211..3846468 100644 --- a/src/client/Window.hpp +++ b/src/client/Window.hpp @@ -6,6 +6,13 @@ typedef struct GLFWwindow GLFWwindow; typedef void (*GLFWframebuffersizefun)(GLFWwindow*, int, int); +struct windowOptions { + int targetFPS = 60; + int sampling = -1; + bool fullscreen = false; + + constexpr int getSamples() const { return sampling > 0 ? (1 << (sampling - 1)) : sampling; } +}; /// GLFW context and window class Window { @@ -29,6 +36,8 @@ public: int minor; } client; int samples; + int fps; + bool fullscreen; }; bool create(const CreateInfo &opt); void destroy(); diff --git a/src/client/config.hpp b/src/client/config.hpp index 6fd784c..4e4aa6c 100644 --- a/src/client/config.hpp +++ b/src/client/config.hpp @@ -8,6 +8,7 @@ #include "render/Renderer.hpp" #include "contouring/Abstract.hpp" #include "control/Camera.hpp" +#include "Window.hpp" namespace config::client { @@ -179,13 +180,7 @@ public: bool controls = false; } debugMenu; - struct { - int targetFPS = 60; - int sampling = -1; - bool fullscreen = false; - - constexpr int getSamples() const { return sampling > 0 ? (1 << (sampling - 1)) : sampling; } - } window; + windowOptions window; bool preferVulkan = true; render::renderOptions renderer; diff --git a/src/client/render/Renderer.hpp b/src/client/render/Renderer.hpp index ffc98b1..8fd5146 100644 --- a/src/client/render/Renderer.hpp +++ b/src/client/render/Renderer.hpp @@ -87,6 +87,7 @@ public: virtual void reloadShaders(const passOptions &) = 0; virtual void reloadTextures(const std::string &, float mipMapLOD, float anisotropy) = 0; virtual void setFillMode(bool wireframe) = 0; + virtual void setVSync(bool vSync) = 0; virtual void loadUI(Window&) = 0; diff --git a/src/client/render/UI.cpp b/src/client/render/UI.cpp index b89e277..18674f5 100644 --- a/src/client/render/UI.cpp +++ b/src/client/render/UI.cpp @@ -4,6 +4,7 @@ #include "../state.hpp" #include "../Window.hpp" #include "../../core/world/materials.hpp" +#include using namespace render; @@ -16,6 +17,11 @@ UI::UI() { IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGui::StyleColorsDark(); + + for(auto file: std::filesystem::directory_iterator("content/textures/")) { + if(file.is_directory() && file.path().filename() != "ui") + texturePacks.push_back(file.path().filename()); + } } UI::~UI() { ImGui::DestroyContext(); @@ -115,7 +121,18 @@ UI::Actions UI::draw(config::client::options &options, state::state &state, cons if (ImGui::Checkbox("Wireframe", &options.renderer.wireframe)) { actions |= Actions::FillMode; } - ImGui::Text("Textures '%s'", options.renderer.textures.c_str()); // MAYBE: select + if (ImGui::BeginCombo("Textures", options.renderer.textures.c_str())) { + for (auto& pack: texturePacks) { + const bool is_selected = (pack == options.renderer.textures); + if (ImGui::Selectable(pack.c_str(), is_selected)) { + options.renderer.textures = pack; + actions |= Actions::RendererTextures; + } + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } std::string anisotropy = std::to_string(options.renderer.getAnisotropy()) + "x"; if (ImGui::SliderInt("Quality", &options.renderer.textureQuality, 0, 200, "%d%%") | ImGui::SliderInt("Sharpness", &options.renderer.textureSharpness, 0, 8, anisotropy.c_str())) { diff --git a/src/client/render/UI.hpp b/src/client/render/UI.hpp index a959656..bccba56 100644 --- a/src/client/render/UI.hpp +++ b/src/client/render/UI.hpp @@ -2,6 +2,8 @@ #include #include +#include +#include #include "../../core/flags.hpp" namespace config::client { struct options; } @@ -17,6 +19,8 @@ namespace render { class UI { protected: UI(); + + std::vector texturePacks; public: virtual ~UI(); @@ -56,7 +60,7 @@ public: static void Unload(); protected: - static Actions draw(config::client::options&, state::state &, const state::reports &, intptr_t aim); + Actions draw(config::client::options&, state::state &, const state::reports &, intptr_t aim); static UI* sInstance; }; diff --git a/src/client/render/gl/Renderer.cpp b/src/client/render/gl/Renderer.cpp index 7a81d29..5737d51 100644 --- a/src/client/render/gl/Renderer.cpp +++ b/src/client/render/gl/Renderer.cpp @@ -42,11 +42,14 @@ void framebuffer_size_callback(GLFWwindow *, int width, int height) { glViewport(0, 0, width, height); } -bool Renderer::Load(Window& window, const renderOptions& opt, int samples) { +bool Renderer::Load(Window& window, const renderOptions& opt, const windowOptions& windOpt) { Window::CreateInfo windowInfo; windowInfo.pfnResize = framebuffer_size_callback; windowInfo.client = {Window::CreateInfo::Client::Type::GL, GL_MAJOR, GL_MINOR}; - windowInfo.samples = samples; + windowInfo.samples = windOpt.getSamples(); + windowInfo.fps = windOpt.targetFPS; + windowInfo.fullscreen = windOpt.fullscreen; + if (!window.create(windowInfo)) return false; @@ -80,6 +83,7 @@ bool Renderer::Load(Window& window, const renderOptions& opt, int samples) { TracyGpuContext; sInstance = new Renderer(opt); + sInstance->setVSync(windOpt.targetFPS < Window::MIN_FPS); LodModel::MakeDefault(); return true; } @@ -178,3 +182,7 @@ void Renderer::setClearColor(glm::vec4 c) { void Renderer::setFillMode(bool wireframe) { glPolygonMode(GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL); } + +void Renderer::setVSync(bool vSync) { + glfwSwapInterval(static_cast(vSync)); +} \ No newline at end of file diff --git a/src/client/render/gl/Renderer.hpp b/src/client/render/gl/Renderer.hpp index b360554..a2159f2 100644 --- a/src/client/render/gl/Renderer.hpp +++ b/src/client/render/gl/Renderer.hpp @@ -9,6 +9,7 @@ #include "api/Models.hpp" #include "api/Images.hpp" +struct windowOptions; namespace render::gl { /// OpenGL rendering @@ -16,7 +17,7 @@ class Renderer final: public render::Renderer { public: virtual ~Renderer(); - static bool Load(Window& window, const renderOptions& options, int samples); + static bool Load(Window& window, const renderOptions& options, const windowOptions& windOpt); glm::vec3 FogColor; GLfloat FogDepth; @@ -56,6 +57,7 @@ public: void reloadShaders(const pass::VoxelProgram::options &) override; void reloadTextures(const std::string &, float mipMapLOD, float anisotropy) override; void setFillMode(bool wireframe) override; + void setVSync(bool vSync) override; void loadUI(Window &) override; diff --git a/src/client/render/index.cpp b/src/client/render/index.cpp index 10d6af7..2dd18fb 100644 --- a/src/client/render/index.cpp +++ b/src/client/render/index.cpp @@ -5,20 +5,20 @@ namespace render { -bool Load(Window& window, bool preferVulkan, const renderOptions& options, int samples) { +bool Load(Window& window, bool preferVulkan, const renderOptions& options, const windowOptions& windOpt) { if(!preferVulkan) { LOG_T("Trying OpenGL"); - if(gl::Renderer::Load(window, options, samples)) + if(gl::Renderer::Load(window, options, windOpt)) return true; window.destroy(); } LOG_T("Trying Vulkan"); - if(vk::Renderer::Load(window, options, samples)) + if(vk::Renderer::Load(window, options, windOpt)) return true; window.destroy(); if(preferVulkan) { LOG_I("Fallback to OpenGL"); - if(gl::Renderer::Load(window, options, samples)) + if(gl::Renderer::Load(window, options, windOpt)) return true; } LOG_E("No available graphics library"); diff --git a/src/client/render/index.hpp b/src/client/render/index.hpp index 21920ce..f5266d4 100644 --- a/src/client/render/index.hpp +++ b/src/client/render/index.hpp @@ -1,8 +1,9 @@ #pragma once class Window; +struct windowOptions; namespace render { struct renderOptions; -bool Load(Window& window, bool preferVulkan, const renderOptions& options, int samples); +bool Load(Window& window, bool preferVulkan, const renderOptions& options, const windowOptions& windOpt); } \ No newline at end of file diff --git a/src/client/render/vk/CommandCenter.cpp b/src/client/render/vk/CommandCenter.cpp index b826d18..65fa207 100644 --- a/src/client/render/vk/CommandCenter.cpp +++ b/src/client/render/vk/CommandCenter.cpp @@ -141,30 +141,18 @@ void CommandCenter::allocate(const std::vector& views, const Pipeli { // Descriptor pools std::array poolSizes{}; poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - poolSizes[0].descriptorCount = framebuffers.size(); + poolSizes[0].descriptorCount = framebuffers.size() * 3; poolSizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - poolSizes[1].descriptorCount = framebuffers.size() * 3; + poolSizes[1].descriptorCount = framebuffers.size() * 4; VkDescriptorPoolCreateInfo poolInfo{}; poolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; poolInfo.poolSizeCount = poolSizes.size(); poolInfo.pPoolSizes = poolSizes.data(); - poolInfo.maxSets = framebuffers.size(); + poolInfo.maxSets = framebuffers.size() * 3; poolInfo.flags = 0; //VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT - if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &voxelDescriptorPool) != VK_SUCCESS) { - FATAL("Failed to create descriptor pool!"); - } - - poolSizes[1].descriptorCount = framebuffers.size(); - - if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &skyDescriptorPool) != VK_SUCCESS) { - FATAL("Failed to create descriptor pool!"); - } - - poolInfo.poolSizeCount = 1; - - if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &indicDescriptorPool) != VK_SUCCESS) { + if (vkCreateDescriptorPool(device, &poolInfo, nullptr, &descriptorPool) != VK_SUCCESS) { FATAL("Failed to create descriptor pool!"); } } @@ -172,10 +160,10 @@ void CommandCenter::allocate(const std::vector& views, const Pipeli VkDescriptorSetAllocateInfo allocInfo{}; allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; allocInfo.descriptorSetCount = framebuffers.size(); - - auto allocSets = [&](VkDescriptorPool pool, VkDescriptorSetLayout layout, std::vector& out) { + + auto allocSets = [&](VkDescriptorSetLayout layout, std::vector& out) { std::vector layouts(framebuffers.size(), layout); - allocInfo.descriptorPool = pool; + allocInfo.descriptorPool = descriptorPool; allocInfo.pSetLayouts = layouts.data(); out.resize(framebuffers.size()); @@ -183,9 +171,9 @@ void CommandCenter::allocate(const std::vector& views, const Pipeli FATAL("Failed to allocate descriptor sets!"); } }; - allocSets(voxelDescriptorPool, pipe.getVoxelDescriptorSet(), voxelDescriptorSets); - allocSets(indicDescriptorPool, pipe.getIndicDescriptorSet(), indicDescriptorSets); - allocSets(skyDescriptorPool, pipe.getSkyDescriptorSet(), skyDescriptorSets); + allocSets(pipe.getVoxelDescriptorSet(), voxelDescriptorSets); + allocSets(pipe.getIndicDescriptorSet(), indicDescriptorSets); + allocSets(pipe.getSkyDescriptorSet(), skyDescriptorSets); for (size_t i = 0; i < voxelDescriptorSets.size(); i++) { VkDescriptorBufferInfo bufferInfo{}; @@ -260,9 +248,7 @@ void CommandCenter::free() { TracyVkDestroy(tracyCtx); vkFreeCommandBuffers(device, graphicsPool, static_cast(graphicsBuffers.size()), graphicsBuffers.data()); - vkDestroyDescriptorPool(device, voxelDescriptorPool, ALLOC); - vkDestroyDescriptorPool(device, indicDescriptorPool, ALLOC); - vkDestroyDescriptorPool(device, skyDescriptorPool, ALLOC); + vkDestroyDescriptorPool(device, descriptorPool, ALLOC); colorbuffer.reset(); depthbuffer.reset(); diff --git a/src/client/render/vk/CommandCenter.hpp b/src/client/render/vk/CommandCenter.hpp index 43aca23..752ef7b 100644 --- a/src/client/render/vk/CommandCenter.hpp +++ b/src/client/render/vk/CommandCenter.hpp @@ -57,17 +57,16 @@ private: BufferGroup uniformBuffers; - VkDescriptorPool voxelDescriptorPool; + VkDescriptorPool descriptorPool; + std::vector voxelDescriptorSets; std::unique_ptr voxelTextureAtlas; std::unique_ptr voxelNormalAtlas; std::unique_ptr voxelHOSAtlas; - VkDescriptorPool indicDescriptorPool; std::vector indicDescriptorSets; std::unique_ptr indicCubeBuffer; - VkDescriptorPool skyDescriptorPool; std::vector skyDescriptorSets; std::unique_ptr skyboxTexture; std::unique_ptr skyCubeBuffer; diff --git a/src/client/render/vk/PhysicalDeviceInfo.cpp b/src/client/render/vk/PhysicalDeviceInfo.cpp index ad46911..612e776 100644 --- a/src/client/render/vk/PhysicalDeviceInfo.cpp +++ b/src/client/render/vk/PhysicalDeviceInfo.cpp @@ -81,7 +81,7 @@ std::optional PhysicalDeviceInfo::findSupportedFormat(const std::vecto } VkFormat PhysicalDeviceInfo::findDepthFormat() const { if (auto res = findSupportedFormat( - {VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT}, + {VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_D32_SFLOAT_S8_UINT}, VK_IMAGE_TILING_OPTIMAL, VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)) return res.value(); diff --git a/src/client/render/vk/PhysicalDeviceInfo.hpp b/src/client/render/vk/PhysicalDeviceInfo.hpp index a7ea5d9..39c6bcd 100644 --- a/src/client/render/vk/PhysicalDeviceInfo.hpp +++ b/src/client/render/vk/PhysicalDeviceInfo.hpp @@ -24,20 +24,21 @@ struct QueueFamilyIndices { }; struct PhysicalDeviceInfo { PhysicalDeviceInfo() {} - PhysicalDeviceInfo(GLFWwindow *window, VkPhysicalDevice device, VkSurfaceKHR surface, int targetSamples): + PhysicalDeviceInfo(GLFWwindow *window, VkPhysicalDevice device, VkSurfaceKHR surface, int targetSamples, bool vSync): window(window), device(device), surface(surface), - swapDetails(SwapChainSupportDetails::Query(device, surface)), queueIndices(QueueFamilyIndices::Query(device, surface)) + swapDetails(SwapChainSupportDetails::Query(device, surface)), queueIndices(QueueFamilyIndices::Query(device, surface)), + vSync(vSync) { vkGetPhysicalDeviceProperties(device, &properties); vkGetPhysicalDeviceFeatures(device, &features); samples = [&] { - if (targetSamples < 0) - targetSamples = 4; VkSampleCountFlags counts = properties.limits.framebufferColorSampleCounts & properties.limits.framebufferDepthSampleCounts; //MAYBE: properties.limits.framebufferStencilSampleCounts + if (targetSamples < 0) + targetSamples = counts / 4; for (auto sample: {VK_SAMPLE_COUNT_64_BIT, VK_SAMPLE_COUNT_32_BIT, VK_SAMPLE_COUNT_16_BIT, - VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_2_BIT + VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_2_BIT }) { if (targetSamples >= sample && (counts & sample)) return sample; @@ -64,5 +65,7 @@ struct PhysicalDeviceInfo { VkPhysicalDeviceProperties properties; VkPhysicalDeviceFeatures features; std::vector optionalExtensions; + bool vSync; + bool tripleBuffering = true; }; } \ No newline at end of file diff --git a/src/client/render/vk/Pipeline.cpp b/src/client/render/vk/Pipeline.cpp index 7918096..0ad3c45 100644 --- a/src/client/render/vk/Pipeline.cpp +++ b/src/client/render/vk/Pipeline.cpp @@ -8,7 +8,7 @@ #define CONTENT_DIR "content/" #define SHADER_DIR CONTENT_DIR "shaders/" -constexpr auto BLENDING = true; +constexpr auto BLENDING = false; using namespace render::vk; diff --git a/src/client/render/vk/Renderer.cpp b/src/client/render/vk/Renderer.cpp index 60e1ed5..5df2f83 100644 --- a/src/client/render/vk/Renderer.cpp +++ b/src/client/render/vk/Renderer.cpp @@ -163,11 +163,14 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugValidationCallback(VkDebugUtilsMessageSeveri return VK_FALSE; } -bool Renderer::Load(Window& window, const renderOptions& opt, int samples) { +bool Renderer::Load(Window& window, const renderOptions& opt, const windowOptions& windOpt) { Window::CreateInfo windowInfo; windowInfo.pfnResize = on_resize_callback; windowInfo.client = {Window::CreateInfo::Client::Type::VK, 0, 0}; windowInfo.samples = -1; + windowInfo.fps = windOpt.targetFPS; + windowInfo.fullscreen = windOpt.fullscreen; + if (!window.create(windowInfo)) return false; @@ -297,7 +300,7 @@ bool Renderer::Load(Window& window, const renderOptions& opt, int samples) { uint bestScore = 0; for(const auto& device: devices) { uint score = 1; - auto infos = PhysicalDeviceInfo(window.getPtr(), device, surface, samples); + auto infos = PhysicalDeviceInfo(window.getPtr(), device, surface, windOpt.getSamples(), windOpt.targetFPS < Window::MIN_FPS); { uint32_t availableExtensionsCount; @@ -521,6 +524,12 @@ void Renderer::setFillMode(bool wireframe) { options.wireframe = wireframe; recreateSwapChain(); } +void Renderer::setVSync(bool vSync) { + if (vSync != getInfos().vSync) { + physicalInfo->vSync = vSync; + recreateSwapChain(); + } +} void Renderer::lookFrom(const Camera& camera) { ProjectionMatrix = camera.getProjectionMatrix(); diff --git a/src/client/render/vk/Renderer.hpp b/src/client/render/vk/Renderer.hpp index 3af8d7f..e654445 100644 --- a/src/client/render/vk/Renderer.hpp +++ b/src/client/render/vk/Renderer.hpp @@ -2,6 +2,7 @@ #include "../Renderer.hpp" #include "forward.hpp" +struct windowOptions; namespace render::vk { class Allocator; class SwapChain; @@ -13,7 +14,7 @@ class Renderer final: public render::Renderer { public: virtual ~Renderer(); - static bool Load(Window& window, const renderOptions& options, int samples); + static bool Load(Window& window, const renderOptions& options, const windowOptions& windOpt); void loadUI(Window &) override; @@ -35,6 +36,7 @@ public: void reloadShaders(const passOptions &) override; void reloadTextures(const std::string &, float mipMapLOD, float anisotropy) override; void setFillMode(bool wireframe) override; + void setVSync(bool vSync) override; Allocator* getAllocator() const { return allocator.get(); } struct UICtx { diff --git a/src/client/render/vk/SwapChain.cpp b/src/client/render/vk/SwapChain.cpp index 0748295..6ac2922 100644 --- a/src/client/render/vk/SwapChain.cpp +++ b/src/client/render/vk/SwapChain.cpp @@ -8,13 +8,20 @@ SwapChain::SwapChain(VkDevice device, const PhysicalDeviceInfo& info): device(de vkGetDeviceQueue(device, info.queueIndices.presentFamily.value(), 0, &presentQueue); { // Swapchain VkPresentModeKHR presentMode = [&]() { - // MAYBE: add prefer no triple buffering options - for (const auto& availablePresentMode: info.swapDetails.presentModes) { - if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) { - return availablePresentMode; + std::vector preferredModes; + if (info.vSync) { + preferredModes.push_back(VK_PRESENT_MODE_FIFO_RELAXED_KHR); + } else { + if (info.tripleBuffering) + preferredModes.push_back(VK_PRESENT_MODE_MAILBOX_KHR); + preferredModes.push_back(VK_PRESENT_MODE_IMMEDIATE_KHR); + } + for(auto mode: preferredModes) { + for (const auto& availablePresentMode: info.swapDetails.presentModes) { + if (availablePresentMode == mode) + return availablePresentMode; } } - return VK_PRESENT_MODE_FIFO_KHR; }(); diff --git a/src/server/world/SharedUniverse.cpp b/src/server/world/SharedUniverse.cpp index 05b4e00..d5b0f2a 100644 --- a/src/server/world/SharedUniverse.cpp +++ b/src/server/world/SharedUniverse.cpp @@ -9,7 +9,7 @@ SharedUniverse::SharedUniverse(const options &o, server_handle *const localHandl const auto id = entities.at(PLAYER_ENTITY_ID).instances.emplace(Entity::Instance{}); assert(id == PLAYER_ENTITY_ID); - localHandle->areas = (world::client::area_map*)(&areas); //FIXME: templated area + localHandle->areas = (world::client::area_map*)(&areas); //WONT FIX: templated area localHandle->emit = std::function([&](const world::action::packet &packet) { if(const auto fill = std::get_if(&packet)) { this->set(fill->pos, fill->val); diff --git a/src/server/world/SharedUniverse.hpp b/src/server/world/SharedUniverse.hpp index 62904b9..26cd313 100644 --- a/src/server/world/SharedUniverse.hpp +++ b/src/server/world/SharedUniverse.hpp @@ -9,9 +9,6 @@ namespace world::server { /// Server with data for LocalClientUniverse binding class SharedUniverse final: public Universe { public: - //TODO: override area type - //TODO: update edits - SharedUniverse(const options &, server_handle *const); virtual ~SharedUniverse();