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