diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.EtrediaEmpires.dir/.idea/.gitignore b/.idea/.idea.EtrediaEmpires.dir/.idea/.gitignore new file mode 100644 index 0000000..d505038 --- /dev/null +++ b/.idea/.idea.EtrediaEmpires.dir/.idea/.gitignore @@ -0,0 +1,13 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/modules.xml +/.idea.EtrediaEmpires.iml +/contentModel.xml +/projectSettingsUpdater.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.idea.EtrediaEmpires.dir/.idea/encodings.xml b/.idea/.idea.EtrediaEmpires.dir/.idea/encodings.xml new file mode 100644 index 0000000..df87cf9 --- /dev/null +++ b/.idea/.idea.EtrediaEmpires.dir/.idea/encodings.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/.idea.EtrediaEmpires.dir/.idea/indexLayout.xml b/.idea/.idea.EtrediaEmpires.dir/.idea/indexLayout.xml new file mode 100644 index 0000000..7b08163 --- /dev/null +++ b/.idea/.idea.EtrediaEmpires.dir/.idea/indexLayout.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/.idea.EtrediaEmpires.dir/.idea/vcs.xml b/.idea/.idea.EtrediaEmpires.dir/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/.idea.EtrediaEmpires.dir/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/EtrediaEmpires.iml b/.idea/EtrediaEmpires.iml new file mode 100644 index 0000000..f08604b --- /dev/null +++ b/.idea/EtrediaEmpires.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..bbce9cb --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,11 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..0b76fe5 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..a443a4a --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 713f9b4..dc80d29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,20 +1,25 @@ -cmake_minimum_required (VERSION 3.8) +cmake_minimum_required (VERSION 4.2.3) + +set(CMAKE_CXX_STANDARD 23) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_SCAN_FOR_MODULES ON) +set(CMAKE_POSITION_INDEPENDENT_CODE OFF) + +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) if (POLICY CMP0141) cmake_policy(SET CMP0141 NEW) set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") endif() -set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -project (EtrediaEmpires) +project (EtrediaEmpires LANGUAGES CXX) add_subdirectory(sdk/map) add_subdirectory(sdk/assets) -add_subdirectory(utils) add_subdirectory(p7lib) -add_subdirectory(server) +add_subdirectory(utils) +add_subdirectory(server/lib) add_subdirectory(engine-api) add_subdirectory(renderers/magnum-renderer) add_subdirectory(engine) \ No newline at end of file diff --git a/CMakePresets.json b/CMakePresets.json index ba02f36..b38212e 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -8,9 +8,9 @@ "binaryDir": "${sourceDir}/out/build/${presetName}", "installDir": "${sourceDir}/out/install/${presetName}", "cacheVariables": { - "CMAKE_C_COMPILER": "cl.exe", - "CMAKE_CXX_COMPILER": "cl.exe", - "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" + "CMAKE_C_COMPILER": "cl.exe", + "CMAKE_CXX_COMPILER": "cl.exe", + "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" }, "condition": { "type": "equals", diff --git a/assets/map/regions.map b/assets/map/regions.map new file mode 100644 index 0000000..db1df15 Binary files /dev/null and b/assets/map/regions.map differ diff --git a/assets/scenarios/empires.save b/assets/scenarios/empires.save index da43286..51b9795 100644 Binary files a/assets/scenarios/empires.save and b/assets/scenarios/empires.save differ diff --git a/cmake/executable.cmake b/cmake/executable.cmake new file mode 100644 index 0000000..eb0f0ed --- /dev/null +++ b/cmake/executable.cmake @@ -0,0 +1,52 @@ +function(add_executable_target TARGET_NAME) + + set(CMAKE_CXX_STANDARD 23) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + + + project(${TARGET_NAME} LANGUAGES CXX) + add_executable(${TARGET_NAME}) + + file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS + src/*.cpp + src/*.c + ) + + file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS + include/*.hpp + include/*.h + ) + + file(GLOB_RECURSE MODULES CONFIGURE_DEPENDS + modules/*.cppm + modules/*.ixx + ) + + target_sources(${TARGET_NAME} PUBLIC FILE_SET modules TYPE CXX_MODULES BASE_DIRS ${PROJECT_SOURCE_DIR} FILES ${MODULES}) + target_sources(${TARGET_NAME} PUBLIC FILE_SET headers TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR} FILES ${HEADERS}) + target_sources(${TARGET_NAME} PRIVATE ${SOURCES}) + + # MSVC STD module linking + # target_compile_options(${TARGET_NAME} PRIVATE + # /EHsc + # "SHELL:/reference \"std=$ENV{STD_MODULE_DIR}/std.ifc\"" + # "SHELL:/reference \"std.compat=$ENV{STD_MODULE_DIR}/std.compat.ifc\"" + #) + #target_link_libraries(${TARGET_NAME} PRIVATE "$ENV{STD_MODULE_DIR}/std.obj") + # target_link_libraries(${TARGET_NAME} PRIVATE "$ENV{STD_MODULE_DIR}/std.compat.obj") + #target_compile_options(${TARGET_NAME} PRIVATE + # /wd5050 + #) + #target_compile_features(${TARGET_NAME} PRIVATE cxx_std_23 INTERFACE cxx_std_23) + + # Clang modules +# target_compile_options(${TARGET_NAME} PRIVATE +# -fmodules +# -fcxx-modules +# -fbuiltin-module-map +# -fimplicit-module-maps +# ) + + target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) + +endfunction() diff --git a/cmake/library.cmake b/cmake/library.cmake new file mode 100644 index 0000000..43c51c9 --- /dev/null +++ b/cmake/library.cmake @@ -0,0 +1,52 @@ +function(add_library_target TARGET_NAME) + + set(CMAKE_CXX_STANDARD 23) + set(CMAKE_CXX_STANDARD_REQUIRED ON) + + + project(${TARGET_NAME} LANGUAGES CXX) + add_library(${TARGET_NAME}) + + file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS + src/*.cpp + src/*.c + ) + + file(GLOB_RECURSE HEADERS CONFIGURE_DEPENDS + include/*.hpp + include/*.h + ) + + file(GLOB_RECURSE MODULES CONFIGURE_DEPENDS + modules/*.cppm + modules/*.ixx + ) + + target_sources(${TARGET_NAME} PUBLIC FILE_SET modules TYPE CXX_MODULES BASE_DIRS ${PROJECT_SOURCE_DIR} FILES ${MODULES}) + target_sources(${TARGET_NAME} PUBLIC FILE_SET headers TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR} FILES ${HEADERS}) + target_sources(${TARGET_NAME} PRIVATE ${SOURCES}) + + # MSVC STD module linking + # target_compile_options(${TARGET_NAME} PRIVATE + # /EHsc + # "SHELL:/reference \"std=$ENV{STD_MODULE_DIR}/std.ifc\"" + # "SHELL:/reference \"std.compat=$ENV{STD_MODULE_DIR}/std.compat.ifc\"" + #) + #target_link_libraries(${TARGET_NAME} PRIVATE "$ENV{STD_MODULE_DIR}/std.obj") + # target_link_libraries(${TARGET_NAME} PRIVATE "$ENV{STD_MODULE_DIR}/std.compat.obj") + #target_compile_options(${TARGET_NAME} PRIVATE + # /wd5050 + #) + #target_compile_features(${TARGET_NAME} PRIVATE cxx_std_23 INTERFACE cxx_std_23) + + # Clang modules +# target_compile_options(${TARGET_NAME} PRIVATE +# -fmodules +# -fcxx-modules +# -fbuiltin-module-map +# -fimplicit-module-maps +# ) + + target_include_directories(${TARGET_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) + +endfunction() diff --git a/engine-api/CMakeLists.txt b/engine-api/CMakeLists.txt index 853ba5e..ad9bd7f 100644 --- a/engine-api/CMakeLists.txt +++ b/engine-api/CMakeLists.txt @@ -1,36 +1,18 @@ -if (POLICY CMP0141) - cmake_policy(SET CMP0141 NEW) - set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") -endif() - -set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - - project(engine-api) -file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS - "src/*.cpp" - "src/*.c" - "include/*.hpp" - "include/*.h" -) - +include(${CMAKE_SOURCE_DIR}/cmake/library.cmake) # Find dependencies find_package(glfw3 CONFIG REQUIRED) +find_package(glm CONFIG REQUIRED) # Link library -add_library(${PROJECT_NAME} ${SOURCES}) +add_library_target(${PROJECT_NAME}) target_link_libraries(${PROJECT_NAME} PRIVATE p7) +target_link_libraries(${PROJECT_NAME} PUBLIC server) target_link_libraries(${PROJECT_NAME} PUBLIC utils) target_link_libraries(${PROJECT_NAME} PRIVATE glfw) - -target_include_directories(${PROJECT_NAME} PUBLIC include/) - -if (CMAKE_VERSION VERSION_GREATER 3.12) - set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) -endif() \ No newline at end of file +target_link_libraries(${PROJECT_NAME} PRIVATE glm::glm) \ No newline at end of file diff --git a/engine-api/include/ee_engine_api/AssetData.hpp b/engine-api/include/ee_engine_api/AssetData.hpp deleted file mode 100644 index 33b1c75..0000000 --- a/engine-api/include/ee_engine_api/AssetData.hpp +++ /dev/null @@ -1,59 +0,0 @@ -#pragma once -#include "GameData.hpp" -#include "Map.hpp" -#include -#include -#include - -namespace ee_assets -{ - struct AssetData {}; - template concept Asset = std::derived_from; - - enum AssetType - { - BINARY, - - MAP_MESH, - SAVE, - - SHADER, - MATERIAL, - IMAGE - }; - - struct AssetBinary : public AssetData - { - uint8_t* content = nullptr; - size_t size = 0; - - AssetBinary(uint8_t* &source, const size_t sourceSize); - ~AssetBinary(); - }; - - struct AssetMapMesh : public AssetData - { - ee_engine::MapMesh content; - - uint8_t* Serialize(size_t &size); - AssetMapMesh() {}; - AssetMapMesh(uint8_t* &source, const size_t sourceSize); - }; - - struct AssetSave : public AssetData - { - std::vector subjects; - - uint8_t* Serialize(size_t &size); - AssetSave() {}; - AssetSave(uint8_t* &source, const size_t sourceSize); - }; - - #define AssetShader AssetBinary - - struct AssetMaterial : public AssetData - { - uint32_t vertexShaderAssetID; - uint32_t fragmentShaderAssetID; - }; -} \ No newline at end of file diff --git a/engine-api/include/ee_engine_api/GameData.hpp b/engine-api/include/ee_engine_api/GameData.hpp deleted file mode 100644 index cb8e3d7..0000000 --- a/engine-api/include/ee_engine_api/GameData.hpp +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include -#include - -namespace ee_data -{ - struct Subject - { - uint32_t tag; - uint32_t color; - std::vector regions; - }; -} \ No newline at end of file diff --git a/engine-api/include/ee_engine_api/Map.hpp b/engine-api/include/ee_engine_api/Map.hpp deleted file mode 100644 index 03997f3..0000000 --- a/engine-api/include/ee_engine_api/Map.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace ee_engine -{ - struct MapMesh - { - struct Province - { - std::vector vertices; - std::vector indices; - }; - std::unordered_map> states; - }; - - struct ProvinceSSBO - { - uint32_t stateId; - uint32_t color; - }; -} \ No newline at end of file diff --git a/engine-api/modules/AssetData.cppm b/engine-api/modules/AssetData.cppm new file mode 100644 index 0000000..8679207 --- /dev/null +++ b/engine-api/modules/AssetData.cppm @@ -0,0 +1,63 @@ +module; + +#include +#include +#include +#include + +export module AssetData; +import GameData; +import MapView; + +export namespace ee_assets +{ + struct AssetData {}; + template concept Asset = std::is_base_of_v; + + enum AssetType + { + BINARY, + + MAP_MESH, + SAVE, + + SHADER, + MATERIAL, + IMAGE + }; + + struct AssetBinary : public AssetData + { + std::uint8_t* content = nullptr; + std::size_t size = 0; + + AssetBinary(std::uint8_t* &source, const std::size_t sourceSize); + ~AssetBinary(); + }; + + struct AssetMapMesh : public AssetData + { + ee_engine::MapMesh content; + + std::uint8_t* Serialize(std::size_t &size); + AssetMapMesh() {}; + AssetMapMesh(std::uint8_t* &source, const std::size_t sourceSize); + }; + + struct AssetSave : public AssetData + { + ee_data::GameState content; + + std::uint8_t* Serialize(std::size_t &size); + AssetSave() {}; + AssetSave(std::uint8_t* &source, const std::size_t sourceSize); + }; + + using AssetShader = AssetBinary; + + struct AssetMaterial : public AssetData + { + std::uint32_t vertexShaderAssetID; + std::uint32_t fragmentShaderAssetID; + }; +} \ No newline at end of file diff --git a/engine-api/include/ee_engine_api/InputInterface.hpp b/engine-api/modules/Input.cppm similarity index 87% rename from engine-api/include/ee_engine_api/InputInterface.hpp rename to engine-api/modules/Input.cppm index ca9ee43..3b5c162 100644 --- a/engine-api/include/ee_engine_api/InputInterface.hpp +++ b/engine-api/modules/Input.cppm @@ -1,7 +1,10 @@ -#pragma once +module; + #include -namespace ee_engine +export module Input; + +export namespace ee_engine { struct InputHandlers { diff --git a/engine-api/include/ee_engine_api/RenderInterface.hpp b/engine-api/modules/Render.cppm similarity index 50% rename from engine-api/include/ee_engine_api/RenderInterface.hpp rename to engine-api/modules/Render.cppm index 06ac6a6..e043d7c 100644 --- a/engine-api/include/ee_engine_api/RenderInterface.hpp +++ b/engine-api/modules/Render.cppm @@ -1,62 +1,102 @@ -#pragma once -#include -#include "Map.hpp" -#include "AssetData.hpp" +module; -namespace ee_engine +#include +#include +#include +#include +#include +#include + +export module Render; +import worker; +import MapView; +import AssetData; + +export namespace ee_engine { struct ShaderRefs { ee_assets::AssetShader *vertProvinces; ee_assets::AssetShader *fragProvinces; }; - + struct CameraTransform { glm::vec2 position {0.0f, 0.0f}; float zoom = 1.0f; }; - + struct MeshTransform { glm::vec2 position {0.0f, 0.0f}; glm::vec2 scale {1.0f, 1.0f}; float rotation; }; - - class IRenderer + + struct RendererCommand : public ee_utils::WorkerCommand + { + enum Type : std::uint8_t + { + NONE, + + UPDATE_REGION, + + COMPLETED + }; + + struct RegionPayload { std::uint32_t id; ProvinceSSBO data; }; + + union { + RegionPayload region; + }; + }; + + class IRenderer : public ee_utils::Worker { public: virtual ~IRenderer(); - + + constexpr bool isReady() const noexcept {return _isReady;} + void RegisterMaterials(const ShaderRefs &shaders); void RegisterMapMesh(MapMesh *mapMesh); - + virtual void Init() = 0; virtual void Shutdown() = 0; void Draw(); - + virtual void ResizeWindow(int width, int height); void SetCamera(const CameraTransform &camera); - CameraTransform getCamera(); - + constexpr CameraTransform getCamera() const noexcept {return camera;}; + + + protected: + bool _isReady; int screenWidth, screenHeight; float screenAspect; CameraTransform camera; glm::mat4 viewProjection; - + GLFWwindow *window; MapMesh *mapMesh; ShaderRefs shaders; - + + struct RegionIndecies {std::size_t startIndex; std::size_t provincesCount;}; + std::unordered_map regionsMapping; + explicit IRenderer(GLFWwindow *window); - + virtual void Clear() = 0; virtual void DrawMap() = 0; virtual void DrawUI() = 0; - + virtual void ApplyCamera() = 0; + + virtual void UpdateProvinces(const std::size_t index, const std::vector &data) = 0; + + private: + void UpdateRegionCmd(RendererCommand &command); }; } \ No newline at end of file diff --git a/engine-api/modules/views/MapView.cppm b/engine-api/modules/views/MapView.cppm new file mode 100644 index 0000000..cd71529 --- /dev/null +++ b/engine-api/modules/views/MapView.cppm @@ -0,0 +1,28 @@ +module; + +#include +#include +#include +#include + +//TODO: module Views +export module MapView; + +export namespace ee_engine +{ + struct MapMesh + { + struct Province + { + std::vector vertices; + std::vector indices; + }; + std::unordered_map> regions; + }; + + struct ProvinceSSBO + { + std::uint32_t regionId; + std::uint32_t color; + }; +} \ No newline at end of file diff --git a/engine-api/src/AssetData.cpp b/engine-api/src/AssetData.cpp index 6810b73..1f8fbcb 100644 --- a/engine-api/src/AssetData.cpp +++ b/engine-api/src/AssetData.cpp @@ -1,7 +1,12 @@ -#include -#include -#include +module; + #include +#include +#include + +module AssetData; +import allocator; +import buffers; /* @@ -9,12 +14,11 @@ YOU CAN PREVENT SOURCE BUFFER FROM CLOSING. IT CAN BE USED FOR STORING ASSET DATA WITHOUT COPY. IN THIS CASE, YOU MUST SET SOURCE TO NULLPTR AND FREE BUFFER YOURSELF. -TODO: make binary format describing for common functions instead of individual serialize/deserialize functions -TODO: parallelize convertion loops +TODO: make universal binary format, think about flatbuffers or msgpacks */ -ee_assets::AssetBinary::AssetBinary(uint8_t* &source, const size_t sourceSize) +ee_assets::AssetBinary::AssetBinary(std::uint8_t* &source, const std::size_t sourceSize) { content = source; size = sourceSize; @@ -29,62 +33,62 @@ ee_assets::AssetBinary::~AssetBinary() -ee_assets::AssetMapMesh::AssetMapMesh(uint8_t* &source, const size_t sourceSize) +ee_assets::AssetMapMesh::AssetMapMesh(std::uint8_t* &source, const std::size_t sourceSize) { - uint8_t* buffer = source; - uint8_t* pointer = source; - size_t leftoverSize = sourceSize; + std::uint8_t* buffer = source; + std::uint8_t* pointer = source; + std::size_t leftoverSize = sourceSize; source = nullptr; - uint32_t statesCount = 0; - ee_utils::readNext(&statesCount, pointer, leftoverSize, sizeof(uint32_t)); + std::uint32_t statesCount = 0; + ee_utils::readNext(&statesCount, pointer, leftoverSize, sizeof(std::uint32_t)); - for (uint32_t state = 0; state < statesCount; state++) + for (std::uint32_t state = 0; state < statesCount; state++) { - uint32_t id = 0; + std::uint32_t id = 0; glm::u8vec3 color {}; if (!ee_utils::readNext(&color, pointer, leftoverSize, sizeof(glm::u8vec3))) break; - id = static_cast(color.r) << 16 | - static_cast(color.g) << 8 | - static_cast(color.b); - - uint32_t provincesCount = 0; - ee_utils::readNext(&provincesCount, pointer, leftoverSize, sizeof(uint32_t)); + id = static_cast(color.r) << 16 | + static_cast(color.g) << 8 | + static_cast(color.b); - for (uint32_t pi = 0; pi < provincesCount; pi++) + std::uint32_t provincesCount = 0; + ee_utils::readNext(&provincesCount, pointer, leftoverSize, sizeof(std::uint32_t)); + + for (std::uint32_t pi = 0; pi < provincesCount; pi++) { ee_engine::MapMesh::Province prov; - uint32_t verticesCount = 0; - if (!ee_utils::readNext(&verticesCount, pointer, leftoverSize, sizeof(uint32_t))) + std::uint32_t verticesCount = 0; + if (!ee_utils::readNext(&verticesCount, pointer, leftoverSize, sizeof(std::uint32_t))) break; prov.vertices.reserve(verticesCount); - for (uint32_t vi = 0; vi < verticesCount; vi++) + for (std::uint32_t vi = 0; vi < verticesCount; vi++) { glm::vec2 vertex; if (!ee_utils::readNext(&vertex, pointer, leftoverSize, sizeof(glm::vec2))) break; - + prov.vertices.push_back(vertex); } - uint32_t indicesCount = 0; - if (!ee_utils::readNext(&indicesCount, pointer, leftoverSize, sizeof(uint32_t))) + std::uint32_t indicesCount = 0; + if (!ee_utils::readNext(&indicesCount, pointer, leftoverSize, sizeof(std::uint32_t))) break; prov.indices.reserve(indicesCount); - for(uint32_t ii = 0; ii < indicesCount; ii++) + for(std::uint32_t ii = 0; ii < indicesCount; ii++) { - uint16_t index = 0; - if (!ee_utils::readNext(&index, pointer, leftoverSize, sizeof(uint16_t))) + std::uint16_t index = 0; + if (!ee_utils::readNext(&index, pointer, leftoverSize, sizeof(std::uint16_t))) break; - + prov.indices.push_back(index); } - content.states[id].push_back(prov); + content.regions[id].push_back(prov); } } @@ -92,34 +96,34 @@ ee_assets::AssetMapMesh::AssetMapMesh(uint8_t* &source, const size_t sourceSize) } -ee_assets::AssetSave::AssetSave(uint8_t* &source, const size_t sourceSize) +ee_assets::AssetSave::AssetSave(std::uint8_t* &source, const std::size_t sourceSize) { - uint8_t* buffer = source; - uint8_t* pointer = source; - size_t leftoverSize = sourceSize; + std::uint8_t* buffer = source; + std::uint8_t* pointer = source; + std::size_t leftoverSize = sourceSize; source = nullptr; - uint16_t subjectsCount = static_cast(subjects.size()); - ee_utils::readNext(&subjectsCount, pointer, leftoverSize, sizeof(uint16_t)); + std::uint16_t subjectsCount = static_cast(content.subjects.size()); + ee_utils::readNext(&subjectsCount, pointer, leftoverSize, sizeof(std::uint16_t)); - for (uint16_t i = 0; i < subjectsCount; i++) + for (std::uint16_t i = 0; i < subjectsCount; i++) { ee_data::Subject subject; ee_utils::readNext(&subject.tag, pointer, leftoverSize, sizeof(subject.tag)); ee_utils::readNext(&subject.color, pointer, leftoverSize, sizeof(subject.color)); - - uint16_t regionsCount = 0; - ee_utils::readNext(®ionsCount, pointer, leftoverSize, sizeof(uint16_t)); + + std::uint16_t regionsCount = 0; + ee_utils::readNext(®ionsCount, pointer, leftoverSize, sizeof(std::uint16_t)); subject.regions.resize(regionsCount); ee_utils::readNext( - subject.regions.data(), - pointer, - leftoverSize, - subject.regions.size() * sizeof(uint32_t) + subject.regions.data(), + pointer, + leftoverSize, + subject.regions.size() * sizeof(std::uint32_t) ); - subjects.push_back(subject); + content.subjects.push_back(subject); } DeallocateArray(buffer); @@ -131,35 +135,35 @@ ee_assets::AssetSave::AssetSave(uint8_t* &source, const size_t sourceSize) // SERIALIZERS -uint8_t* ee_assets::AssetSave::Serialize(size_t &size) +std::uint8_t* ee_assets::AssetSave::Serialize(std::size_t &size) { - size = sizeof(uint16_t); - for (ee_data::Subject &subject : subjects) + size = sizeof(std::uint16_t); + for (ee_data::Subject &subject : content.subjects) { size += sizeof(subject.tag); size += sizeof(subject.color); - size += sizeof(uint16_t) + subject.regions.size() * sizeof(uint32_t); + size += sizeof(std::uint16_t) + subject.regions.size() * sizeof(std::uint32_t); } - size_t leftover = size; - uint8_t *result = AllocateArray(size); - uint8_t *pointer = result; + std::size_t leftover = size; + std::uint8_t *result = AllocateArray(size); + std::uint8_t *pointer = result; - uint16_t subjectsCount = static_cast(subjects.size()); - ee_utils::writeNext(pointer, &subjectsCount, leftover, sizeof(uint16_t)); + std::uint16_t subjectsCount = static_cast(content.subjects.size()); + ee_utils::writeNext(pointer, &subjectsCount, leftover, sizeof(std::uint16_t)); - for (ee_data::Subject &subject : subjects) + for (ee_data::Subject &subject : content.subjects) { ee_utils::writeNext(pointer, &subject.tag, leftover, sizeof(subject.tag)); ee_utils::writeNext(pointer, &subject.color, leftover, sizeof(subject.color)); - - uint16_t regionsCount = static_cast(subject.regions.size()); - ee_utils::writeNext(pointer, ®ionsCount, leftover, sizeof(uint16_t)); + + std::uint16_t regionsCount = static_cast(subject.regions.size()); + ee_utils::writeNext(pointer, ®ionsCount, leftover, sizeof(std::uint16_t)); ee_utils::writeNext( - pointer, - subject.regions.data(), - leftover, - subject.regions.size() * sizeof(uint32_t) + pointer, + subject.regions.data(), + leftover, + subject.regions.size() * sizeof(std::uint32_t) ); } diff --git a/engine-api/src/Render.cpp b/engine-api/src/Render.cpp new file mode 100644 index 0000000..32d0976 --- /dev/null +++ b/engine-api/src/Render.cpp @@ -0,0 +1,104 @@ +module; + +#include "Logger.h" +#include +#include +#include +#include +#include +#include + +module Render; + +ee_engine::IRenderer::IRenderer(GLFWwindow *window) +{ + commandsMapping[RendererCommand::UPDATE_REGION] = MAP_WORKER_COMMAND(RendererCommand, UpdateRegionCmd); + + this->window = window; + glfwGetFramebufferSize(window, &screenWidth, &screenHeight); + screenAspect = static_cast(screenWidth) / static_cast(screenHeight); +} + +ee_engine::IRenderer::~IRenderer() +{ + +} + +void ee_engine::IRenderer::RegisterMaterials(const ShaderRefs &shaders) +{ + this->shaders = shaders; +} + +void ee_engine::IRenderer::RegisterMapMesh(MapMesh* mapMesh) +{ + this->mapMesh = mapMesh; +} + +void ee_engine::IRenderer::Draw() +{ + Clear(); + DrawMap(); + DrawUI(); +} + +void ee_engine::IRenderer::ResizeWindow(int width, int height) +{ + screenWidth = width; + screenHeight = height; + screenAspect = static_cast(screenWidth) / static_cast(screenHeight); +} + +void ee_engine::IRenderer::SetCamera(const CameraTransform &camera) +{ + if (camera.zoom <= 0) + { + LOG(WARNING, "Camera zoom cannot be zero or less!"); + return; + } + + this->camera = camera; + + float halfHeight = camera.zoom; + float halfWidth = camera.zoom * screenAspect; + + glm::mat4 P = glm::ortho( + -halfWidth, +halfWidth, + -halfHeight, +halfHeight + ); + + glm::mat4 V = glm::translate( + glm::mat4(1.0f), + glm::vec3(-camera.position, 0.0f) + ); + + viewProjection = P * V; + + ApplyCamera(); +} + +void ee_engine::IRenderer::UpdateRegionCmd(ee_engine::RendererCommand &command) +{ + if (!regionsMapping.contains(command.region.id)) + { + LOG(WARNING, "Updating unregistered region with id: %d", command.region.id); + return; + } + + if (command.region.id != command.region.data.regionId) + { + LOG(ERROR, "Updating regions ID is not supported! Region: %d Changed ID: %d", + command.region.id, command.region.data.regionId); + } + + RegionIndecies mapping = regionsMapping[command.region.id]; + std::vector buffer; + buffer.reserve(mapping.provincesCount); + for (std::size_t i = 0; i < mapping.provincesCount; i++) + { + buffer.push_back(command.region.data); + } + + UpdateProvinces(mapping.startIndex, buffer); + + command.type = ee_engine::RendererCommand::COMPLETED; +} \ No newline at end of file diff --git a/engine-api/src/RenderInterface.cpp b/engine-api/src/RenderInterface.cpp deleted file mode 100644 index 1c886eb..0000000 --- a/engine-api/src/RenderInterface.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include -#include -#include "Logger.h" - -ee_engine::IRenderer::IRenderer(GLFWwindow *window) -{ - this->window = window; - glfwGetFramebufferSize(window, &screenWidth, &screenHeight); - screenAspect = static_cast(screenWidth) / static_cast(screenHeight); -} - -ee_engine::IRenderer::~IRenderer() -{ - -} - -void ee_engine::IRenderer::RegisterMaterials(const ShaderRefs &shaders) -{ - this->shaders = shaders; -} - -void ee_engine::IRenderer::RegisterMapMesh(MapMesh* mapMesh) -{ - this->mapMesh = mapMesh; -} - -void ee_engine::IRenderer::Draw() -{ - Clear(); - DrawMap(); - DrawUI(); -} - -void ee_engine::IRenderer::ResizeWindow(int width, int height) -{ - screenWidth = width; - screenHeight = height; - screenAspect = static_cast(screenWidth) / static_cast(screenHeight); -} - -void ee_engine::IRenderer::SetCamera(const CameraTransform &camera) -{ - if (camera.zoom <= 0) - { - LOG(WARNING, "Camera zoom cannot be zero or less!"); - return; - } - - this->camera = camera; - - float halfHeight = camera.zoom; - float halfWidth = camera.zoom * screenAspect; - - glm::mat4 P = glm::ortho( - -halfWidth, +halfWidth, - -halfHeight, +halfHeight - ); - - glm::mat4 V = glm::translate( - glm::mat4(1.0f), - glm::vec3(-camera.position, 0.0f) - ); - - viewProjection = P * V; - - ApplyCamera(); -} - -ee_engine::CameraTransform ee_engine::IRenderer::getCamera() {return this->camera;} \ No newline at end of file diff --git a/engine/.vscode/launch.json b/engine/.vscode/launch.json deleted file mode 100644 index e8338f2..0000000 --- a/engine/.vscode/launch.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "configurations": [ - { - "type": "cmake", - "request": "launch", - "name": "Debug portfile(s)", - "cmakeDebugType": "external", - "pipeName": "\\\\.\\pipe\\vcpkg_ext_portfile_dbg", - "preLaunchTask": "Debug vcpkg commands" - } - ] -} \ No newline at end of file diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 09cbd2a..b31ea13 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -1,24 +1,6 @@ -cmake_minimum_required (VERSION 3.8) +include(${CMAKE_SOURCE_DIR}/cmake/executable.cmake) -if (POLICY CMP0141) - cmake_policy(SET CMP0141 NEW) - set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") -endif() - -set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -project (engine) - - -# List sources - -file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS - "src/*.cpp" - "src/*.c" - "include/*.hpp" - "include/*.h" -) +set(EXE engine) # Find dependencies @@ -29,45 +11,38 @@ find_package(glm CONFIG REQUIRED) # Link library -add_executable(${PROJECT_NAME} ${SOURCES}) +add_executable_target(${EXE}) -target_link_libraries(${PROJECT_NAME} PUBLIC utils) -target_link_libraries(${PROJECT_NAME} PUBLIC engine-api) -target_link_libraries(${PROJECT_NAME} PUBLIC magnum-renderer) +target_link_libraries(${EXE} PUBLIC utils) +target_link_libraries(${EXE} PUBLIC engine-api) +target_link_libraries(${EXE} PUBLIC magnum-renderer) -target_link_libraries(${PROJECT_NAME} PRIVATE Boost::lockfree) -target_link_libraries(${PROJECT_NAME} PRIVATE xxHash::xxhash) -target_link_libraries(${PROJECT_NAME} PRIVATE p7) -target_link_libraries(${PROJECT_NAME} PRIVATE glfw) -target_link_libraries(${PROJECT_NAME} PRIVATE glm::glm) - -target_include_directories(${PROJECT_NAME} PUBLIC include/) - -if (CMAKE_VERSION VERSION_GREATER 3.12) - set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) -endif() +target_link_libraries(${EXE} PRIVATE Boost::lockfree) +target_link_libraries(${EXE} PRIVATE xxHash::xxhash) +target_link_libraries(${EXE} PRIVATE p7) +target_link_libraries(${EXE} PRIVATE glfw) +target_link_libraries(${EXE} PRIVATE glm::glm) # Compile options if (APP_VERSION) - string(REPLACE "." ";" APP_VERSION_LIST ${APP_VERSION}) - list(GET APP_VERSION_LIST 0 MAJOR_VERSION) - list(GET APP_VERSION_LIST 1 MINOR_VERSION) - list(GET APP_VERSION_LIST 2 PATCH_VERSION) - target_compile_definitions(${PROJECT_NAME} - PRIVATE APP_VERSION - PRIVATE MAJOR_VERSION=${MAJOR_VERSION} - PRIVATE MINOR_VERSION=${MINOR_VERSION} - PRIVATE PATCH_VERSION=${PATCH_VERSION} - ) + string(REPLACE "." ";" APP_VERSION_LIST ${APP_VERSION}) + list(GET APP_VERSION_LIST 0 MAJOR_VERSION) + list(GET APP_VERSION_LIST 1 MINOR_VERSION) + list(GET APP_VERSION_LIST 2 PATCH_VERSION) + target_compile_definitions(${EXE} + PRIVATE APP_VERSION + PRIVATE MAJOR_VERSION=${MAJOR_VERSION} + PRIVATE MINOR_VERSION=${MINOR_VERSION} + PRIVATE PATCH_VERSION=${PATCH_VERSION} + ) endif() # Set a symbolic link so executable can find the /assets folder set(link_src "${CMAKE_SOURCE_DIR}/assets") set(link_dst "${CMAKE_CURRENT_BINARY_DIR}/assets") -add_custom_command( - TARGET ${PROJECT_NAME} - POST_BUILD COMMAND ${CMAKE_COMMAND} - -E create_symlink ${link_src} ${link_dst} - DEPENDS ${link_dst} - COMMENT "symbolic link ${link_src} => ${link_dst}" +add_custom_command( + TARGET ${EXE} + POST_BUILD COMMAND ${CMAKE_COMMAND} + -E create_symlink ${link_src} ${link_dst} + COMMENT "symbolic link ${link_src} => ${link_dst}" ) \ No newline at end of file diff --git a/engine/include/Actions.hpp b/engine/include/Actions.hpp deleted file mode 100644 index 4a7ff4d..0000000 --- a/engine/include/Actions.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include - -class Actions -{ -public: - static ee_engine::InputHandlers mappings; - -private: - static void Zoom(float dx, float dy); - static void MapScroll(float dx, float dy); - - Actions(); -}; \ No newline at end of file diff --git a/engine/include/AssetManager.hpp b/engine/include/AssetManager.hpp deleted file mode 100644 index fe8628e..0000000 --- a/engine/include/AssetManager.hpp +++ /dev/null @@ -1,172 +0,0 @@ -#pragma once -#include "FileSystem.hpp" -#include - -#include "Logger.h" -#include -#include -#include -#include -#include -#include -#include - -#define INVALID_ASSET_ID UINT32_MAX - -struct AssetAddress -{ - std::atomic resource; -}; - -struct AssetHandle -{ - size_t slot = 0; - uint32_t id = 0; -}; - -class AssetInfo -{ -public: - ee_assets::AssetType type = ee_assets::BINARY; - - std::atomic isReady; - AssetAddress* resourceAddress; - - AssetInfo(void *resource); - - AssetInfo(const AssetInfo&) = delete; - AssetInfo& operator=(const AssetInfo&) = delete; - - AssetInfo(AssetInfo&& other) noexcept; - AssetInfo& operator=(AssetInfo&& other) noexcept; -}; - -struct AssetLoadingEntry -{ - AssetHandle handle; - FileHandle* file; - IFileSystem* fileOwner; -}; - -struct AssetStreamCommand -{ - enum Type - { - NONE, - - LOAD, - FIND, - GET, - - COMPLETED - } type = NONE; - - AssetHandle target; - uint32_t targetId = INVALID_ASSET_ID; - std::filesystem::path targetPath; - ee_assets::AssetType targetType = ee_assets::BINARY; - std::atomic* out; -}; - -class AssetManager -{ -public: - std::atomic isRunning; - - AssetManager(); - ~AssetManager(); - - void Start(); - void Shutdown(); - - void LoadDir(ee_assets::AssetType type, const std::filesystem::path &path); - - void LoadAsync(ee_assets::AssetType type, const std::filesystem::path &path); - AssetHandle& Find(const std::filesystem::path &path); - AssetHandle& Find(const uint32_t &id); - template T& FindOnce(const std::filesystem::path &path); - template T& FindOnce(const uint32_t &id); - void Redirect(AssetHandle &handle, void *resource); - template T& Get(const AssetHandle &handle); - void Free(AssetHandle &handle); - -private: - std::stop_token *stoken; - std::jthread streamingThread; - boost::lockfree::spsc_queue> commands; - - IFileSystem *diskSystem; - - std::vector activeAssets; - std::unordered_map assetsIdMapping; - std::unordered_map assetsMapping; - std::vector freeAssetSlots; - std::vector loadingEntries; - - std::vector binaryStorage; - std::vector savesStorage; - std::vector mapMeshesStorage; - std::vector shadersStorage; - std::vector materialsStorage; - - void Threading(); - void Request(const AssetStreamCommand &command); - void Request(const AssetStreamCommand::Type &type); - void Loop(); - void ProcessCommand(AssetStreamCommand &command); - void Release(); - - template void FinishLoadConstruct(AssetLoadingEntry &loaded, std::vector &storage); - template void FinishLoadPlain(AssetLoadingEntry &loaded, std::vector &storage); - template void ClearStorage(std::vector &storage); -}; - -template T& AssetManager::Get(const AssetHandle &handle) -{ - std::atomic result; - AssetStreamCommand command { - .type = AssetStreamCommand::GET, - .target = handle, - .out = &result - }; - Request(command); - while (command.out->load() == nullptr); - return *reinterpret_cast(command.out->load()); -} - -template T& AssetManager::FindOnce(const std::filesystem::path &path) -{ - return Get(Find(path)); -} - -template T& AssetManager::FindOnce(const uint32_t &id) -{ - return Get(Find(id)); -} - -template void AssetManager::FinishLoadConstruct(AssetLoadingEntry &loaded, std::vector &storage) -{ - T* resource = Allocate(loaded.file->data, loaded.file->size); - storage.push_back(resource); - Redirect(loaded.handle, storage.back()); -} - -template void AssetManager::FinishLoadPlain(AssetLoadingEntry &loaded, std::vector &storage) -{ - T* resource = Allocate(); - if (loaded.file->size < sizeof(T)) - LOG(CRITICAL, "File size is less than needed for asset of type: %d", typeid(T).name()); - std::memcpy(resource, loaded.file->data, sizeof(T)); - storage.push_back(resource); - Redirect(loaded.handle, storage.back()); -} - -template void AssetManager::ClearStorage(std::vector &storage) -{ - for (T* &resource : storage) - { - if (resource != nullptr) - Deallocate(resource); - } - storage.clear(); -} \ No newline at end of file diff --git a/engine/include/Engine.hpp b/engine/include/Engine.hpp deleted file mode 100644 index 8032060..0000000 --- a/engine/include/Engine.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include -#include -#include -#include "AssetManager.hpp" - -class Engine -{ -public: - static GLFWwindow *window; - static ee_engine::IInput *input; - static AssetManager *assetManager; - static ee_engine::IRenderer *renderer; - - static void Shutdown(); - -private: - Engine(); -}; diff --git a/engine/include/FileSystem.hpp b/engine/include/FileSystem.hpp deleted file mode 100644 index 1df5a35..0000000 --- a/engine/include/FileSystem.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once -#include -#include -#include - -#ifdef _WIN32 - #include -#endif - -#ifdef __linux__ -#endif - -#define FILE_OPEN_NONE 0 -#define FILE_OPEN_READ (1 << 0) -#define FILE_OPEN_WRITE (1 << 1) -#define FILE_OPEN_MMAP (1 << 2) - -#define FILE_READ_SEQUENTIAL 0 -#define FILE_READ_RANDOM_ACCESS (1 << 0) - -struct FileHandle -{ - size_t id = 0; - - size_t size = 0; - size_t bufferSize = 0; - uint8_t *data = nullptr; - uint8_t *buffer = nullptr; - - #ifndef NDEBUG - std::filesystem::path debugPath; - #endif - - #ifdef _WIN32 - HANDLE win32Handle = INVALID_HANDLE_VALUE; - OVERLAPPED overlapped; - #endif - - #ifdef __linux__ - #endif -}; - -class IFileSystem -{ -public: - virtual FileHandle& Open(const std::filesystem::path &path, const uint32_t flags) = 0; - virtual void ReadAsync(FileHandle &file, const uint32_t bufferSize, const uint32_t flags) = 0; - virtual bool PollReady(FileHandle &file) = 0; - virtual void Close(FileHandle &file) = 0; - - ~IFileSystem(); - -protected: - std::vector activeFiles; - std::vector failedFiles; - std::vector freeFileSlots; -}; - -class NativeFileSystem : public IFileSystem -{ -public: - FileHandle& Open(const std::filesystem::path &path, const uint32_t flags) override; - void ReadAsync(FileHandle &file, const uint32_t bufferSize, uint32_t flags) override; - bool PollReady(FileHandle &file) override; - void Close(FileHandle &file) override; - -private: - -}; \ No newline at end of file diff --git a/engine/include/GLFWInput.hpp b/engine/include/GLFWInput.hpp deleted file mode 100644 index 755cfa0..0000000 --- a/engine/include/GLFWInput.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include -#include - -class GLFWInput : public ee_engine::IInput -{ -public: - GLFWInput(ee_engine::InputHandlers handlers); - void Poll() override; -}; \ No newline at end of file diff --git a/engine/include/compile_config.hpp b/engine/include/compile_config.hpp index 6fe4a2e..fbdbf69 100644 --- a/engine/include/compile_config.hpp +++ b/engine/include/compile_config.hpp @@ -1,17 +1,20 @@ -#pragma once +#ifndef ETREDIAEMPIRES_COMPILE_CONFIG_HPP +#define ETREDIAEMPIRES_COMPILE_CONFIG_HPP #define P7_LOGS_PATH L" /P7.Dir=logs/game/" #ifdef NDEBUG - #define P7_SINK L" /P7.Sink=FileTxt" +#define P7_SINK L" /P7.Sink=FileTxt" #else - #define P7_SINK L" /P7.Sink=Console" +#define P7_SINK L" /P7.Sink=Console" #endif #ifndef APP_VERSION - #define MAJOR_VERSION 0 - #define MINOR_VERSION 0 - #define PATCH_VERSION 0 +#define MAJOR_VERSION 0 +#define MINOR_VERSION 0 +#define PATCH_VERSION 0 #endif -#define ASSETS_HASH_SPACE 0 \ No newline at end of file +#define ASSETS_HASH_SPACE 0 + +#endif //ETREDIAEMPIRES_COMPILE_CONFIG_HPP diff --git a/engine/modules/Actions.cppm b/engine/modules/Actions.cppm new file mode 100644 index 0000000..43ac330 --- /dev/null +++ b/engine/modules/Actions.cppm @@ -0,0 +1,17 @@ +export module Actions; +import Input; + +export +{ + class Actions + { + public: + static ee_engine::InputHandlers mappings; + + private: + static void Zoom(float dx, float dy); + static void MapScroll(float dx, float dy); + + Actions(); + }; +} \ No newline at end of file diff --git a/engine/modules/AssetManager.cppm b/engine/modules/AssetManager.cppm new file mode 100644 index 0000000..60abb68 --- /dev/null +++ b/engine/modules/AssetManager.cppm @@ -0,0 +1,425 @@ +module; + +#include "Logger.h" +#include "compile_config.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +export module AssetManager; + export import AssetData; + +import allocator; +import worker; +import FileSystem; + +export +{ + struct AssetAddress + { + std::atomic resource; + }; + + struct AssetHandle + { + inline static constexpr std::uint32_t INVALID_ASSET_ID = UINT32_MAX; + std::size_t slot = 0; + std::uint32_t id = 0; + }; + + class AssetInfo + { + public: + ee_assets::AssetType type = ee_assets::BINARY; + + std::atomic isReady; + AssetAddress* resourceAddress; + + AssetInfo(void *resource) + { + this->resourceAddress = Allocate(); + this->resourceAddress->resource.store(resource); + } + + AssetInfo(const AssetInfo&) = delete; + AssetInfo& operator=(const AssetInfo&) = delete; + + AssetInfo(AssetInfo&& other) noexcept : + type(other.type), + resourceAddress(other.resourceAddress) + { + isReady.store(other.isReady.load(std::memory_order_relaxed), std::memory_order_relaxed); + + other.resourceAddress = nullptr; + other.isReady.store(false, std::memory_order_relaxed); + } + + AssetInfo& operator=(AssetInfo&& other) noexcept + { + if (this != &other) + { + type = other.type; + resourceAddress = other.resourceAddress; + isReady.store(other.isReady.load(std::memory_order_relaxed), std::memory_order_relaxed); + + other.resourceAddress = nullptr; + other.isReady.store(false, std::memory_order_relaxed); + } + return *this; + } + }; + + struct AssetLoadingEntry + { + AssetHandle handle; + FileHandle* file; + IFileSystem* fileOwner; + }; + + struct AssetStreamCommand : ee_utils::WorkerCommand + { + enum Type : std::uint8_t + { + NONE, + + LOAD, + FIND, + GET, + + COMPLETED + }; + + AssetHandle target; + std::uint32_t targetId = AssetHandle::INVALID_ASSET_ID; + std::filesystem::path targetPath; + ee_assets::AssetType targetType = ee_assets::BINARY; + std::atomic* out = nullptr; + }; + + class AssetManager final : public ee_utils::ThreadedWorker + { + public: + AssetManager() : ee_utils::ThreadedWorker(L"Assets Stream") + { + commandsMapping[AssetStreamCommand::LOAD] = MAP_WORKER_COMMAND(AssetStreamCommand, LoadCmd); + commandsMapping[AssetStreamCommand::FIND] = MAP_WORKER_COMMAND(AssetStreamCommand, FindCmd); + commandsMapping[AssetStreamCommand::GET] = MAP_WORKER_COMMAND(AssetStreamCommand, GetCmd); + + diskSystem = Allocate(); + } + + ~AssetManager() + { + Deallocate(diskSystem); + } + + void LoadDir(ee_assets::AssetType type, const std::filesystem::path &path) + { + for (const std::filesystem::directory_entry &entry : std::filesystem::directory_iterator(path)) + { + if (entry.is_directory()) continue; + LoadAsync(type, entry.path()); + } + } + + void LoadAsync(ee_assets::AssetType type, const std::filesystem::path &path) + { + AssetStreamCommand command; + command.type = AssetStreamCommand::LOAD; + command.targetPath = path; + command.targetType = type; + + Request(command); + } + + AssetHandle& Find(const std::filesystem::path &path) + { + std::atomic result; + AssetStreamCommand command; + command.type = AssetStreamCommand::FIND; + command.targetPath = path; + command.out = &result; + + Request(command); + while (command.out->load() == nullptr); + return *reinterpret_cast(command.out->load()); + } + + AssetHandle& Find(const std::uint32_t &id) + { + std::atomic result; + AssetStreamCommand command; + command.type = AssetStreamCommand::FIND; + command.targetId = id; + command.out = &result; + + Request(command); + while (command.out->load() == nullptr); + return *reinterpret_cast(command.out->load()); + } + + // Returned resource reference should not be stored + template T& FindOnce(const std::filesystem::path &path) + { + return Get(Find(path)); + } + + // Returned resource reference should not be stored + template T& FindOnce(const std::uint32_t &id) + { + return Get(Find(id)); + } + + void Redirect(AssetHandle &handle, void *resource) + { + AssetInfo &asset = activeAssets[handle.slot]; + if (asset.resourceAddress == nullptr) + { + LOG(WARNING, "Attempt to redirect empty handle"); + return; + } + + // TODO: LEAK! Free old resource after redirecting handler to other resource + if (asset.resourceAddress->resource.load() != nullptr) + { + void* oldResource = asset.resourceAddress->resource.exchange(nullptr, std::memory_order_acq_rel); + //if (oldResource) + //Deallocate(oldResource); + } + + asset.resourceAddress->resource.store(resource); + } + + // Returned resource reference should not be stored + template T& Get(const AssetHandle &handle) + { + std::atomic result; + AssetStreamCommand command; + command.type = AssetStreamCommand::GET; + command.target = handle; + command.out = &result; + + Request(command); + while (command.out->load() == nullptr); + return *reinterpret_cast(command.out->load()); + } + + void Free(AssetHandle &handle) + { + AssetInfo &asset = activeAssets[handle.slot]; + Redirect(handle, nullptr); + Deallocate(asset.resourceAddress); + asset.resourceAddress = nullptr; + + freeAssetSlots.push_back(handle.slot); + } + + protected: + void Update() override + { + // TODO: FinishLoadTasks() + for (AssetLoadingEntry &entry : loadingEntries) + { + bool isReady = entry.fileOwner->PollReady(*entry.file); + if (isReady) + { + AssetInfo& asset = activeAssets[entry.handle.slot]; + + switch (asset.type) + { + case ee_assets::MAP_MESH: + FinishLoadConstruct(entry, mapMeshesStorage); + break; + case ee_assets::SAVE: + FinishLoadConstruct(entry, savesStorage); + break; + + case ee_assets::SHADER: + FinishLoadConstruct(entry, shadersStorage); + break; + case ee_assets::MATERIAL: + FinishLoadPlain(entry, materialsStorage); + break; + case ee_assets::IMAGE: + break; + + case ee_assets::BINARY: + default: + FinishLoadConstruct(entry, binaryStorage); + break; + } + + entry.fileOwner->Close(*entry.file); + #ifndef NDEBUG + LOG(INFO, "Asset loaded: [%hs]", entry.file->debugPath.generic_u8string().c_str()); + #endif + entry.file = nullptr; + asset.isReady.store(true); + } + } + + std::erase_if(loadingEntries, [](const AssetLoadingEntry &entry) { + return entry.file == nullptr; + }); + } + + void Release() override + { + for (AssetInfo &asset : activeAssets) + { + //TODO: LEAK! Free resource + if (asset.resourceAddress->resource.load() != nullptr) + { + void* resource = asset.resourceAddress->resource.exchange(nullptr, std::memory_order_acq_rel); + //if (resource) + //Deallocate(resource); + } + Deallocate(asset.resourceAddress); + } + activeAssets.clear(); + + for (auto &mapping : assetsMapping) + Deallocate(mapping.second); + assetsMapping.clear(); + + binaryStorage.clear(); + mapMeshesStorage.clear(); + shadersStorage.clear(); + materialsStorage.clear(); + + LOG(INFO, "Asset Streaming is released"); + isRunning.store(false); + } + + private: + IFileSystem *diskSystem; + + std::vector activeAssets; + std::unordered_map assetsIdMapping; + std::unordered_map assetsMapping; + std::vector freeAssetSlots; + std::vector loadingEntries; + + std::vector binaryStorage; + std::vector savesStorage; + std::vector mapMeshesStorage; + std::vector shadersStorage; + std::vector materialsStorage; + + void LoadCmd(AssetStreamCommand &command) + { + LOG(INFO, "LOAD command: [%hs]", command.targetPath.generic_u8string().c_str()); + + /* TODO: process path to select FS */ + /* TODO: select between async load and sync job task */ + + //Async load of full file without mmap in one thread + FileHandle &file = diskSystem->Open(command.targetPath, IFileSystem::FILE_OPEN_READ); + + diskSystem->ReadAsync(file, static_cast(file.size), IFileSystem::FILE_READ_SEQUENTIAL); + + AssetHandle* handle = Allocate(); + AssetInfo asset(nullptr); + asset.type = command.targetType; + + std::size_t assetPos = 0; + if (freeAssetSlots.size() > 0) + { + assetPos = freeAssetSlots.back(); + Deallocate(activeAssets[assetPos].resourceAddress); + activeAssets[assetPos] = std::move(asset); + freeAssetSlots.pop_back(); + } + else + { + activeAssets.push_back(std::move(asset)); + assetPos = activeAssets.size() - 1; + } + handle->slot = assetPos; + auto assetPath = command.targetPath.generic_u8string(); + std::uint32_t assetId = assetsIdMapping[command.targetPath] = + XXH32(assetPath.data(), assetPath.size(), ASSETS_HASH_SPACE); + handle->id = assetId; + assetsMapping[assetId] = handle; + + AssetLoadingEntry loadingEntry { + .handle = *handle, + .file = &file, + .fileOwner = diskSystem + }; + loadingEntries.push_back(loadingEntry); + + command.type = AssetStreamCommand::COMPLETED; + } + + void FindCmd(AssetStreamCommand &command) + { + std::uint32_t id = command.targetId; + if (id == AssetHandle::INVALID_ASSET_ID) + { + std::unordered_map::iterator idMapping = assetsIdMapping.find(command.targetPath); + if (idMapping == assetsIdMapping.end()) + return; + id = idMapping->second; + } + + std::unordered_map::iterator assetMapping = assetsMapping.find(id); + + if (assetMapping == assetsMapping.end()) + return; + + if (command.out != nullptr) + command.out->store(assetMapping->second); + + command.type = AssetStreamCommand::COMPLETED; + } + + void GetCmd(AssetStreamCommand &command) + { + if (activeAssets.size() <= command.target.slot) + return; + if (!activeAssets[command.target.slot].isReady) + return; + + if (command.out != nullptr) + command.out->store(activeAssets[command.target.slot].resourceAddress->resource); + + command.type = AssetStreamCommand::COMPLETED; + } + + template void FinishLoadConstruct(AssetLoadingEntry &loaded, std::vector &storage) + { + T* resource = Allocate(loaded.file->data, loaded.file->size); + storage.push_back(resource); + Redirect(loaded.handle, storage.back()); + } + + template void FinishLoadPlain(AssetLoadingEntry &loaded, std::vector &storage) + { + T* resource = Allocate(); + if (loaded.file->size < sizeof(T)) + LOG(CRITICAL, "File size is less than needed for asset of type: %d", typeid(T).name()); + std::memcpy(resource, loaded.file->data, sizeof(T)); + storage.push_back(resource); + Redirect(loaded.handle, storage.back()); + } + + template void ClearStorage(std::vector &storage) + { + for (T* &resource : storage) + { + if (resource != nullptr) + Deallocate(resource); + } + storage.clear(); + } + }; +} diff --git a/engine/modules/Client.cppm b/engine/modules/Client.cppm new file mode 100644 index 0000000..b623526 --- /dev/null +++ b/engine/modules/Client.cppm @@ -0,0 +1,51 @@ +module; + +#include + +export module Client; +import worker; +import GameData; +import DataChannel; +import AssetManager; + +export +{ + struct ClientCommand : public ee_utils::WorkerCommand + { + enum Type : std::uint8_t + { + NONE, + + SEND, + + COMPLETED + }; + }; + + class Client final : public ee_utils::ThreadedWorker + { + public: + Client(); + ~Client(); + void Init(); + + //void Send(); -> Request(SEND) + + const IDataChannel* GetConnection(); + void ConnectServer(); + + void LoadSave(const AssetHandle save); + + protected: + void Update() override; + void Release() override; + + private: + NetworkChannel *networkConnection = nullptr; + AssetHandle save; + + void SendCmd(ClientCommand &command); + + void ViewModelSubject(ee_data::Subject subject); + }; +} \ No newline at end of file diff --git a/engine/modules/DataChannel.cppm b/engine/modules/DataChannel.cppm new file mode 100644 index 0000000..d173768 --- /dev/null +++ b/engine/modules/DataChannel.cppm @@ -0,0 +1,24 @@ +module; + +export module DataChannel; + +export +{ + class IDataChannel + { + public: + // virtual void Request() = 0; + // virtual void Listen() = 0; + // virtual void Mute() = 0; + }; + + class NetworkChannel final : public IDataChannel + { + + }; + + class ThreadChannel final : public IDataChannel + { + + }; +} \ No newline at end of file diff --git a/engine/modules/Engine.cppm b/engine/modules/Engine.cppm new file mode 100644 index 0000000..8fcb8d8 --- /dev/null +++ b/engine/modules/Engine.cppm @@ -0,0 +1,59 @@ +module; + +#include + +export module Engine; + export import Render; + export import Input; + export import AssetManager; + export import Client; + +import allocator; +import worker; + +export +{ + class Engine + { + public: + inline static GLFWwindow *window; + inline static ee_engine::IInput *input; + inline static AssetManager *assetManager; + inline static ee_engine::IRenderer *renderer; + inline static Client *client; + + static void Shutdown() + { + if (input != nullptr) + Deallocate(input); + + if (renderer != nullptr) + { + renderer->Shutdown(); + Deallocate(renderer); + } + renderer = nullptr; + + WaitThreadShutdown(assetManager); + WaitThreadShutdown(client); + + glfwDestroyWindow(window); + glfwTerminate(); + } + + template + static void WaitThreadShutdown(T* &thread) + { + if (thread != nullptr) + { + thread->Shutdown(); + while(thread->isRunning.load()) {} + Deallocate(thread); + } + thread = nullptr; + } + + private: + Engine(); + }; +} \ No newline at end of file diff --git a/engine/modules/FileSystem.cppm b/engine/modules/FileSystem.cppm new file mode 100644 index 0000000..484794e --- /dev/null +++ b/engine/modules/FileSystem.cppm @@ -0,0 +1,72 @@ +module; + +#include +#include +#include +#include +#include + +export module FileSystem; + +export +{ + struct FileHandle { + std::size_t id = 0; + + std::size_t size = 0; + std::size_t bufferSize = 0; + std::uint8_t *data = nullptr; + std::uint8_t *buffer = nullptr; + + #ifndef NDEBUG + std::filesystem::path debugPath; + #endif + + #ifdef _WIN32 + HANDLE win32Handle = INVALID_HANDLE_VALUE; + OVERLAPPED overlapped; + #endif + + #ifdef __linux__ + #endif + }; + + class IFileSystem { + public: + inline static constexpr std::uint32_t FILE_OPEN_NONE = 0; + inline static constexpr std::uint32_t FILE_OPEN_READ = (1 << 0); + inline static constexpr std::uint32_t FILE_OPEN_WRITE = (1 << 1); + inline static constexpr std::uint32_t FILE_OPEN_MMAP = (1 << 2); + inline static constexpr std::uint32_t FILE_READ_SEQUENTIAL = 0; + inline static constexpr std::uint32_t FILE_READ_RANDOM_ACCESS = (1 << 0); + + virtual FileHandle &Open(const std::filesystem::path &path, const std::uint32_t flags) = 0; + + virtual void ReadAsync(FileHandle &file, const std::uint32_t bufferSize, const std::uint32_t flags) = 0; + + virtual bool PollReady(FileHandle &file) = 0; + + virtual void Close(FileHandle &file) = 0; + + virtual ~IFileSystem(); + + protected: + std::vector activeFiles; + std::vector failedFiles; + std::vector freeFileSlots; + }; + + class NativeFileSystem : public IFileSystem { + public: + FileHandle &Open(const std::filesystem::path &path, const std::uint32_t flags) override; + + void ReadAsync(FileHandle &file, const std::uint32_t bufferSize, std::uint32_t flags) override; + + bool PollReady(FileHandle &file) override; + + void Close(FileHandle &file) override; + + private: + + }; +} \ No newline at end of file diff --git a/engine/modules/GLFWInput.cppm b/engine/modules/GLFWInput.cppm new file mode 100644 index 0000000..68c6a0d --- /dev/null +++ b/engine/modules/GLFWInput.cppm @@ -0,0 +1,16 @@ +module; + +#include + +export module GLFWInput; +import Input; + +export { + class GLFWInput : public ee_engine::IInput + { + public: + GLFWInput(ee_engine::InputHandlers handlers); + + void Poll() override; + }; +} \ No newline at end of file diff --git a/engine/src/Actions.cpp b/engine/src/Actions.cpp index 76da11e..1d5a755 100644 --- a/engine/src/Actions.cpp +++ b/engine/src/Actions.cpp @@ -1,7 +1,10 @@ -#include "Actions.hpp" -#include "Engine.hpp" +module; + #include +module Actions; +import Engine; + ee_engine::InputHandlers Actions::mappings { .zooming = Zoom, .mapScroll = MapScroll diff --git a/engine/src/AssetManager.cpp b/engine/src/AssetManager.cpp deleted file mode 100644 index ecb2441..0000000 --- a/engine/src/AssetManager.cpp +++ /dev/null @@ -1,344 +0,0 @@ -#include "compile_config.hpp" -#include "AssetManager.hpp" -#include -#include "Logger.h" -#include -#include -#include - - -AssetInfo::AssetInfo(void *resource) -{ - this->resourceAddress = Allocate(); - this->resourceAddress->resource.store(resource); -} - -AssetInfo::AssetInfo(AssetInfo&& other) noexcept : - type(other.type), - resourceAddress(other.resourceAddress) -{ - isReady.store(other.isReady.load(std::memory_order_relaxed), std::memory_order_relaxed); - - other.resourceAddress = nullptr; - other.isReady.store(false, std::memory_order_relaxed); -} - -AssetInfo& AssetInfo::operator=(AssetInfo&& other) noexcept -{ - if (this != &other) - { - type = other.type; - resourceAddress = other.resourceAddress; - isReady.store(other.isReady.load(std::memory_order_relaxed), std::memory_order_relaxed); - - other.resourceAddress = nullptr; - other.isReady.store(false, std::memory_order_relaxed); - } - return *this; -} - -void AssetManager::Redirect(AssetHandle &handle, void* resource) -{ - AssetInfo &asset = activeAssets[handle.slot]; - if (asset.resourceAddress == nullptr) - { - LOG(WARNING, "Attempt to redirect empty handle"); - return; - } - - if (asset.resourceAddress->resource.load() != nullptr) - { - void* oldResource = asset.resourceAddress->resource.exchange(nullptr, std::memory_order_acq_rel); - if (oldResource) - //Deallocate(asset.resourceAddress->resource.load()); - Deallocate(oldResource); - } - - asset.resourceAddress->resource.store(resource); -} - -void AssetManager::Free(AssetHandle &handle) -{ - AssetInfo &asset = activeAssets[handle.slot]; - Redirect(handle, nullptr); - Deallocate(asset.resourceAddress); - asset.resourceAddress = nullptr; - - freeAssetSlots.push_back(handle.slot); -} - -AssetManager::AssetManager() -{ - diskSystem = Allocate(); -} - -AssetManager::~AssetManager() -{ - Deallocate(diskSystem); -} - -void AssetManager::Request(const AssetStreamCommand &command) -{ - commands.push(command); -} - -void AssetManager::Request(const AssetStreamCommand::Type &type) -{ - commands.push(AssetStreamCommand {.type = type}); -} - -void AssetManager::LoadAsync(ee_assets::AssetType type, const std::filesystem::path &path) -{ - AssetStreamCommand command { - .type = AssetStreamCommand::LOAD, - .targetPath = path, - .targetType = type - }; - Request(command); -} - -AssetHandle& AssetManager::Find(const std::filesystem::path &path) -{ - std::atomic result; - AssetStreamCommand command { - .type = AssetStreamCommand::FIND, - .targetPath = path, - .out = &result - }; - Request(command); - while (command.out->load() == nullptr); - return *reinterpret_cast(command.out->load()); -} -AssetHandle& AssetManager::Find(const uint32_t &id) -{ - std::atomic result; - AssetStreamCommand command { - .type = AssetStreamCommand::FIND, - .targetId = id, - .out = &result - }; - Request(command); - while (command.out->load() == nullptr); - return *reinterpret_cast(command.out->load()); -} - -void AssetManager::Start() -{ - if (isRunning) throw std::logic_error("Asset Streaming can be started only once"); - - isRunning.store(true); - streamingThread = std::jthread([this](std::stop_token stop) { - this->stoken = &stop; - Threading(); - }); -} - -void AssetManager::Shutdown() -{ - streamingThread.request_stop(); -} - -void AssetManager::Threading() -{ - Logger::trace->Register_Thread(L"Asset Stream", 0); - LOG(INFO, "Asset Streaming thread started"); - - Loop(); - - Release(); -} - -void AssetManager::Loop() -{ - AssetStreamCommand commandBuffer; - std::vector incompleteCommands; - while (!stoken->stop_requested()) - { - while (commands.pop(commandBuffer)) - { - ProcessCommand(commandBuffer); - if (commandBuffer.type != AssetStreamCommand::COMPLETED) - incompleteCommands.push_back(commandBuffer); - } - for (AssetStreamCommand &command : incompleteCommands) - { - commands.push(command); - } - incompleteCommands.clear(); - - // TODO: FinishLoadTasks() - for (AssetLoadingEntry &entry : loadingEntries) - { - bool isReady = entry.fileOwner->PollReady(*entry.file); - if (isReady) - { - AssetInfo& asset = activeAssets[entry.handle.slot]; - - switch (asset.type) - { - case ee_assets::MAP_MESH: - FinishLoadConstruct(entry, mapMeshesStorage); - break; - case ee_assets::SAVE: - FinishLoadConstruct(entry, savesStorage); - break; - - case ee_assets::SHADER: - FinishLoadConstruct(entry, shadersStorage); - break; - case ee_assets::MATERIAL: - FinishLoadPlain(entry, materialsStorage); - break; - case ee_assets::IMAGE: - break; - - case ee_assets::BINARY: - default: - FinishLoadConstruct(entry, binaryStorage); - break; - } - - entry.fileOwner->Close(*entry.file); -#ifndef NDEBUG - LOG(INFO, "Asset loaded: [%hs]", entry.file->debugPath.generic_u8string().c_str()); -#endif - entry.file = nullptr; - asset.isReady.store(true); - } - } - - std::erase_if(loadingEntries, [](const AssetLoadingEntry &entry) { - return entry.file == nullptr; - }); - } -} -void AssetManager::ProcessCommand(AssetStreamCommand &command) -{ - // TODO: method for each command - switch(command.type) - { - case AssetStreamCommand::LOAD: - { - LOG(INFO, "LOAD command: [%hs]", command.targetPath.generic_u8string().c_str()); - - /* TODO: process path to select FS */ - /* TODO: select between async load and sync job task */ - - //Async load of full file without mmap in one thread - FileHandle &file = diskSystem->Open(command.targetPath, FILE_OPEN_READ); - - diskSystem->ReadAsync(file, static_cast(file.size), FILE_READ_SEQUENTIAL); - - AssetHandle* handle = Allocate(); - AssetInfo asset(nullptr); - asset.type = command.targetType; - - size_t assetPos = 0; - if (freeAssetSlots.size() > 0) - { - assetPos = freeAssetSlots.back(); - Deallocate(activeAssets[assetPos].resourceAddress); - activeAssets[assetPos] = std::move(asset); - freeAssetSlots.pop_back(); - } - else - { - activeAssets.push_back(std::move(asset)); - assetPos = activeAssets.size() - 1; - } - handle->slot = assetPos; - auto assetPath = command.targetPath.generic_u8string(); - uint32_t assetId = assetsIdMapping[command.targetPath] = - XXH32(assetPath.data(), assetPath.size(), ASSETS_HASH_SPACE); - handle->id = assetId; - assetsMapping[assetId] = handle; - - AssetLoadingEntry loadingEntry { - .handle = *handle, - .file = &file, - .fileOwner = diskSystem - }; - loadingEntries.push_back(loadingEntry); - - command.type = AssetStreamCommand::COMPLETED; - break; - } - - case AssetStreamCommand::FIND: - { - uint32_t id = command.targetId; - if (id == INVALID_ASSET_ID) - { - std::unordered_map::iterator idMapping = assetsIdMapping.find(command.targetPath); - if (idMapping == assetsIdMapping.end()) - break; - id = idMapping->second; - } - - std::unordered_map::iterator assetMapping = assetsMapping.find(id); - - if (assetMapping == assetsMapping.end()) - break; - - command.out->store(assetMapping->second); - - command.type = AssetStreamCommand::COMPLETED; - break; - } - - case AssetStreamCommand::GET: - { - if (activeAssets.size() <= command.target.slot) - break; - if (!activeAssets[command.target.slot].isReady) - break; - - command.out->store(activeAssets[command.target.slot].resourceAddress->resource); - - command.type = AssetStreamCommand::COMPLETED; - break; - } - - default: - { - LOG(WARNING, "Unhandled command. Type id: %d", command.type); - break; - } - } -} - -void AssetManager::Release() -{ - for (AssetInfo &asset : activeAssets) - { - if (asset.resourceAddress->resource.load() != nullptr) - { - void* resource = asset.resourceAddress->resource.exchange(nullptr, std::memory_order_acq_rel); - if (resource) - Deallocate(resource); - } - Deallocate(asset.resourceAddress); - } - activeAssets.clear(); - - for (auto &mapping : assetsMapping) - Deallocate(mapping.second); - assetsMapping.clear(); - - binaryStorage.clear(); - mapMeshesStorage.clear(); - shadersStorage.clear(); - materialsStorage.clear(); - - LOG(INFO, "Asset Streaming is released"); - isRunning.store(false); -} - -void AssetManager::LoadDir(ee_assets::AssetType type, const std::filesystem::path &path) -{ - for (const std::filesystem::directory_entry &entry : std::filesystem::directory_iterator(path)) - { - if (entry.is_directory()) continue; - LoadAsync(type, entry.path()); - } -} \ No newline at end of file diff --git a/engine/src/Client.cpp b/engine/src/Client.cpp new file mode 100644 index 0000000..765b1db --- /dev/null +++ b/engine/src/Client.cpp @@ -0,0 +1,93 @@ +module; + +#include "Logger.h" +#include +#include +#include + +module Client; +import allocator; +import MapView; +import Engine; + +Client::Client() : ee_utils::ThreadedWorker(L"Client") +{ + commandsMapping[ClientCommand::SEND] = MAP_WORKER_COMMAND(ClientCommand, SendCmd); + +} + +void Client::Init() +{ + if (Engine::renderer == nullptr || !Engine::renderer->isReady()) + { + LOG(CRITICAL, "Renderer is not ready. Client cannot be created"); + throw std::logic_error("Renderer is not ready"); + } + + // TEST + ee_assets::AssetSave &asset = Engine::assetManager->Get(save); + ViewModelSubject(asset.content.subjects[0]); + ViewModelSubject(asset.content.subjects[1]); +} + +const IDataChannel* Client::GetConnection() +{ + return networkConnection; +} + +void Client::ConnectServer() +{ + if (networkConnection != nullptr) + Deallocate(networkConnection); + + networkConnection = Allocate(); +} + +void Client::LoadSave(const AssetHandle save) +{ + this->save = save; +} + +void Client::Update() +{ + +} + +void Client::Release() +{ + +} + + +void Client::SendCmd(ClientCommand &command) +{ + + + command.type = ClientCommand::COMPLETED; +} + + +void Client::ViewModelSubject(ee_data::Subject subject) +{ + for (const std::uint32_t region : subject.regions) + { + ee_engine::ProvinceSSBO vm { + .regionId = region, + .color = subject.color + }; + + ee_engine::RendererCommand cmd; + cmd.type = ee_engine::RendererCommand::UPDATE_REGION; + cmd.region = {.id = region, .data = vm}; + + Engine::renderer->Request(cmd); + } +} + + + +Client::~Client() +{ + if (networkConnection != nullptr) + Deallocate(networkConnection); +} \ No newline at end of file diff --git a/engine/src/Engine.cpp b/engine/src/Engine.cpp deleted file mode 100644 index f4a47b8..0000000 --- a/engine/src/Engine.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "Engine.hpp" -#include - -GLFWwindow* Engine::window; - -ee_engine::IInput* Engine::input; -AssetManager* Engine::assetManager; -ee_engine::IRenderer* Engine::renderer; - -void Engine::Shutdown() -{ - if (input != nullptr) - Deallocate(input); - - if (renderer != nullptr) - { - renderer->Shutdown(); - Deallocate(renderer); - } - renderer = nullptr; - - if (assetManager != nullptr) - { // Wait for asset manager to clean and shutdown - assetManager->Shutdown(); - while(assetManager->isRunning.load()) {} - Deallocate(assetManager); - } - assetManager = nullptr; - - glfwDestroyWindow(window); - glfwTerminate(); -} \ No newline at end of file diff --git a/engine/src/FileSystem.cpp b/engine/src/FileSystem.cpp index 06b6fb2..ef66758 100644 --- a/engine/src/FileSystem.cpp +++ b/engine/src/FileSystem.cpp @@ -1,6 +1,13 @@ -#include "FileSystem.hpp" +module; + #include "Logger.h" -#include +#include +#include +#include + +module FileSystem; +import allocator; + IFileSystem::~IFileSystem() { @@ -12,13 +19,13 @@ IFileSystem::~IFileSystem() #ifdef _WIN32 -FileHandle& NativeFileSystem::Open(const std::filesystem::path &path, const uint32_t flags) +FileHandle& NativeFileSystem::Open(const std::filesystem::path &path, const std::uint32_t flags) { FileHandle* result = Allocate(); - #ifndef NDEBUG +#ifndef NDEBUG result->debugPath = path; - #endif +#endif DWORD createFileMode = 0; @@ -28,13 +35,13 @@ FileHandle& NativeFileSystem::Open(const std::filesystem::path &path, const uint createFileMode |= GENERIC_WRITE; HANDLE file = CreateFileW( - path.c_str(), - createFileMode, - NULL, - NULL, - OPEN_EXISTING, - FILE_FLAG_OVERLAPPED, - NULL + path.c_str(), + createFileMode, + NULL, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL ); if (file == INVALID_HANDLE_VALUE) @@ -51,7 +58,7 @@ FileHandle& NativeFileSystem::Open(const std::filesystem::path &path, const uint if (freeFileSlots.size() > 0) { - size_t pos = freeFileSlots.back(); + std::size_t pos = freeFileSlots.back(); result->id = pos; activeFiles[pos] = result; freeFileSlots.pop_back(); @@ -65,20 +72,20 @@ FileHandle& NativeFileSystem::Open(const std::filesystem::path &path, const uint return *result; } -void NativeFileSystem::ReadAsync(FileHandle &file, const uint32_t bufferSize, const uint32_t flags) +void NativeFileSystem::ReadAsync(FileHandle &file, const std::uint32_t bufferSize, const std::uint32_t flags) { file.overlapped = { - .hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr) + .hEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr) }; - file.buffer = AllocateArray(bufferSize); + file.buffer = AllocateArray(bufferSize); file.bufferSize = bufferSize; BOOL isSync = ReadFile( - file.win32Handle, - file.buffer, - bufferSize, - NULL, - &file.overlapped + file.win32Handle, + file.buffer, + bufferSize, + NULL, + &file.overlapped ); if (isSync || GetLastError() != ERROR_IO_PENDING) @@ -116,7 +123,7 @@ bool NativeFileSystem::PollReady(FileHandle &file) return false; } } - + return true; } diff --git a/engine/src/GLFWInput.cpp b/engine/src/GLFWInput.cpp index 68e9028..482a629 100644 --- a/engine/src/GLFWInput.cpp +++ b/engine/src/GLFWInput.cpp @@ -1,6 +1,10 @@ -#include "GLFWInput.hpp" -#include "Engine.hpp" +module; + #include "Logger.h" +#include + +module GLFWInput; +import Engine; GLFWInput::GLFWInput(ee_engine::InputHandlers handlers) : ee_engine::IInput(handlers) { @@ -8,7 +12,7 @@ GLFWInput::GLFWInput(ee_engine::InputHandlers handlers) : ee_engine::IInput(hand glfwSetScrollCallback(Engine::window, [](GLFWwindow *window, double dx, double dy) { reinterpret_cast(glfwGetWindowUserPointer(window))-> - handlers.zooming(static_cast(dx), static_cast(dy)); + handlers.zooming(static_cast(dx), static_cast(dy)); }); LOG(INFO, "Input mappings initialized"); diff --git a/engine/src/main.cpp b/engine/src/main.cpp index 0116605..e8a91aa 100644 --- a/engine/src/main.cpp +++ b/engine/src/main.cpp @@ -1,98 +1,114 @@ +import allocator; + +import Engine; +import Actions; +import MagnumRender; +import GLFWInput; + #include "Logger.h" - -#include -#include - #include "compile_config.hpp" -#include "GLFWInput.hpp" -#include "Actions.hpp" -#include "Engine.hpp" - #include +#include IP7_Trace* Logger::trace; int main(int argc, char **argv) { - // Setup P7 logger - IP7_Client *p7client = P7_Create_Client(P7_SINK P7_LOGS_PATH); - P7_Set_Crash_Handler(); - Logger::trace = P7_Create_Trace(p7client, L"TC 1"); - Logger::trace->Register_Thread(L"Main", 0); + // Setup P7 logger + IP7_Client *p7client = P7_Create_Client(P7_SINK P7_LOGS_PATH); + P7_Set_Crash_Handler(); + Logger::trace = P7_Create_Trace(p7client, L"TC 1"); + Logger::trace->Register_Thread(L"Main", 0); - LOG(INFO, "Etredia Empires, v%d.%d.%d", MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION); + LOG(INFO, "Etredia Empires, v%d.%d.%d", MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION); - // Setup GLFW - glfwInit(); - - // Vulkan only - // glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + // Setup GLFW + glfwInit(); - GLFWwindow *window = glfwCreateWindow(800, 600, "Etredia Empires", nullptr, nullptr); + // Vulkan only + // glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - if (!window) - LOG(CRITICAL, "GLFW Window failed"); - else LOG(INFO, "GLFW Window created"); + GLFWwindow *window = glfwCreateWindow(800, 600, "Etredia Empires", nullptr, nullptr); - glfwMakeContextCurrent(window); - Engine::window = window; + if (!window) + LOG(CRITICAL, "GLFW Window failed"); + else LOG(INFO, "GLFW Window created"); - // Setup Asset Manager - Engine::assetManager = Allocate(); - Engine::assetManager->Start(); - Engine::assetManager->LoadDir(ee_assets::SHADER, "assets/shaders"); - Engine::assetManager->LoadDir(ee_assets::MATERIAL, "assets/materials"); + glfwMakeContextCurrent(window); + Engine::window = window; - // Load assets - Engine::assetManager->LoadAsync(ee_assets::MAP_MESH, "assets/map/states.map"); - Engine::assetManager->LoadAsync(ee_assets::SAVE, "assets/scenarios/empires.save"); + // Setup Asset Manager TODO: builder + Engine::assetManager = Allocate(); + Engine::assetManager->Start(); + Engine::assetManager->LoadDir(ee_assets::SHADER, "assets/shaders"); + Engine::assetManager->LoadDir(ee_assets::MATERIAL, "assets/materials"); - // Setup input manager TODO: builder - Engine::input = Allocate(Actions::mappings); + // Load assets + Engine::assetManager->LoadAsync(ee_assets::MAP_MESH, "assets/map/regions.map"); + Engine::assetManager->LoadAsync(ee_assets::SAVE, "assets/scenarios/empires.save"); - // Setup renderer TODO: builder - Engine::renderer = reinterpret_cast(Allocate(window)); - - ee_assets::AssetMapMesh &states = Engine::assetManager->FindOnce("assets/map/states.map"); - Engine::renderer->RegisterMapMesh(&states.content); - - //TODO: ShaderRefs builder from set of AssetMaterial - ee_assets::AssetMaterial &provincesMaterial = - Engine::assetManager->FindOnce("assets/materials/provinces.mat"); - ee_assets::AssetShader &vertProv = Engine::assetManager->FindOnce(provincesMaterial.vertexShaderAssetID); - ee_assets::AssetShader &fragProv = Engine::assetManager->FindOnce(provincesMaterial.fragmentShaderAssetID); - Engine::renderer->RegisterMaterials({ - .vertProvinces = &vertProv, - .fragProvinces = &fragProv - }); - - Engine::renderer->Init(); - Engine::renderer->SetCamera({ - //.position = {1000.0f, 1000.0f}, - .zoom = 2000.0f - }); - - glfwSetFramebufferSizeCallback(window, [](GLFWwindow *window, int width, int height) { - Engine::renderer->ResizeWindow(width, height); - }); + // Setup input manager TODO: builder + Engine::input = Allocate(Actions::mappings); - // Game loop - while(!glfwWindowShouldClose(window)) - { - Engine::renderer->Draw(); + // Setup renderer TODO: builder + Engine::renderer = reinterpret_cast(Allocate(window)); - glfwSwapBuffers(window); - Engine::input->Poll(); - glfwPollEvents(); - } + ee_assets::AssetMapMesh &states = Engine::assetManager->FindOnce("assets/map/regions.map"); + Engine::renderer->RegisterMapMesh(&states.content); - // Free memory - LOG(INFO, "Exit..."); - Engine::Shutdown(); - //TODO: check Unregister in other threads and make threaded module base class - Logger::trace->Unregister_Thread(0); - Logger::trace->Release(); - p7client->Release(); + //TODO: ShaderRefs builder from set of AssetMaterial + ee_assets::AssetMaterial &provincesMaterial = + Engine::assetManager->FindOnce("assets/materials/provinces.mat"); + ee_assets::AssetShader &vertProv = Engine::assetManager->FindOnce(provincesMaterial.vertexShaderAssetID); + ee_assets::AssetShader &fragProv = Engine::assetManager->FindOnce(provincesMaterial.fragmentShaderAssetID); + Engine::renderer->RegisterMaterials({ + .vertProvinces = &vertProv, + .fragProvinces = &fragProv + }); - return 0; -} \ No newline at end of file + Engine::renderer->Init(); + Engine::renderer->SetCamera({ + //.position = {1000.0f, 1000.0f}, + .zoom = 2000.0f + }); + + glfwSetFramebufferSizeCallback(window, [](GLFWwindow *window, int width, int height) { + Engine::renderer->ResizeWindow(width, height); + }); + + // Setup Client TODO: builder + Engine::client = Allocate(); + AssetHandle save = Engine::assetManager->Find("assets/scenarios/empires.save"); + Engine::client->LoadSave(save); + Engine::client->Init(); + Engine::client->Start(); + + // Game loop + ee_engine::RendererCommand renderCmdBuffer; std::vector renderIncompletesBuffer; + while(!glfwWindowShouldClose(window)) + { + Engine::renderer->ProcessQueue(renderCmdBuffer, renderIncompletesBuffer); + Engine::renderer->Draw(); + + glfwSwapBuffers(window); + Engine::input->Poll(); + glfwPollEvents(); + } + + // Free memory + LOG(INFO, "Exit..."); + Engine::Shutdown(); + //TODO: check Unregister in other threads and make threaded module base class + Logger::trace->Unregister_Thread(0); + Logger::trace->Release(); + p7client->Release(); + + return 0; +} + +// TODO: Rename states to regions in old sources +// TODO: Remove unneccesary address providing like (const type &arg) for small primitives +// TODO: Use CRTP where possible in classes with virtual/override +// TODO: Use final in classes with override +// TODO: Implementations of API as partition modules +// TODO: Leaks detection \ No newline at end of file diff --git a/p7lib/CMakeLists.txt b/p7lib/CMakeLists.txt index 4ab7ed0..f1dabdc 100644 --- a/p7lib/CMakeLists.txt +++ b/p7lib/CMakeLists.txt @@ -53,7 +53,7 @@ else() enable_cxx_compiler_flag_if_supported("-Wno-long-long") enable_cxx_compiler_flag_if_supported("-Wno-missing-field-initializers") enable_cxx_compiler_flag_if_supported("-Wno-unknown-pragmas") - enable_cxx_compiler_flag_if_supported("-fPIC") + #enable_cxx_compiler_flag_if_supported("-fPIC") macro(set_ide_folder _project_name) endmacro() diff --git a/p7lib/Sources/CMakeLists.txt b/p7lib/Sources/CMakeLists.txt index 23d6656..e4169d4 100644 --- a/p7lib/Sources/CMakeLists.txt +++ b/p7lib/Sources/CMakeLists.txt @@ -36,11 +36,11 @@ if(P7_BUILD_SHARED) target_link_libraries(${PROJECT_NAME}-shared ${P7_PLATFORM_LIBS}) endif() -set_property(TARGET ${PROJECT_NAME} PROPERTY POSITION_INDEPENDENT_CODE ON) +#set_property(TARGET ${PROJECT_NAME} PROPERTY POSITION_INDEPENDENT_CODE ON) -if(P7_BUILD_SHARED) - set_property(TARGET ${PROJECT_NAME}-shared PROPERTY POSITION_INDEPENDENT_CODE ON) -endif() +#if(P7_BUILD_SHARED) +# set_property(TARGET ${PROJECT_NAME}-shared PROPERTY POSITION_INDEPENDENT_CODE ON) +#endif() target_include_directories(${PROJECT_NAME} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../Headers/") diff --git a/renderers/magnum-renderer/CMakeLists.txt b/renderers/magnum-renderer/CMakeLists.txt index 55e3757..0a64544 100644 --- a/renderers/magnum-renderer/CMakeLists.txt +++ b/renderers/magnum-renderer/CMakeLists.txt @@ -1,23 +1,6 @@ -cmake_minimum_required (VERSION 3.8) +include(${CMAKE_SOURCE_DIR}/cmake/library.cmake) -if (POLICY CMP0141) - cmake_policy(SET CMP0141 NEW) - set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") -endif() - -set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -project (magnum-renderer) - -# List sources - -file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS - "src/*.cpp" - "src/*.c" - "include/*.hpp" - "include/*.h" -) +set(LIB magnum-renderer) # Find dependencies @@ -38,20 +21,14 @@ find_package(Magnum REQUIRED # Link library -add_library(${PROJECT_NAME} ${SOURCES}) +add_library_target(${LIB}) -target_link_libraries(${PROJECT_NAME} PUBLIC engine-api) -target_link_libraries(${PROJECT_NAME} PUBLIC utils) +target_link_libraries(${LIB} PUBLIC engine-api) +target_link_libraries(${LIB} PUBLIC utils) -target_link_libraries(${PROJECT_NAME} PUBLIC p7) -target_link_libraries(${PROJECT_NAME} PRIVATE +target_link_libraries(${LIB} PUBLIC p7) +target_link_libraries(${LIB} PRIVATE Magnum::GL Magnum::GlfwApplication Magnum::Shaders - Magnum::Magnum) - -target_include_directories(${PROJECT_NAME} PUBLIC include/) - -if (CMAKE_VERSION VERSION_GREATER 3.12) - set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) -endif() \ No newline at end of file + Magnum::Magnum) \ No newline at end of file diff --git a/renderers/magnum-renderer/include/ee_magnum/Materials.hpp b/renderers/magnum-renderer/modules/Materials.cppm similarity index 57% rename from renderers/magnum-renderer/include/ee_magnum/Materials.hpp rename to renderers/magnum-renderer/modules/Materials.cppm index 004531c..a23fd3d 100644 --- a/renderers/magnum-renderer/include/ee_magnum/Materials.hpp +++ b/renderers/magnum-renderer/modules/Materials.cppm @@ -1,39 +1,42 @@ -#pragma once +module; -#undef min -#undef max +#define NOMINMAX #include #include #include #include -#include +#include +#include -#define PROVINCES_SSBO_BINDING 0 -#define CAMERA_UNIFORM 1 -//TODO: push constant -#define TRANSFORM_UNIFORM 2 -#define PROVINCES_ID_UNIFORM 3 +export module Materials; using namespace Magnum; -namespace ee_magnum +export namespace ee_magnum { class BaseMaterial : public GL::AbstractShaderProgram { public: + inline static constexpr std::int32_t CAMERA_BINDING = 1; + //TODO: push constant + inline static constexpr std::int32_t TRANSFORM_BINDING = 2; + void setModel(const Matrix4 &model); void setViewProjection(const Matrix4 &vewProjection); - + protected: explicit BaseMaterial(const std::string &vertSrc, const std::string &fragSrc); }; - + class ProvinceMaterial : public BaseMaterial { public: + inline static constexpr std::int32_t PROVINCES_DATA_BINDING = 0; + inline static constexpr std::int32_t PROVINCES_ID_BINDING = 3; + explicit ProvinceMaterial(const std::string &vertSrc, const std::string &fragSrc); - - void setId(const uint32_t &id); + + void setId(const std::uint32_t &id); }; -} \ No newline at end of file +} diff --git a/renderers/magnum-renderer/include/ee_magnum/Renderer.hpp b/renderers/magnum-renderer/modules/Render.cppm similarity index 68% rename from renderers/magnum-renderer/include/ee_magnum/Renderer.hpp rename to renderers/magnum-renderer/modules/Render.cppm index d48a14f..d2d7b65 100644 --- a/renderers/magnum-renderer/include/ee_magnum/Renderer.hpp +++ b/renderers/magnum-renderer/modules/Render.cppm @@ -1,47 +1,51 @@ -#pragma once +module; -#undef min -#undef max +#define NOMINMAX #include #include #include #include +#include -#include "Materials.hpp" -#include +export module MagnumRender; +import MapView; +import Materials; +import Render; using namespace Magnum; -namespace ee_magnum +export namespace ee_magnum { - class MagnumRenderer : public ee_engine::IRenderer + class MagnumRenderer final : public ee_engine::IRenderer { public: MagnumRenderer(GLFWwindow *window); ~MagnumRenderer(); - + void Init() override; void Shutdown() override; - + protected: void Clear() override; void DrawMap() override; void DrawUI() override; - + void ApplyCamera() override; - + + virtual void UpdateProvinces(const std::size_t index, const std::vector &data) override; + private: Platform::GLContext context; - + std::vector provinceMeshes; GL::Buffer provinceSSBO; ProvinceMaterial *provinceMaterial; - + void ValidateSupport(); void LoadShaders(); void LoadProvinces(); - + void ApplyMapMVP(); }; } \ No newline at end of file diff --git a/renderers/magnum-renderer/src/Materials.cpp b/renderers/magnum-renderer/src/Material.cpp similarity index 72% rename from renderers/magnum-renderer/src/Materials.cpp rename to renderers/magnum-renderer/src/Material.cpp index b4cb02f..0cdc11a 100644 --- a/renderers/magnum-renderer/src/Materials.cpp +++ b/renderers/magnum-renderer/src/Material.cpp @@ -1,5 +1,17 @@ -#include +module; + +#define NOMINMAX + +#include +#include +#include +#include + #include "Logger.h" +#include +#include + +module Materials; ee_magnum::BaseMaterial::BaseMaterial(const std::string &vertSrc, const std::string &fragSrc) { @@ -16,18 +28,18 @@ ee_magnum::BaseMaterial::BaseMaterial(const std::string &vertSrc, const std::str attachShader(vert); attachShader(frag); - + link(); } void ee_magnum::BaseMaterial::setModel(const Matrix4 &m) { - setUniform(TRANSFORM_UNIFORM, m); + setUniform(TRANSFORM_BINDING, m); } void ee_magnum::BaseMaterial::setViewProjection(const Matrix4 &vp) { - setUniform(CAMERA_UNIFORM, vp); + setUniform(CAMERA_BINDING, vp); } ee_magnum::ProvinceMaterial::ProvinceMaterial(const std::string &vertSrc, const std::string &fragSrc): BaseMaterial(vertSrc, fragSrc) @@ -37,5 +49,5 @@ ee_magnum::ProvinceMaterial::ProvinceMaterial(const std::string &vertSrc, const void ee_magnum::ProvinceMaterial::setId(const uint32_t &id) { - setUniform(PROVINCES_ID_UNIFORM, id); -} \ No newline at end of file + setUniform(PROVINCES_ID_BINDING, id); +} diff --git a/renderers/magnum-renderer/src/Renderer.cpp b/renderers/magnum-renderer/src/Render.cpp similarity index 61% rename from renderers/magnum-renderer/src/Renderer.cpp rename to renderers/magnum-renderer/src/Render.cpp index 8648b86..85cbc0c 100644 --- a/renderers/magnum-renderer/src/Renderer.cpp +++ b/renderers/magnum-renderer/src/Render.cpp @@ -1,24 +1,33 @@ -#include "Logger.h" -#include "ee_utils/allocator.hpp" -#include +module; +#define NOMINMAX + +#include "Logger.h" + +#include +#include #include #include -#include #include #include #include +#include +#include +#include #include #include +module MagnumRender; +import allocator; + using namespace Math::Literals; ee_magnum::MagnumRenderer::MagnumRenderer(GLFWwindow *window) : IRenderer(window) { - ValidateSupport(); + ValidateSupport(); - LOG(INFO, "Renderer created"); + LOG(INFO, "Renderer created"); } void ee_magnum::MagnumRenderer::Init() @@ -28,6 +37,7 @@ void ee_magnum::MagnumRenderer::Init() LoadShaders(); LoadProvinces(); + _isReady = true; LOG(INFO, "Renderer initialized"); } @@ -39,7 +49,7 @@ void ee_magnum::MagnumRenderer::Clear() void ee_magnum::MagnumRenderer::DrawMap() { ApplyCamera(); - for (uint32_t i = 0; i < provinceMeshes.size(); i++) + for (std::uint32_t i = 0; i < provinceMeshes.size(); i++) { provinceMaterial->setId(i); provinceMaterial->draw(provinceMeshes[i]); @@ -48,12 +58,12 @@ void ee_magnum::MagnumRenderer::DrawMap() void ee_magnum::MagnumRenderer::DrawUI() { - + } void ee_magnum::MagnumRenderer::ValidateSupport() { - + } void ee_magnum::MagnumRenderer::ApplyCamera() @@ -67,11 +77,11 @@ void ee_magnum::MagnumRenderer::ApplyCamera() void ee_magnum::MagnumRenderer::LoadShaders() { provinceMaterial = Allocate(std::string( - reinterpret_cast(shaders.vertProvinces->content), - shaders.vertProvinces->size + reinterpret_cast(shaders.vertProvinces->content), + shaders.vertProvinces->size ) + '\0', std::string( - reinterpret_cast(shaders.fragProvinces->content), - shaders.fragProvinces->size + reinterpret_cast(shaders.fragProvinces->content), + shaders.fragProvinces->size )) + '\0'; LOG(INFO, "Shaders loaded"); @@ -80,36 +90,47 @@ void ee_magnum::MagnumRenderer::LoadShaders() void ee_magnum::MagnumRenderer::LoadProvinces() { std::vector provincesData; - for (auto& [state, provs]: mapMesh->states) + + std::size_t regionIndex = 0; + for (auto& [region, provs]: mapMesh->regions) { for (ee_engine::MapMesh::Province &province: provs) { GL::Mesh stateMesh; stateMesh.setPrimitive(GL::MeshPrimitive::Triangles) - .setCount(static_cast(province.indices.size())) - .addVertexBuffer(GL::Buffer{province.vertices}, 0, GL::Attribute<0, Magnum::Vector2>{}) - .setIndexBuffer(GL::Buffer{province.indices}, 0, GL::MeshIndexType::UnsignedShort); + .setCount(static_cast(province.indices.size())) + .addVertexBuffer(GL::Buffer{province.vertices}, 0, GL::Attribute<0, Magnum::Vector2>{}) + .setIndexBuffer(GL::Buffer{province.indices}, 0, GL::MeshIndexType::UnsignedShort); provinceMeshes.push_back(std::move(stateMesh)); ee_engine::ProvinceSSBO data { - .stateId = state, - .color = state + .regionId = region, + //.color = region + .color = 0xFFFFFF }; provincesData.push_back(data); } + + regionsMapping[region] = {.startIndex = regionIndex, .provincesCount = provs.size()}; + regionIndex += provs.size() * sizeof(ee_engine::ProvinceSSBO); } LOG(INFO, "Registered %d province meshes in renderer", provinceMeshes.size()); provinceSSBO.setTargetHint(GL::Buffer::TargetHint::ShaderStorage); provinceSSBO.setData(provincesData, GL::BufferUsage::DynamicDraw); - provinceSSBO.bind(GL::Buffer::Target::ShaderStorage, PROVINCES_SSBO_BINDING); + provinceSSBO.bind(GL::Buffer::Target::ShaderStorage, ProvinceMaterial::PROVINCES_DATA_BINDING); } +void ee_magnum::MagnumRenderer::UpdateProvinces(const std::size_t index, const std::vector &data) +{ + provinceSSBO.setSubData(index, data); +} + void ee_magnum::MagnumRenderer::Shutdown() { provinceMeshes.clear(); @@ -121,5 +142,5 @@ void ee_magnum::MagnumRenderer::Shutdown() ee_magnum::MagnumRenderer::~MagnumRenderer() { - + } \ No newline at end of file diff --git a/sdk/assets/CMakeLists.txt b/sdk/assets/CMakeLists.txt index 047078b..aab223f 100644 --- a/sdk/assets/CMakeLists.txt +++ b/sdk/assets/CMakeLists.txt @@ -13,10 +13,13 @@ project (compile_assets) find_package(nlohmann_json CONFIG REQUIRED) find_package(xxHash CONFIG REQUIRED) -add_executable(${PROJECT_NAME} compile_assets.cpp) +add_executable(${PROJECT_NAME} compile_assets.cpp define/regions.def) target_link_libraries(${PROJECT_NAME} PRIVATE nlohmann_json::nlohmann_json) target_link_libraries(${PROJECT_NAME} PRIVATE xxHash::xxhash) target_link_libraries(${PROJECT_NAME} PUBLIC engine-api) +target_link_libraries(${PROJECT_NAME} PUBLIC server) + +target_compile_options(${PROJECT_NAME} PRIVATE /Zc:preprocessor) if (CMAKE_VERSION VERSION_GREATER 3.12) set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) diff --git a/sdk/assets/compile_assets.cpp b/sdk/assets/compile_assets.cpp index 868eb2b..c4f9566 100644 --- a/sdk/assets/compile_assets.cpp +++ b/sdk/assets/compile_assets.cpp @@ -1,3 +1,6 @@ +import AssetData; +import GameData; + #include #include #include @@ -7,7 +10,6 @@ #include #include #include -#include using json = nlohmann::json; @@ -23,11 +25,19 @@ namespace ee_data ) } +namespace ee_data +{ + NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( + GameState, + subjects + ) +} + namespace ee_assets { NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( AssetSave, - subjects + content ) NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE( @@ -124,7 +134,7 @@ int main(int argc, char **argv) // Compile colors CompileRecursive(data, [](const std::basic_string &key, json &value) { if (!value.is_string()) return; - + const char* color_str = value.get_ref().c_str() + 1; uint8_t b = 0, g = 0, r = 0; uint32_t hex = 0; diff --git a/sdk/assets/define/regions.def b/sdk/assets/define/regions.def index 68f1761..5af5463 100644 --- a/sdk/assets/define/regions.def +++ b/sdk/assets/define/regions.def @@ -2,18 +2,14 @@ #define MAP(name, color) #endif -MAP(elnia, 0xFF0000) -MAP(south_hleria, 0xFFD800) -MAP(siburia_central, 0xFF00DC) -MAP(siburia, 0xFF0000) -MAP(savatia, 0xFF0000) -MAP(east_monfua, 0xFF0000) +MAP(pepene, 0xAA00FF) +MAP(scarna, 0xFF007F) -MAP(dineria, 0x0400FF) -MAP(perdania, 0xFF6A00) +MAP(dineria, 0xFFFF00) +MAP(perdania, 0x7FFF00) MAP(arstinia, 0xFF0000) -MAP(ortostan, 0xFF0000) -MAP(zerandia, 0xFF0000) -MAP(mgahvatia, 0xFF0000) +MAP(alende, 0x0000FF) +MAP(zerandia, 0xFF5400) +MAP(mgahvatia, 0x5400FF) #undef MAP \ No newline at end of file diff --git a/sdk/assets/saves/empires.save.json b/sdk/assets/saves/empires.save.json index 1c13b51..f0fab0b 100644 --- a/sdk/assets/saves/empires.save.json +++ b/sdk/assets/saves/empires.save.json @@ -1,33 +1,26 @@ { + "content": { "subjects": [ - - { - "tag": "ESH", - "color": "#FF0000", - - "regions": [ - "elnia", - "south_hleria", - "siburia_central", - "siburia", - "savatia", - "east_monfua" - ] - }, - - { - "tag": "UCB", - "color": "#00FF00", - - "regions": [ - "dineria", - "perdania", - "arstinia", - "ortostan", - "zerandia", - "mgahvatia" - ] - } - + { + "tag": "FSC", + "color": "#FF0000", + "regions": [ + "pepene", + "scarna" + ] + }, + { + "tag": "UCB", + "color": "#0000FF", + "regions": [ + "dineria", + "perdania", + "arstinia", + "alende", + "zerandia", + "mgahvatia" + ] + } ] + } } \ No newline at end of file diff --git a/sdk/map/regions.bmp b/sdk/map/regions.bmp new file mode 100644 index 0000000..ee3812a Binary files /dev/null and b/sdk/map/regions.bmp differ diff --git a/sdk/map/run.cmd b/sdk/map/run.cmd index 11b0a5b..21b3933 100644 --- a/sdk/map/run.cmd +++ b/sdk/map/run.cmd @@ -1,2 +1,2 @@ @echo off -"%CD%/../../out/build/DEBUG/sdk/map/convert_map.exe" states.bmp ../../assets/map/states.map \ No newline at end of file +"%CD%/../../out/build/DEBUG/sdk/map/convert_map.exe" regions.bmp ../../assets/map/regions.map \ No newline at end of file diff --git a/server/.vscode/launch.json b/server/.vscode/launch.json deleted file mode 100644 index e8338f2..0000000 --- a/server/.vscode/launch.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "configurations": [ - { - "type": "cmake", - "request": "launch", - "name": "Debug portfile(s)", - "cmakeDebugType": "external", - "pipeName": "\\\\.\\pipe\\vcpkg_ext_portfile_dbg", - "preLaunchTask": "Debug vcpkg commands" - } - ] -} \ No newline at end of file diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt deleted file mode 100644 index 8999193..0000000 --- a/server/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -cmake_minimum_required (VERSION 3.8) - -if (POLICY CMP0141) - cmake_policy(SET CMP0141 NEW) - set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") -endif() - -set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - -project ("server") - -add_subdirectory ("economy") -add_subdirectory ("economy/test") - -add_subdirectory ("ecs") -add_subdirectory ("ecs/test") \ No newline at end of file diff --git a/server/economy/CMakeLists.txt b/server/economy/CMakeLists.txt deleted file mode 100644 index 7e11e37..0000000 --- a/server/economy/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -project(Economy) - -# List sources - -set(HEADERS "economy.hpp" "defines.hpp" "enterprise_defaults.hpp" "systems.hpp") -set(HEADERS_COMPONENTS "container.hpp" "enterprise.hpp" "state.hpp" "tags.hpp" - "miner.hpp" "producer.hpp" "deliverer.hpp") - -set(SOURCES "Economy.cpp") -set(SOURCES_SYSTEMS "enterprise_routine.cpp" "mining.cpp" "delivering.cpp") - -list(TRANSFORM HEADERS PREPEND "include/ee_economy/") -list(TRANSFORM HEADERS_COMPONENTS PREPEND "include/ee_economy/components/") - -list(TRANSFORM SOURCES PREPEND "src/") -list(TRANSFORM SOURCES_SYSTEMS PREPEND "src/systems/") - -# Find dependencies - -find_package(EnTT CONFIG REQUIRED) - -# Link library - -add_library(${PROJECT_NAME} ${HEADERS} ${HEADERS_COMPONENTS} ${SOURCES} ${SOURCES_SYSTEMS}) -add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) - -target_link_libraries(${PROJECT_NAME} PRIVATE EnTT::EnTT) - -target_include_directories(${PROJECT_NAME} PUBLIC include/) - -if (CMAKE_VERSION VERSION_GREATER 3.12) - set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) -endif() \ No newline at end of file diff --git a/server/economy/include/ee_economy/components/container.hpp b/server/economy/include/ee_economy/components/container.hpp deleted file mode 100644 index f734244..0000000 --- a/server/economy/include/ee_economy/components/container.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "../defines.hpp" -#include - -namespace ee_economy -{ - struct Container - { - double capacity = 0.; - double total = 0.; - std::unordered_map content; - - void add(RESOURCE_TYPE type, double delta) - { - this->content[type] += delta; - this->total += delta; - } - }; -} \ No newline at end of file diff --git a/server/economy/include/ee_economy/components/deliverer.hpp b/server/economy/include/ee_economy/components/deliverer.hpp deleted file mode 100644 index 825a022..0000000 --- a/server/economy/include/ee_economy/components/deliverer.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include -#include - -namespace ee_economy -{ - struct DeliverContract - { - entt::entity from; - entt::entity to; - entt::entity sponsor; - - double amount = 0.0; - double cost = 0.0; - double distance = 1.0; - }; - - struct Deliverer - { - RESOURCE_TYPE resource = RESOURCE_TYPE::NONE; - - std::vector contracts; - }; -} \ No newline at end of file diff --git a/server/economy/include/ee_economy/components/enterprise.hpp b/server/economy/include/ee_economy/components/enterprise.hpp deleted file mode 100644 index 2addb79..0000000 --- a/server/economy/include/ee_economy/components/enterprise.hpp +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once -#include -#include -#include - -namespace ee_economy -{ - struct Enterprise - { - bool isBuilding = false; - entt::entity state; - ACTION_TYPE action = ACTION_TYPE::STORE; - - /* - * Mining - Amount of mined resource - * Delivering - Amount of resource that can be delivered by one truck - * Production - - */ - double efficiency = 0.; - double baseEfficiency = 0.; - double factorEfficiency = 1.; - - std::vector linksFrom; - std::vector linksTo; - - uint16_t staffSize = 1; - - // This can be splitted in percents between bank enterprises in future - double totalMoney = 0; - double salary = 0; - bool isBankrupt = false; - - void setMoney(double value) - { - totalMoney = value; - } - - inline void updateEfficiency() - { - this->efficiency = this->baseEfficiency * this->factorEfficiency; - } - - void setBaseEfficiency(double value) - { - this->baseEfficiency = value; - updateEfficiency(); - } - - void setFactorEfficiency(double value) - { - this->factorEfficiency = value; - updateEfficiency(); - } - }; -} \ No newline at end of file diff --git a/server/economy/include/ee_economy/components/miner.hpp b/server/economy/include/ee_economy/components/miner.hpp deleted file mode 100644 index 44cb3c2..0000000 --- a/server/economy/include/ee_economy/components/miner.hpp +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include -#include - -namespace ee_economy -{ - struct Miner - { - RESOURCE_TYPE resource = RESOURCE_TYPE::NONE; - }; -} \ No newline at end of file diff --git a/server/economy/include/ee_economy/components/producer.hpp b/server/economy/include/ee_economy/components/producer.hpp deleted file mode 100644 index 379f2bc..0000000 --- a/server/economy/include/ee_economy/components/producer.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once - -namespace ee_economy -{ - struct Producer - { - - }; -} \ No newline at end of file diff --git a/server/economy/include/ee_economy/components/state.hpp b/server/economy/include/ee_economy/components/state.hpp deleted file mode 100644 index 0b5cb1a..0000000 --- a/server/economy/include/ee_economy/components/state.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include - -namespace ee_economy -{ - struct State { - int16_t externalId = -1; - }; -} \ No newline at end of file diff --git a/server/economy/include/ee_economy/components/tags.hpp b/server/economy/include/ee_economy/components/tags.hpp deleted file mode 100644 index ea625ce..0000000 --- a/server/economy/include/ee_economy/components/tags.hpp +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -namespace ee_economy -{ - -} \ No newline at end of file diff --git a/server/economy/include/ee_economy/defines.hpp b/server/economy/include/ee_economy/defines.hpp deleted file mode 100644 index 8ea641c..0000000 --- a/server/economy/include/ee_economy/defines.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once - -#include - -namespace ee_economy -{ - const double TOLERANCE = 0.001; - - const double BASE_FUEL_PER_KM = 1.0; - - enum struct ACTION_TYPE : uint8_t - { - MINING, - PRODUCTION, - DELIVERY, - STORE, - DESTRUCTION, - BUILD, - TRADE - }; - - enum struct CONTAINABLE_TYPE : uint8_t - { - RESOURCE, - GOODS, - SERVICE - }; - - enum struct RESOURCE_TYPE : uint8_t - { - NONE, - - AGRICULTURE, - MEAT, - COTTON, - LEATHER, - WOOL, - TIMBER, - COAL, - OIL, - GAS, - IRON, - COPPER, - LITHIUM, - URANIUM, - GOLD, - - FERTILIZER, - FABRIC, - FURNITURE, - LUXURY, - CLOTHING, - ALCOHOL, - PAPER, - GLASS, - PLASTIC, - CEMENT, - STEEL, - FUEL, - AVIATION_FUEL, - ROCKET_FUEL, - ENGINES, - ELECTRICITY, - AUTOMOBILE, - AIRPLANE, - HELICOPTER, - PHONE, - TRUCK, - CONSTRUCTION_EQUIPMENT, - PROCESSOR, - COMPUTER, - ELECTRONIC, - SEMICONDUCTOR, - BATTERY, - SYNTHETIC_RUBBER, - SYNTHETIC_FABRIC, - MACHINE_TOOLS, - MODERN_MACHINE_TOOLS, - POLYMERS, - MILITARY_EQUIPMENT, - MEDICINES, - TACTICAL_MISSILES, - NUCLEAR_MISSILES, - OIL_GAS - }; -} \ No newline at end of file diff --git a/server/economy/include/ee_economy/economy.hpp b/server/economy/include/ee_economy/economy.hpp deleted file mode 100644 index 17bbccd..0000000 --- a/server/economy/include/ee_economy/economy.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include "defines.hpp" -#include "enterprise_defaults.hpp" -#include "systems.hpp" - -#include "components/tags.hpp" -#include "components/state.hpp" -#include "components/container.hpp" - -#include "components/enterprise.hpp" -#include "components/miner.hpp" -#include "components/producer.hpp" -#include "components/deliverer.hpp" diff --git a/server/economy/include/ee_economy/enterprise_defaults.hpp b/server/economy/include/ee_economy/enterprise_defaults.hpp deleted file mode 100644 index 64e0164..0000000 --- a/server/economy/include/ee_economy/enterprise_defaults.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include "defines.hpp" -#include "components/container.hpp" - -namespace ee_economy -{ - struct EnterpriseDefaults - { - Container container; - - RESOURCE_TYPE resourceTarget = RESOURCE_TYPE::NONE; - double baseEfficiency = 0.0; - double factorEfficiency = 1.0; - }; -} \ No newline at end of file diff --git a/server/economy/include/ee_economy/resources_exchange.hpp b/server/economy/include/ee_economy/resources_exchange.hpp deleted file mode 100644 index 81ac8b0..0000000 --- a/server/economy/include/ee_economy/resources_exchange.hpp +++ /dev/null @@ -1,27 +0,0 @@ -// Rules for resources exchange in base before modifiers applying - -#pragma once -#include -#include "defines.hpp" - -namespace ee_economy -{ - struct ExchangeRule - { - double outValue; - - std::unordered_map consume; - }; - - const std::unordered_map resourcesExchange = { - { - RESOURCE_TYPE::FABRIC, - exchange_rule { - .outValue = 2., - .consume = { - {RESOURCE_TYPE::WOOL, 3.} - } - } - } - }; -} \ No newline at end of file diff --git a/server/economy/include/ee_economy/systems.hpp b/server/economy/include/ee_economy/systems.hpp deleted file mode 100644 index f13bb5e..0000000 --- a/server/economy/include/ee_economy/systems.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once -#include - -namespace ee_economy -{ - void enterpriseRoutine(entt::registry& registry); - - void mining(entt::registry& registry); - // void producing(entt::registry& registry); - void delivering(entt::registry& registry); - // void storaging(entt::registry& registry); // consume money for storage time - // void destructing(entt::registry& registry); - // void building(entt::registry& registry); - // void trading(entt::registry& registry); -} \ No newline at end of file diff --git a/server/economy/src/Economy.cpp b/server/economy/src/Economy.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/server/economy/src/systems/delivering.cpp b/server/economy/src/systems/delivering.cpp deleted file mode 100644 index 0f53bd6..0000000 --- a/server/economy/src/systems/delivering.cpp +++ /dev/null @@ -1,56 +0,0 @@ -#include - -void ee_economy::delivering(entt::registry ®istry) -{ - auto deliverers = registry.view(); - - for (auto [entity, enterprise, deliverer, storage]: deliverers.each()) - { - if (enterprise.isBankrupt) continue; - - for (DeliverContract &contract: deliverer.contracts) - { - double paidAmount = contract.amount; - - if (contract.cost > 0) - { - Enterprise &sponsor = registry.get(contract.sponsor); - - double costPerOne = contract.cost / contract.amount; - double payment = contract.cost; - - if (payment > sponsor.totalMoney) - { - payment = (int)(sponsor.totalMoney / costPerOne) * costPerOne; - paidAmount = payment / costPerOne; - } - sponsor.setMoney(sponsor.totalMoney - payment); - enterprise.setMoney(enterprise.totalMoney + payment); - contract.cost -= payment; - } - - Container &fromStorage = registry.get(contract.from); - Container &toStorage = registry.get(contract.to); - - double deliverValue = enterprise.efficiency; - if (contract.amount < enterprise.efficiency) - deliverValue = contract.amount; - if (toStorage.total + deliverValue > toStorage.capacity) - deliverValue = toStorage.capacity - toStorage.total; - if (deliverValue > fromStorage.content[deliverer.resource]) - deliverValue = fromStorage.content[deliverer.resource]; - if (deliverValue > paidAmount) - deliverValue = paidAmount; - if (deliverValue < 0.0) - deliverValue = 0.0; - - toStorage.add(deliverer.resource, deliverValue); - fromStorage.add(deliverer.resource, -deliverValue); - contract.amount -= deliverValue; - } - - std::erase_if(deliverer.contracts, [](const DeliverContract &contract) { - return contract.amount <= 0.0; - }); - } -} \ No newline at end of file diff --git a/server/economy/src/systems/enterprise_routine.cpp b/server/economy/src/systems/enterprise_routine.cpp deleted file mode 100644 index c038252..0000000 --- a/server/economy/src/systems/enterprise_routine.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include - -void ee_economy::enterpriseRoutine(entt::registry ®istry) -{ - auto enterprises = registry.view(); - - for (auto [entity, enterprise]: enterprises.each()) - { - double salaryDebt = enterprise.salary * enterprise.staffSize; - if (enterprise.totalMoney < salaryDebt) - { - enterprise.isBankrupt = true; - enterprise.setMoney(0.0); - } - else - { - enterprise.setMoney(enterprise.totalMoney - salaryDebt); - } - } -} \ No newline at end of file diff --git a/server/economy/src/systems/mining.cpp b/server/economy/src/systems/mining.cpp deleted file mode 100644 index 323717c..0000000 --- a/server/economy/src/systems/mining.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include - -void ee_economy::mining(entt::registry ®istry) -{ - auto miners = registry.view(); - - for (auto [entity, enterprise, miner, localStorage]: miners.each()) - { - if (enterprise.isBankrupt) continue; - - Container& state = registry.get(enterprise.state); - - double minedValue = enterprise.efficiency; - if (localStorage.total + minedValue > localStorage.capacity) - minedValue = localStorage.capacity - localStorage.total; - if (minedValue > state.content[miner.resource]) - minedValue = state.content[miner.resource]; - - localStorage.add(miner.resource, minedValue); - state.add(miner.resource, -minedValue); - } -} \ No newline at end of file diff --git a/server/economy/test/CMakeLists.txt b/server/economy/test/CMakeLists.txt deleted file mode 100644 index 36a932f..0000000 --- a/server/economy/test/CMakeLists.txt +++ /dev/null @@ -1,26 +0,0 @@ -project(economy_tests) - -# List sources - -set(SOURCES "test_conf.hpp" "main.cpp" - "systems/enterprise_routine.cpp" "systems/mining.cpp" "systems/delivering.cpp") - -# Find dependencies - -find_package(GTest CONFIG REQUIRED) - -# Link - -include(GoogleTest) - -add_executable(${PROJECT_NAME} ${SOURCES}) -target_link_libraries(${PROJECT_NAME} PRIVATE GTest::gtest_main) -target_link_libraries(${PROJECT_NAME} PRIVATE Economy::Economy) - -# Test - -if (CMAKE_VERSION VERSION_GREATER 3.12) - set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) -endif() - -gtest_discover_tests(${PROJECT_NAME}) \ No newline at end of file diff --git a/server/economy/test/main.cpp b/server/economy/test/main.cpp deleted file mode 100644 index 45acf01..0000000 --- a/server/economy/test/main.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include - -int main(int argc, char **argv) -{ - ::testing::InitGoogleTest(&argc, argv); - - return RUN_ALL_TESTS(); -} \ No newline at end of file diff --git a/server/economy/test/systems/delivering.cpp b/server/economy/test/systems/delivering.cpp deleted file mode 100644 index e1dd1c1..0000000 --- a/server/economy/test/systems/delivering.cpp +++ /dev/null @@ -1,214 +0,0 @@ -#include -#include -#include "../test_conf.hpp" - -TEST_F(SystemsTest, DeliverySingleNormal) -{ - // [Miner -> Storage] by Deliverer - - ee_economy::Enterprise &delivererEnterprise = registry.get(deliverer); - ee_economy::Deliverer &delivererDeliverer = registry.get(deliverer); - - delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL; - delivererEnterprise.setBaseEfficiency(1.0); - delivererDeliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0}); - - ee_economy::Container &fromContainer = registry.get(miner); - ee_economy::Container &toContainer = registry.get(storage); - - fromContainer.capacity = 15.0; - fromContainer.add(ee_economy::RESOURCE_TYPE::COAL, 15.0); - - toContainer.capacity = 15.0; - - ee_economy::delivering(registry); - - ASSERT_DOUBLE_EQ(fromContainer.total, 14.0); - ASSERT_DOUBLE_EQ(fromContainer.content[ee_economy::RESOURCE_TYPE::COAL], 14.0); - ASSERT_DOUBLE_EQ(toContainer.total, 1.0); - ASSERT_DOUBLE_EQ(toContainer.content[ee_economy::RESOURCE_TYPE::COAL], 1.0); - ASSERT_EQ(delivererDeliverer.contracts.size(), 1); -} - -TEST_F(SystemsTest, DeliverySingleEmpty) -{ - // [Miner -> Storage] by Deliverer - - ee_economy::Enterprise &delivererEnterprise = registry.get(deliverer); - ee_economy::Deliverer &delivererDeliverer = registry.get(deliverer); - - delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL; - delivererEnterprise.setBaseEfficiency(1.0); - delivererDeliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0}); - - ee_economy::Container &fromContainer = registry.get(miner); - ee_economy::Container &toContainer = registry.get(storage); - - fromContainer.capacity = 15.0; - toContainer.capacity = 15.0; - - ee_economy::delivering(registry); - - ASSERT_DOUBLE_EQ(fromContainer.total, 0.0); - ASSERT_DOUBLE_EQ(fromContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0); - ASSERT_DOUBLE_EQ(toContainer.total, 0.0); - ASSERT_DOUBLE_EQ(toContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0); - ASSERT_EQ(delivererDeliverer.contracts.size(), 1); -} - -TEST_F(SystemsTest, DeliverySinglePoor) -{ - // [Miner -> Storage] by Deliverer - - ee_economy::Enterprise &delivererEnterprise = registry.get(deliverer); - ee_economy::Deliverer &delivererDeliverer = registry.get(deliverer); - - delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL; - delivererEnterprise.setBaseEfficiency(1.0); - delivererDeliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0}); - - ee_economy::Container &fromContainer = registry.get(miner); - ee_economy::Container &toContainer = registry.get(storage); - - fromContainer.capacity = 15.0; - fromContainer.add(ee_economy::RESOURCE_TYPE::COAL, 0.5); - - toContainer.capacity = 15.0; - - ee_economy::delivering(registry); - - ASSERT_DOUBLE_EQ(fromContainer.total, 0.0); - ASSERT_DOUBLE_EQ(fromContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0); - ASSERT_DOUBLE_EQ(toContainer.total, 0.5); - ASSERT_DOUBLE_EQ(toContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.5); - ASSERT_EQ(delivererDeliverer.contracts.size(), 1); -} - -TEST_F(SystemsTest, DeliverySingleFinishContract) -{ - // [Miner -> Storage] by Deliverer - - ee_economy::Enterprise &delivererEnterprise = registry.get(deliverer); - ee_economy::Deliverer &delivererDeliverer = registry.get(deliverer); - - delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL; - delivererEnterprise.setBaseEfficiency(15.0); - delivererDeliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0}); - - ee_economy::Container &fromContainer = registry.get(miner); - ee_economy::Container &toContainer = registry.get(storage); - - fromContainer.capacity = 15.0; - fromContainer.add(ee_economy::RESOURCE_TYPE::COAL, 15.0); - - toContainer.capacity = 15.0; - - ee_economy::delivering(registry); - - ASSERT_DOUBLE_EQ(fromContainer.total, 5.0); - ASSERT_DOUBLE_EQ(fromContainer.content[ee_economy::RESOURCE_TYPE::COAL], 5.0); - ASSERT_DOUBLE_EQ(toContainer.total, 10.0); - ASSERT_DOUBLE_EQ(toContainer.content[ee_economy::RESOURCE_TYPE::COAL], 10.0); - ASSERT_EQ(delivererDeliverer.contracts.size(), 0); -} - -TEST_F(SystemsTest, DeliveryMultipleFinishPoorCycle) -{ - // [Miner -> Storage | Storage -> Miner] by Deliverer - - ee_economy::Enterprise &delivererEnterprise = registry.get(deliverer); - ee_economy::Deliverer &delivererDeliverer = registry.get(deliverer); - - delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL; - delivererEnterprise.setBaseEfficiency(16.0); - delivererDeliverer.contracts.push_back({.from = miner, .to = storage, .amount = 20.0}); - delivererDeliverer.contracts.push_back({.from = storage, .to = miner, .amount = 5.0}); - - ee_economy::Container &minerContainer = registry.get(miner); - ee_economy::Container &storageContainer = registry.get(storage); - - minerContainer.capacity = 15.0; - minerContainer.add(ee_economy::RESOURCE_TYPE::COAL, 15.0); - - storageContainer.capacity = 15.0; - - ee_economy::delivering(registry); - - ASSERT_DOUBLE_EQ(minerContainer.total, 5.0); - ASSERT_DOUBLE_EQ(minerContainer.content[ee_economy::RESOURCE_TYPE::COAL], 5.0); - ASSERT_DOUBLE_EQ(storageContainer.total, 10.0); - ASSERT_DOUBLE_EQ(storageContainer.content[ee_economy::RESOURCE_TYPE::COAL], 10.0); - ASSERT_EQ(delivererDeliverer.contracts.size(), 1); - ASSERT_EQ(delivererDeliverer.contracts[0].from, miner); -} - -TEST_F(SystemsTest, DeliveryPayment) -{ - // [Miner -> Storage] by Deliverer for $Miner - // [Miner -> Storage] by Deliverer - - ee_economy::Enterprise &delivererEnterprise = registry.get(deliverer); - ee_economy::Deliverer &delivererDeliverer = registry.get(deliverer); - - delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL; - delivererEnterprise.setBaseEfficiency(10.0); - delivererDeliverer.contracts.push_back({ - .from = miner, - .to = storage, - .sponsor = miner, - .amount = 10.0, - .cost = 100.0 - }); - - ee_economy::Container &fromContainer = registry.get(miner); - ee_economy::Enterprise &fromEnterprise = registry.get(miner); - ee_economy::Container &toContainer = registry.get(storage); - - fromContainer.capacity = 10.0; - fromContainer.add(ee_economy::RESOURCE_TYPE::COAL, 10.0); - fromEnterprise.setMoney(95.0); - - toContainer.capacity = 10.0; - - ee_economy::delivering(registry); - - ASSERT_DOUBLE_EQ(fromContainer.total, 1.0); - ASSERT_DOUBLE_EQ(fromContainer.content[ee_economy::RESOURCE_TYPE::COAL], 1.0); - ASSERT_DOUBLE_EQ(toContainer.total, 9.0); - ASSERT_DOUBLE_EQ(toContainer.content[ee_economy::RESOURCE_TYPE::COAL], 9.0); - ASSERT_DOUBLE_EQ(fromEnterprise.totalMoney, 5.0); - ASSERT_DOUBLE_EQ(delivererEnterprise.totalMoney, 90.0); - - ee_economy::DeliverContract contract = delivererDeliverer.contracts[0]; - ASSERT_DOUBLE_EQ(contract.cost, 10.0); - ASSERT_DOUBLE_EQ(contract.amount, 1.0); -} - -TEST_F(SystemsTest, DeliveryBankrupt) -{ - // [Miner -> Storage] by Deliverer - - ee_economy::Enterprise &delivererEnterprise = registry.get(deliverer); - ee_economy::Deliverer &delivererDeliverer = registry.get(deliverer); - - delivererDeliverer.resource = ee_economy::RESOURCE_TYPE::COAL; - delivererDeliverer.contracts.push_back({.from = miner, .to = storage, .amount = 10.0}); - delivererEnterprise.setBaseEfficiency(1.0); - delivererEnterprise.isBankrupt = true; - - ee_economy::Container &fromContainer = registry.get(miner); - ee_economy::Container &toContainer = registry.get(storage); - - fromContainer.capacity = 15.0; - fromContainer.add(ee_economy::RESOURCE_TYPE::COAL, 15.0); - - toContainer.capacity = 15.0; - - ee_economy::delivering(registry); - - ASSERT_DOUBLE_EQ(fromContainer.total, 15.0); - ASSERT_DOUBLE_EQ(fromContainer.content[ee_economy::RESOURCE_TYPE::COAL], 15.0); - ASSERT_DOUBLE_EQ(toContainer.total, 0.0); - ASSERT_DOUBLE_EQ(toContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0); - ASSERT_EQ(delivererDeliverer.contracts.size(), 1); -} \ No newline at end of file diff --git a/server/economy/test/systems/enterprise_routine.cpp b/server/economy/test/systems/enterprise_routine.cpp deleted file mode 100644 index 4f814b2..0000000 --- a/server/economy/test/systems/enterprise_routine.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include -#include "../test_conf.hpp" - -TEST_F(SystemsTest, RoutineNormal) -{ - ee_economy::Enterprise &minerEnterprise = registry.get(miner); - minerEnterprise.setMoney(1000000000.0); - minerEnterprise.salary = 100000.0; - minerEnterprise.staffSize = 10; - - ee_economy::enterpriseRoutine(registry); - - ASSERT_DOUBLE_EQ(minerEnterprise.totalMoney, 999000000.0); - ASSERT_FALSE(minerEnterprise.isBankrupt); -} - -TEST_F(SystemsTest, RoutineBankruptcy) -{ - ee_economy::Enterprise &minerEnterprise = registry.get(miner); - minerEnterprise.setMoney(1000000.0); - minerEnterprise.salary = 100000.0; - minerEnterprise.staffSize = 11; - - ee_economy::enterpriseRoutine(registry); - - ASSERT_DOUBLE_EQ(minerEnterprise.totalMoney, 0.0); - ASSERT_TRUE(minerEnterprise.isBankrupt); -} \ No newline at end of file diff --git a/server/economy/test/systems/mining.cpp b/server/economy/test/systems/mining.cpp deleted file mode 100644 index e92ba28..0000000 --- a/server/economy/test/systems/mining.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include -#include -#include "../test_conf.hpp" - -TEST_F(SystemsTest, MiningNormal) -{ - ee_economy::Container &stateContainer = registry.get(state); - ee_economy::Container &minerContainer = registry.get(miner); - ee_economy::Enterprise &minerEnterprise = registry.get(miner); - ee_economy::Miner &minerMiner = registry.get(miner); - - stateContainer.capacity = 15.0; - stateContainer.add(ee_economy::RESOURCE_TYPE::COAL, 10.0); - - minerContainer.capacity = 5.0; - minerMiner.resource = ee_economy::RESOURCE_TYPE::COAL; - minerEnterprise.setBaseEfficiency(0.1); - - ee_economy::mining(registry); - - ASSERT_DOUBLE_EQ(stateContainer.total, 9.9); - ASSERT_DOUBLE_EQ(stateContainer.content[ee_economy::RESOURCE_TYPE::COAL], 9.9); - ASSERT_DOUBLE_EQ(minerContainer.total, 0.1); - ASSERT_DOUBLE_EQ(minerContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.1); -} - -TEST_F(SystemsTest, MiningEmptyState) -{ - ee_economy::Container &stateContainer = registry.get(state); - ee_economy::Container &minerContainer = registry.get(miner); - ee_economy::Enterprise &minerEnterprise = registry.get(miner); - ee_economy::Miner &minerMiner = registry.get(miner); - - stateContainer.capacity = 15.0; - - minerContainer.capacity = 5.0; - minerMiner.resource = ee_economy::RESOURCE_TYPE::COAL; - minerEnterprise.setBaseEfficiency(0.1); - - ee_economy::mining(registry); - - ASSERT_DOUBLE_EQ(stateContainer.total, 0.0); - ASSERT_DOUBLE_EQ(stateContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0); - ASSERT_DOUBLE_EQ(minerContainer.total, 0.0); - ASSERT_DOUBLE_EQ(minerContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0); -} - -TEST_F(SystemsTest, MiningPoorState) -{ - ee_economy::Container &stateContainer = registry.get(state); - ee_economy::Container &minerContainer = registry.get(miner); - ee_economy::Enterprise &minerEnterprise = registry.get(miner); - ee_economy::Miner &minerMiner = registry.get(miner); - - stateContainer.capacity = 15.0; - stateContainer.add(ee_economy::RESOURCE_TYPE::COAL, 0.05); - - minerContainer.capacity = 5.0; - minerMiner.resource = ee_economy::RESOURCE_TYPE::COAL; - minerEnterprise.setBaseEfficiency(0.1); - - ee_economy::mining(registry); - - ASSERT_DOUBLE_EQ(stateContainer.total, 0.0); - ASSERT_DOUBLE_EQ(stateContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0); - ASSERT_DOUBLE_EQ(minerContainer.total, 0.05); - ASSERT_DOUBLE_EQ(minerContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.05); -} - -TEST_F(SystemsTest, MiningReachCap) -{ - ee_economy::Container &stateContainer = registry.get(state); - ee_economy::Container &minerContainer = registry.get(miner); - ee_economy::Enterprise &minerEnterprise = registry.get(miner); - ee_economy::Miner &minerMiner = registry.get(miner); - - stateContainer.capacity = 15.0; - stateContainer.add(ee_economy::RESOURCE_TYPE::COAL, 10.0); - - minerContainer.capacity = 0.05; - minerMiner.resource = ee_economy::RESOURCE_TYPE::COAL; - minerEnterprise.setBaseEfficiency(0.1); - - ee_economy::mining(registry); - - ASSERT_DOUBLE_EQ(stateContainer.total, 9.95); - ASSERT_DOUBLE_EQ(stateContainer.content[ee_economy::RESOURCE_TYPE::COAL], 9.95); - ASSERT_DOUBLE_EQ(minerContainer.total, 0.05); - ASSERT_DOUBLE_EQ(minerContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.05); -} - -TEST_F(SystemsTest, MiningBankrupt) -{ - ee_economy::Container &stateContainer = registry.get(state); - ee_economy::Container &minerContainer = registry.get(miner); - ee_economy::Enterprise &minerEnterprise = registry.get(miner); - ee_economy::Miner &minerMiner = registry.get(miner); - - stateContainer.capacity = 15.0; - stateContainer.add(ee_economy::RESOURCE_TYPE::COAL, 10.0); - - minerContainer.capacity = 5.0; - minerMiner.resource = ee_economy::RESOURCE_TYPE::COAL; - minerEnterprise.setBaseEfficiency(0.1); - minerEnterprise.isBankrupt = true; - - ee_economy::mining(registry); - - ASSERT_DOUBLE_EQ(stateContainer.total, 10.0); - ASSERT_DOUBLE_EQ(stateContainer.content[ee_economy::RESOURCE_TYPE::COAL], 10.0); - ASSERT_DOUBLE_EQ(minerContainer.total, 0.0); - ASSERT_DOUBLE_EQ(minerContainer.content[ee_economy::RESOURCE_TYPE::COAL], 0.0); -} \ No newline at end of file diff --git a/server/economy/test/test_conf.hpp b/server/economy/test/test_conf.hpp deleted file mode 100644 index 7673dc7..0000000 --- a/server/economy/test/test_conf.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include -#include -#include - -struct SystemsTest : testing::Test -{ - entt::registry registry; - - entt::entity state; - - entt::entity miner; - entt::entity storage; - entt::entity deliverer; - - void SetUp() - { - // Create state - state = registry.create(); - registry.emplace(state); - registry.emplace(state); - - // Create miner enterprise - miner = registry.create(); - registry.emplace(miner, false, state); - registry.emplace(miner); - registry.emplace(miner); - - // Create storage enterprise - storage = registry.create(); - registry.emplace(storage, false, state); - registry.emplace(storage); - - // Create delivering enterprise - deliverer = registry.create(); - registry.emplace(deliverer, false, state); - registry.emplace(deliverer); - registry.emplace(deliverer); - } - - void TearDown() - { - } -}; \ No newline at end of file diff --git a/server/ecs/CMakeLists.txt b/server/ecs/CMakeLists.txt deleted file mode 100644 index 34a8fc2..0000000 --- a/server/ecs/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -project(ECS) - -# List sources - -set(HEADERS "ecs.hpp" "api.hpp" "world.hpp") -set(SOURCES "api.cpp" "world.cpp") - -list(TRANSFORM HEADERS PREPEND "include/ee_ecs/") -list(TRANSFORM SOURCES PREPEND "src/") - -# Find dependencies -find_package(EnTT CONFIG REQUIRED) - -# Link library - -add_library(${PROJECT_NAME} ${HEADERS} ${SOURCES}) -add_library(${PROJECT_NAME}::${PROJECT_NAME} ALIAS ${PROJECT_NAME}) - -target_link_libraries(${PROJECT_NAME} PUBLIC Economy::Economy) -target_link_libraries(${PROJECT_NAME} PRIVATE EnTT::EnTT) - -target_include_directories(${PROJECT_NAME} PUBLIC include/) - - -if (CMAKE_VERSION VERSION_GREATER 3.12) - set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) -endif() \ No newline at end of file diff --git a/server/ecs/include/ee_ecs/api.hpp b/server/ecs/include/ee_ecs/api.hpp deleted file mode 100644 index 5350f05..0000000 --- a/server/ecs/include/ee_ecs/api.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once -#include -#include "data.hpp" - -namespace ee_ecs -{ - - void init(InitConfiguration config); - void start(); - - template - const std::vector getAllEnterprises(); - //const EnterpriseInfo getEnterprise(uint32_t id); -} \ No newline at end of file diff --git a/server/ecs/include/ee_ecs/data.hpp b/server/ecs/include/ee_ecs/data.hpp deleted file mode 100644 index a406c6d..0000000 --- a/server/ecs/include/ee_ecs/data.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include -#include -#include - -namespace ee_ecs -{ - - struct InitConfiguration - { - std::unordered_map states; - }; - - struct EnterpriseInfo - { - const ee_economy::Enterprise* info = nullptr; - const ee_economy::Container* storage = nullptr; - std::variant< - const ee_economy::Miner*, - const ee_economy::Deliverer* - > specialInfo; - }; - -} \ No newline at end of file diff --git a/server/ecs/include/ee_ecs/ecs.hpp b/server/ecs/include/ee_ecs/ecs.hpp deleted file mode 100644 index 1e527a2..0000000 --- a/server/ecs/include/ee_ecs/ecs.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#include "api.hpp" -#include "world.hpp" \ No newline at end of file diff --git a/server/ecs/include/ee_ecs/world.hpp b/server/ecs/include/ee_ecs/world.hpp deleted file mode 100644 index 649c4fc..0000000 --- a/server/ecs/include/ee_ecs/world.hpp +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once -#include "ee_economy/components/container.hpp" -#include -#include -#include -#include - -namespace ee_ecs -{ - class World - { - private: - entt::registry registry; - std::unordered_map statesTable; - - void updateEnterprises(); - - public: - // Run every registered system - void update(); - - entt::entity registerState(const int16_t id, const ee_economy::Container &resources); - - entt::entity spawnEnterprise( - const bool isBuilding, - const ee_economy::ACTION_TYPE action, - const entt::entity state, - const ee_economy::EnterpriseDefaults &defaults - ); - - entt::registry& getRegistry(); - }; -} \ No newline at end of file diff --git a/server/ecs/src/api.cpp b/server/ecs/src/api.cpp deleted file mode 100644 index 6233eab..0000000 --- a/server/ecs/src/api.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "ee_ecs/world.hpp" -#include - - -static ee_ecs::World worldInstance; - -void ee_ecs::init(ee_ecs::InitConfiguration config) -{ - for (auto& [id, container]: config.states) - { - worldInstance.registerState(id, container); - } -} - -void ee_ecs::start() -{ - while (true) {} -} - -template - const std::vector ee_ecs::getAllEnterprises() -{ - std::vector result; - //TODO: REPLACE VIEWS WITH GROUPS! - auto enterprises = worldInstance.getRegistry().group<>(entt::get< - ee_economy::Enterprise, - ee_economy::Container, - T - >); - result.reserve(enterprises.size_hint()); - - for (auto [entity, enterprise, container, action]: enterprises.each()) - { - EnterpriseInfo eninfo; - eninfo.info = &enterprise; - - eninfo.storage = &container; - eninfo.specialInfo = &action; - - result.push_back(eninfo); - } - - return result; -} diff --git a/server/ecs/src/world.cpp b/server/ecs/src/world.cpp deleted file mode 100644 index f98e20b..0000000 --- a/server/ecs/src/world.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include -#include - -void ee_ecs::World::updateEnterprises() -{ - ee_economy::enterpriseRoutine(this->registry); - - ee_economy::mining(this->registry); - ee_economy::delivering(this->registry); -} - -void ee_ecs::World::update() -{ - this->updateEnterprises(); -} - -entt::entity ee_ecs::World::registerState(const int16_t id, const ee_economy::Container &resources) -{ - if (this->statesTable.contains(id)) - throw std::invalid_argument("State with this Id is already registered"); - - entt::entity entity = this->registry.create(); - - this->registry.emplace(entity, id); - this->registry.emplace( - entity, - resources.capacity, - resources.total, - resources.content - ); - - this->statesTable[id] = entity; - - return entity; -} - -entt::entity ee_ecs::World::spawnEnterprise( - const bool isBuilding, - const ee_economy::ACTION_TYPE action, - const entt::entity state, - const ee_economy::EnterpriseDefaults &defaults -) -{ - entt::entity entity = this->registry.create(); - - this->registry.emplace( - entity, - isBuilding, - state, - action, - - defaults.baseEfficiency * defaults.factorEfficiency, - - defaults.baseEfficiency, - defaults.factorEfficiency - ); - - this->registry.emplace( - entity, - defaults.container.capacity, - defaults.container.total, - defaults.container.content - ); - - switch (action) - { - case ee_economy::ACTION_TYPE::MINING: - { - this->registry.emplace(entity, defaults.resourceTarget); - break; - } - - case ee_economy::ACTION_TYPE::DELIVERY: - { - this->registry.emplace(entity, defaults.resourceTarget); - break; - } - - default: - break; - } - - return entity; -} - -entt::registry& ee_ecs::World::getRegistry() {return this->registry;} \ No newline at end of file diff --git a/server/ecs/test/CMakeLists.txt b/server/ecs/test/CMakeLists.txt deleted file mode 100644 index 2df383f..0000000 --- a/server/ecs/test/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -project(ecs_tests) - -# List sources - -set(SOURCES "test_conf.hpp" "main.cpp" "world.cpp" "benchmark.cpp") - -# Find dependencies - -find_package(GTest CONFIG REQUIRED) - -# Link - -include(GoogleTest) - -add_executable(${PROJECT_NAME} ${SOURCES}) -target_link_libraries(${PROJECT_NAME} PRIVATE GTest::gtest_main) -target_link_libraries(${PROJECT_NAME} PRIVATE ECS::ECS) - -# Test - -if (CMAKE_VERSION VERSION_GREATER 3.12) - set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 20) -endif() - -gtest_discover_tests(${PROJECT_NAME}) \ No newline at end of file diff --git a/server/ecs/test/benchmark.cpp b/server/ecs/test/benchmark.cpp deleted file mode 100644 index 6530535..0000000 --- a/server/ecs/test/benchmark.cpp +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include "test_conf.hpp" -#include -#include - -struct timer final { - timer() - : start{std::chrono::system_clock::now()} {} - - void elapsed() { - auto now = std::chrono::system_clock::now(); - std::cout << std::chrono::duration(now - start).count() << " seconds" << std::endl; - } - -private: - std::chrono::time_point start; -}; - -template -void genericWith(Func func) { - timer timer; - func(); - timer.elapsed(); -} - -TEST_F(WorldBenchmark, UpdateSystems) -{ - genericWith([&]() { - world.update(); - }); -} \ No newline at end of file diff --git a/server/ecs/test/main.cpp b/server/ecs/test/main.cpp deleted file mode 100644 index 45acf01..0000000 --- a/server/ecs/test/main.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include - -int main(int argc, char **argv) -{ - ::testing::InitGoogleTest(&argc, argv); - - return RUN_ALL_TESTS(); -} \ No newline at end of file diff --git a/server/ecs/test/test_conf.hpp b/server/ecs/test/test_conf.hpp deleted file mode 100644 index 5e6ec9e..0000000 --- a/server/ecs/test/test_conf.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include - -struct WorldBenchmark : testing::Test -{ - ee_ecs::World world; - - void SetUp() - { - for (int16_t i = 0; i < 1000; i++) - { - ee_economy::Container resources {.capacity = 100.0}; - resources.add(ee_economy::RESOURCE_TYPE::COAL, 100.0); - entt::entity state = world.registerState(i, resources); - - ee_economy::EnterpriseDefaults miner { - .container {.capacity = 100.0}, - .resourceTarget = ee_economy::RESOURCE_TYPE::GOLD, - .baseEfficiency = 1.0 - }; - - world.spawnEnterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner); - world.spawnEnterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner); - world.spawnEnterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner); - world.spawnEnterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner); - world.spawnEnterprise(false, ee_economy::ACTION_TYPE::MINING, state, miner); - } - } - - void TearDown() - { - - } -}; \ No newline at end of file diff --git a/server/ecs/test/world.cpp b/server/ecs/test/world.cpp deleted file mode 100644 index 01d17ef..0000000 --- a/server/ecs/test/world.cpp +++ /dev/null @@ -1,80 +0,0 @@ -#include -#include -#include -#include - -TEST(WorldTest, RegisterState) -{ - ee_ecs::World world; - - ee_economy::Container res {.capacity = 100.0}; - res.add(ee_economy::RESOURCE_TYPE::COAL, 98.0); - entt::entity state = world.registerState(10, res); - - ee_economy::State registeredState = world.getRegistry().get(state); - ee_economy::Container registeredContainer = world.getRegistry().get(state); - - ASSERT_EQ(registeredState.externalId, 10); - ASSERT_DOUBLE_EQ(registeredContainer.content[ee_economy::RESOURCE_TYPE::COAL], 98.0); -} - -TEST(WorldTest, RegisterStateDuplicate) -{ - ee_ecs::World world; - - world.registerState(10, {}); - - ASSERT_THROW({ - world.registerState(10, {}); - }, std::invalid_argument); -} - -TEST(WorldTest, SpawnMiner) -{ - ee_ecs::World world; - - entt::entity state = world.getRegistry().create(); - world.getRegistry().emplace(state, (int16_t)0); - world.getRegistry().emplace(state, 100.0); - - ee_economy::EnterpriseDefaults defaults { - .container {.capacity = 100.0 }, - .resourceTarget = ee_economy::RESOURCE_TYPE::COAL, - .baseEfficiency = 1.0, - }; - - entt::entity enterprise = world.spawnEnterprise(false, ee_economy::ACTION_TYPE::MINING, state, defaults); - - ee_economy::Enterprise registeredEnterprise = world.getRegistry().get(enterprise); - ee_economy::Miner registeredAction = world.getRegistry().get(enterprise); - ee_economy::Container registeredContainer = world.getRegistry().get(enterprise); - - ASSERT_DOUBLE_EQ(registeredEnterprise.baseEfficiency, 1.0); - ASSERT_EQ(registeredAction.resource, ee_economy::RESOURCE_TYPE::COAL); - ASSERT_DOUBLE_EQ(registeredContainer.capacity, 100.0); -} - -TEST(WorldTest, SpawnDeliverer) -{ - ee_ecs::World world; - - entt::entity state = world.getRegistry().create(); - world.getRegistry().emplace(state, (int16_t)0); - world.getRegistry().emplace(state, 100.0); - - ee_economy::EnterpriseDefaults defaults { - .container {.capacity = 100.0 }, - .resourceTarget = ee_economy::RESOURCE_TYPE::COAL, - .baseEfficiency = 1.0, - }; - - entt::entity enterprise = world.spawnEnterprise(false, ee_economy::ACTION_TYPE::DELIVERY, state, defaults); - - ee_economy::Enterprise registeredEnterprise = world.getRegistry().get(enterprise); - ee_economy::Deliverer registeredAction = world.getRegistry().get(enterprise); - ee_economy::Container registeredContainer = world.getRegistry().get(enterprise); - - ASSERT_DOUBLE_EQ(registeredEnterprise.baseEfficiency, 1.0); - ASSERT_EQ(registeredAction.resource, ee_economy::RESOURCE_TYPE::COAL); - ASSERT_DOUBLE_EQ(registeredContainer.capacity, 100.0); -} \ No newline at end of file diff --git a/server/lib/CMakeLists.txt b/server/lib/CMakeLists.txt new file mode 100644 index 0000000..bdb1f22 --- /dev/null +++ b/server/lib/CMakeLists.txt @@ -0,0 +1,5 @@ +include(${CMAKE_SOURCE_DIR}/cmake/library.cmake) + +set(LIB server) + +add_library_target(${LIB}) \ No newline at end of file diff --git a/server/lib/modules/GameData.cppm b/server/lib/modules/GameData.cppm new file mode 100644 index 0000000..ed6dffc --- /dev/null +++ b/server/lib/modules/GameData.cppm @@ -0,0 +1,21 @@ +module; + +#include +#include + +export module GameData; + +export namespace ee_data +{ + struct Subject + { + std::uint32_t tag; + std::uint32_t color; + std::vector regions; + }; + + struct GameState + { + std::vector subjects; + }; +} \ No newline at end of file diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index c3055eb..b7760a8 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -1,26 +1,14 @@ -if (POLICY CMP0141) - cmake_policy(SET CMP0141 NEW) - set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$,$>,$<$:EditAndContinue>,$<$:ProgramDatabase>>") -endif() - -set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) -set(CMAKE_EXPORT_COMPILE_COMMANDS ON) - - -project(utils) - -file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS - "src/*.cpp" - "src/*.c" - "include/*.hpp" - "include/*.h" -) +include(${CMAKE_SOURCE_DIR}/cmake/library.cmake) +set(LIB utils) # Find dependencies +find_package(Boost REQUIRED COMPONENTS lockfree) + # Link library -add_library(${PROJECT_NAME} ${SOURCES}) +add_library_target(${LIB}) -target_include_directories(${PROJECT_NAME} PUBLIC include/) \ No newline at end of file +target_link_libraries(${LIB} PUBLIC p7) +target_link_libraries(${LIB} PRIVATE Boost::lockfree) \ No newline at end of file diff --git a/utils/include/ee_utils/allocator.hpp b/utils/include/ee_utils/allocator.hpp deleted file mode 100644 index 88ad59c..0000000 --- a/utils/include/ee_utils/allocator.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include - -template T* Allocate(Args&&... args) -{ - return new T(std::forward(args)...); -} - -template void Deallocate(T* obj) -{ - delete obj; -} - -template T* AllocateArray(size_t size) -{ - return new T[size]; -} - -template void DeallocateArray(T* obj) -{ - delete[] obj; -} \ No newline at end of file diff --git a/utils/include/ee_utils/buffers.hpp b/utils/include/ee_utils/buffers.hpp deleted file mode 100644 index 80224f3..0000000 --- a/utils/include/ee_utils/buffers.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include - -#define as_bytes(value) reinterpret_cast(value) - -namespace ee_utils -{ - bool readNext(void* dst, uint8_t* &srcPointer, size_t &srcLeftoverSize, const size_t &readSize); - bool writeNext(uint8_t* &dstPointer, void* src, size_t &dstLeftoverSize, const size_t &writeSize); -} \ No newline at end of file diff --git a/utils/include/ee_utils/platform.hpp b/utils/include/ee_utils/platform.hpp new file mode 100644 index 0000000..c89380b --- /dev/null +++ b/utils/include/ee_utils/platform.hpp @@ -0,0 +1,11 @@ +#ifndef ETREDIAEMPIRES_PLATFORM_HPP +#define ETREDIAEMPIRES_PLATFORM_HPP + +#ifdef _WIN32 +#include +#endif + +#ifdef __linux__ +#endif + +#endif //ETREDIAEMPIRES_PLATFORM_HPP diff --git a/utils/include/ee_utils/utils.hpp b/utils/include/ee_utils/utils.hpp new file mode 100644 index 0000000..6f93970 --- /dev/null +++ b/utils/include/ee_utils/utils.hpp @@ -0,0 +1,6 @@ +#ifndef ETREDIAEMPIRES_UTILS_HPP +#define ETREDIAEMPIRES_UTILS_HPP + +#define MAP_WORKER_COMMAND(TCommand, method) [this](TCommand &cmd) {this->method(cmd);} + +#endif //ETREDIAEMPIRES_UTILS_HPP diff --git a/utils/modules/allocator.cppm b/utils/modules/allocator.cppm new file mode 100644 index 0000000..a6ee53b --- /dev/null +++ b/utils/modules/allocator.cppm @@ -0,0 +1,27 @@ +module; + +#include + +export module allocator; + +export { + template T* Allocate(Args&&... args) + { + return new T(std::forward(args)...); + } + + template void Deallocate(T* obj) + { + delete obj; + } + + template T* AllocateArray(std::size_t size) + { + return new T[size]; + } + + template void DeallocateArray(T* obj) + { + delete[] obj; + } +} \ No newline at end of file diff --git a/utils/modules/buffers.cppm b/utils/modules/buffers.cppm new file mode 100644 index 0000000..26ef2ed --- /dev/null +++ b/utils/modules/buffers.cppm @@ -0,0 +1,12 @@ +module; + +#include +#include + +export module buffers; + +export namespace ee_utils +{ + bool readNext(void* dst, std::uint8_t* &srcPointer, std::size_t &srcLeftoverSize, const std::size_t &readSize); + bool writeNext(std::uint8_t* &dstPointer, void* src, std::size_t &dstLeftoverSize, const std::size_t &writeSize); +} \ No newline at end of file diff --git a/utils/modules/worker.cppm b/utils/modules/worker.cppm new file mode 100644 index 0000000..c3acb65 --- /dev/null +++ b/utils/modules/worker.cppm @@ -0,0 +1,151 @@ +module; + +#include "Logger.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +export module worker; + +export namespace ee_utils +{ + struct WorkerCommand + { + uint8_t type = 0; + }; + template concept IWorkerCommand = std::is_base_of_v; + + template + class Worker + { + public: + void Request(const TCommand &command) + { + commands.push(command); + } + + void Request(const std::uint8_t type) + { + commands.push(TCommand {.type = type}); + } + + void ProcessQueue(TCommand &buffer, std::vector &incompletesBuffer) + { + while (this->commands.pop(buffer)) + { + ProcessCommand(buffer); + if (buffer.type != maxCmdType) + incompletesBuffer.push_back(buffer); + } + for (TCommand &command : incompletesBuffer) + { + this->commands.push(command); + } + incompletesBuffer.clear(); + } + + protected: + std::array, maxCmdType + 1> commandsMapping; + // TODO: maybe I should use lockfree::queue ? + boost::lockfree::spsc_queue> commands; + + void ProcessCommand(TCommand &command) + { + if (command.type > maxCmdType || !commandsMapping[command.type]) + { + LOG(WARNING, "Unhandled command. Type id: %d", command.type); + command.type = maxCmdType; + return; + } + + commandsMapping[command.type](command); + } + }; + + class ThreadedWorkerBase { + public: + std::atomic isRunning; + + virtual ~ThreadedWorkerBase() {} + + void Start() + { + if (isRunning) + { + LOG(CRITICAL, "Thread can be started only once before stop"); + throw std::logic_error("Thread can be started only once before stop"); + } + + isRunning.store(true); + thread = std::jthread([this](std::stop_token stop) { + this->stoken = &stop; + Threading(); + }); + } + + void Shutdown() + { + if (isRunning) + thread.request_stop(); + else LOG(WARNING, "Tried to shutdown stopped thread"); + } + + protected: + std::stop_token *stoken{}; + std::jthread thread; + + virtual void Threading() = 0; + }; + template concept IThreadedWorker = std::is_base_of_v; + + template + class ThreadedWorker : public Worker, public ThreadedWorkerBase + { + protected: + const wchar_t *threadName; + + explicit ThreadedWorker(const wchar_t *threadName) + { + this->threadName = threadName; + } + + void Threading() + { + Logger::trace->Register_Thread(threadName, 0); + LOG(INFO, "Thread started"); + + Loop(); + + ReleaseStop(); + } + + void Loop() + { + TCommand commandBuffer{}; + std::vector incompleteCommands; + while (!stoken->stop_requested()) + { + this->ProcessQueue(commandBuffer, incompleteCommands); + + Update(); + } + } + + virtual void Update() = 0; + virtual void Release() = 0; + + private: + void ReleaseStop() + { + Release(); + LOG(INFO, "Client is released"); + isRunning.store(false); + } + }; +} \ No newline at end of file diff --git a/utils/src/buffers.cpp b/utils/src/buffers.cpp index 81cf3a8..b767af9 100644 --- a/utils/src/buffers.cpp +++ b/utils/src/buffers.cpp @@ -1,7 +1,12 @@ -#include +module; + +#include +#include #include -bool ee_utils::readNext(void* dst, uint8_t* &srcPointer, size_t &srcLeftoverSize, const size_t &readSize) +module buffers; + +bool ee_utils::readNext(void* dst, std::uint8_t* &srcPointer, std::size_t &srcLeftoverSize, const std::size_t &readSize) { if (srcLeftoverSize >= readSize) { @@ -15,7 +20,7 @@ bool ee_utils::readNext(void* dst, uint8_t* &srcPointer, size_t &srcLeftoverSize return false; } -bool ee_utils::writeNext(uint8_t* &dstPointer, void* src, size_t &dstLeftoverSize, const size_t &writeSize) +bool ee_utils::writeNext(std::uint8_t* &dstPointer, void* src, std::size_t &dstLeftoverSize, const std::size_t &writeSize) { if (dstLeftoverSize >= writeSize) { diff --git a/utils/src/utils.cpp b/utils/src/utils.cpp deleted file mode 100644 index e69de29..0000000