From 2cf37f4e0a1146d694a9db3581293505a41cc935 Mon Sep 17 00:00:00 2001 From: DrSocalkwe3n Date: Tue, 19 Aug 2025 17:12:45 +0600 Subject: [PATCH] * --- CMakeLists.txt | 45 ++++++-- Src/Client/Vulkan/Vulkan.cpp | 21 ++-- Src/Client/Vulkan/VulkanRenderSession.cpp | 2 +- Src/Client/Vulkan/VulkanRenderSession.hpp | 5 +- Src/Common/Abstract.cpp | 14 +++ Src/Common/Abstract.hpp | 100 ++++++++++++------ Src/Server/AssetsManager.cpp | 121 ++++++++++++---------- Src/Server/AssetsManager.hpp | 66 +++++++----- Src/Server/RemoteClient.cpp | 2 +- Src/assets.py | 20 ++-- 10 files changed, 255 insertions(+), 141 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ce9bf2..0b1d21d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,12 @@ project(LuaVox VERSION 0.0 DESCRIPTION "LuaVox Description") add_library(luavox_common INTERFACE) target_compile_features(luavox_common INTERFACE cxx_std_23) +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + target_compile_options(luavox_common INTERFACE -fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=all) + target_link_options(luavox_common INTERFACE -fsanitize=address,undefined) + set(ENV{ASAN_OPTIONS} detect_leaks=0) +endif() + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") target_compile_options(luavox_common INTERFACE -fcoroutines) elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") @@ -151,15 +157,38 @@ FetchContent_MakeAvailable(sqlite3) target_link_libraries(luavox_common INTERFACE SQLite::SQLite3) # Static Assets -file(GLOB_RECURSE ASSETS RELATIVE "${PROJECT_SOURCE_DIR}/assets" "assets/*.*") -file(GLOB_RECURSE ASSETS_A "${PROJECT_SOURCE_DIR}/assets" "assets/*.*") -add_custom_command(OUTPUT assets.o resources.cpp INPUT ${ASSETS_A} - COMMAND cd ${CMAKE_CURRENT_BINARY_DIR} && ${CMAKE_CURRENT_SOURCE_DIR}/Src/assets.py ${ASSETS} - COMMAND cd "${CMAKE_CURRENT_SOURCE_DIR}/assets" && ld -r -b binary -o '${CMAKE_CURRENT_BINARY_DIR}/assets.o' ${ASSETS} - COMMAND objcopy --rename-section .data=.rodata,alloc,load,readonly,data,contents ${CMAKE_CURRENT_BINARY_DIR}/assets.o ${CMAKE_CURRENT_BINARY_DIR}/assets.o) +find_package(Python3 REQUIRED) +set(ASSETS_DIR "${PROJECT_SOURCE_DIR}/assets") +file(GLOB_RECURSE ASSETS_LIST RELATIVE "${ASSETS_DIR}" "${ASSETS_DIR}/*.*") -set_source_files_properties(assets.o PROPERTIES EXTERNAL_OBJECT true GENERATED true) -add_library(assets STATIC resources.cpp assets.o) +set(ASSETS_O "${CMAKE_CURRENT_BINARY_DIR}/assets.o") +set(ASSETS_LD_O "${CMAKE_CURRENT_BINARY_DIR}/assets_ld.o") +set(RESOURCES_CPP "${CMAKE_CURRENT_BINARY_DIR}/resources.cpp") + +set(ASSETS_ABS) +foreach(asset IN LISTS ASSETS_LIST) + list(APPEND ASSETS_ABS "${ASSETS_DIR}/${asset}") +endforeach() + +add_custom_command( + OUTPUT ${ASSETS_O} ${RESOURCES_CPP} + DEPENDS ${ASSETS_ABS} + COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Src/assets.py + "${RESOURCES_CPP}" + ${ASSETS_LIST} + COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_SOURCE_DIR}/assets" ld -r -b binary -o "${ASSETS_LD_O}" ${ASSETS_LIST} + COMMAND ${CMAKE_OBJCOPY} + -O elf64-x86-64 + --rename-section .data=.rodata,alloc,load,readonly,data,contents + ${ASSETS_LD_O} + ${ASSETS_O} + COMMENT "Embedding assets: generating resources.cpp and assets.o" + VERBATIM +) + +set_source_files_properties(${RESOURCES_CPP} PROPERTIES GENERATED true) +set_source_files_properties(${ASSETS_O} PROPERTIES EXTERNAL_OBJECT true GENERATED true) +add_library(assets STATIC ${RESOURCES_CPP} ${ASSETS_O}) set_target_properties(assets PROPERTIES LINKER_LANGUAGE C) target_link_libraries(luavox_common INTERFACE assets) diff --git a/Src/Client/Vulkan/Vulkan.cpp b/Src/Client/Vulkan/Vulkan.cpp index 8a753ec..6bcbdab 100644 --- a/Src/Client/Vulkan/Vulkan.cpp +++ b/Src/Client/Vulkan/Vulkan.cpp @@ -2226,18 +2226,23 @@ void Vulkan::gui_MainMenu() { void Vulkan::gui_ConnectedToServer() { if(Game.Session) { - - if(!ImGui::Begin("MainMenu", nullptr, ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove)) - return; - - std::string text = std::to_string(ImGui::GetIO().Framerate); - ImGui::Text(text.c_str()); - - ImGui::End(); + if(ImGui::Begin("MainMenu", nullptr, ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove)) + { + std::string text = std::to_string(ImGui::GetIO().Framerate); + ImGui::Text(text.c_str()); + if(ImGui::Button("Выйти")) { + Game.RSession->pushStage(EnumRenderStage::Shutdown); + Game.Session->shutdown(EnumDisconnect::ByInterface); + Game.RSession = nullptr; + Game.Session = nullptr; + } + ImGui::End(); + } if(Game.Session->isConnected()) return; + Game.RSession->pushStage(EnumRenderStage::Shutdown); Game.RSession = nullptr; Game.Session = nullptr; Game.ImGuiInterfaces.pop_back(); diff --git a/Src/Client/Vulkan/VulkanRenderSession.cpp b/Src/Client/Vulkan/VulkanRenderSession.cpp index 5662fbe..5ad692f 100644 --- a/Src/Client/Vulkan/VulkanRenderSession.cpp +++ b/Src/Client/Vulkan/VulkanRenderSession.cpp @@ -1266,7 +1266,7 @@ void VulkanRenderSession::pushStage(EnumRenderStage stage) { VKCTX->ThreadVertexObj.join(); } -std::vector VulkanRenderSession::generateMeshForVoxelChunks(const std::vector cubes) { +std::vector VulkanRenderSession::generateMeshForVoxelChunks(const std::vector& cubes) { std::vector out; out.reserve(cubes.size()*6); diff --git a/Src/Client/Vulkan/VulkanRenderSession.hpp b/Src/Client/Vulkan/VulkanRenderSession.hpp index 5d15170..8b577b8 100644 --- a/Src/Client/Vulkan/VulkanRenderSession.hpp +++ b/Src/Client/Vulkan/VulkanRenderSession.hpp @@ -120,8 +120,7 @@ class VulkanRenderSession : public IRenderSession, public IVulkanDependent { } ~ThreadVertexObj_t() { - State.lock()->Stage = EnumRenderStage::Shutdown; - Thread.join(); + assert(!Thread.joinable()); if(CMDPool) vkDestroyCommandPool(VkInst->Graphics.Device, CMDPool, nullptr); @@ -355,7 +354,7 @@ public: void drawWorld(GlobalTime gTime, float dTime, VkCommandBuffer drawCmd); void pushStage(EnumRenderStage stage); - static std::vector generateMeshForVoxelChunks(const std::vector cubes); + static std::vector generateMeshForVoxelChunks(const std::vector& cubes); static std::vector generateMeshForNodeChunks(const Node* nodes); private: diff --git a/Src/Common/Abstract.cpp b/Src/Common/Abstract.cpp index 9fdcaa8..a187248 100644 --- a/Src/Common/Abstract.cpp +++ b/Src/Common/Abstract.cpp @@ -823,4 +823,18 @@ std::u8string unCompressLinear(const std::u8string& data) { return *(std::u8string*) &outString; } +PreparedNodeState::PreparedNodeState(const js::object& profile) { + for(auto& [key, value] : profile) { + + } +} + +PreparedNodeState::PreparedNodeState(const sol::table& profile) { + +} + +PreparedNodeState::PreparedNodeState(const std::u8string& data) { + +} + } \ No newline at end of file diff --git a/Src/Common/Abstract.hpp b/Src/Common/Abstract.hpp index 8bb5438..0266eb1 100644 --- a/Src/Common/Abstract.hpp +++ b/Src/Common/Abstract.hpp @@ -9,10 +9,15 @@ #include #include #include +#include #include +#include namespace LV { + +namespace js = boost::json; + namespace Pos { template @@ -498,40 +503,77 @@ enum struct TexturePipelineCMD : uint8_t { }; +/* + Хранит распаршенное определение состояний нод. + Не привязано ни к какому окружению. +*/ +struct PreparedNodeState { + enum class Op { + Add, Sub, Mul, Div, Mod, + LT, LE, GT, GE, EQ, NE, + And, Or, + Pos, Neg, Not + }; + + struct Node { + struct Num { int v; }; + struct Var { std::string name; }; + struct Unary { Op op; uint16_t rhs; }; + struct Binary { Op op; uint16_t lhs, rhs; }; + std::variant v; + }; + + struct Transformation { + int a; float b; + }; + + struct Model { + uint16_t Id; + bool UVLock = false; + std::vector Transforms; + }; + + struct VectorModel { + std::vector Models; + bool UVLock = false; + // Может добавить возможность использовать переменную рандома в трансформациях? + std::vector Transforms; + }; + + // Локальный идентификатор в именной ресурс + std::vector> ResourceToLocalId; + // Ноды выражений + std::vector Nodes; + // Условия -> вариации модели + веса + std::vector< + std::pair, uint16_t>, + 1 + > + > + > Routes; + + PreparedNodeState(const js::object& profile); + PreparedNodeState(const sol::table& profile); + PreparedNodeState(const std::u8string& data); + + PreparedNodeState() = default; + PreparedNodeState(const PreparedNodeState&) = default; + PreparedNodeState(PreparedNodeState&&) = default; + + PreparedNodeState& operator=(const PreparedNodeState&) = default; + PreparedNodeState& operator=(PreparedNodeState&&) = default; + + // Пишет в сжатый двоичный формат + std::u8string dump() const; +}; + struct TexturePipeline { std::vector BinTextures; std::u8string Pipeline; }; -struct DefVoxel_t { - -}; - -struct DefNode_t { - enum struct EnumDrawType : uint8_t { - NoDraw, // Не рисуется - Simple, // Простая нода с текстурами на каждой стороне - } DrawType = EnumDrawType::Simple; - - TexturePipeline Texs[6]; -}; - -struct DefWorld_t { - -}; - -struct DefPortal_t { - -}; - -struct DefEntity_t { - -}; - -struct DefItem_t { - -}; - using Hash_t = std::array; } diff --git a/Src/Server/AssetsManager.cpp b/Src/Server/AssetsManager.cpp index 79f18eb..16296f8 100644 --- a/Src/Server/AssetsManager.cpp +++ b/Src/Server/AssetsManager.cpp @@ -11,54 +11,54 @@ namespace LV::Server { -AssetsManager::Resource AssetsManager::loadResourceFromFile(EnumAssets type, fs::path path) const { +void AssetsManager::loadResourceFromFile(EnumAssets type, ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const { switch(type) { - case EnumAssets::Nodestate: return loadResourceFromFile_Nodestate(path); - case EnumAssets::Particle: return loadResourceFromFile_Particle(path); - case EnumAssets::Animation: return loadResourceFromFile_Animation(path); - case EnumAssets::Model: return loadResourceFromFile_Model(path); - case EnumAssets::Texture: return loadResourceFromFile_Texture(path); - case EnumAssets::Sound: return loadResourceFromFile_Sound(path); - case EnumAssets::Font: return loadResourceFromFile_Font(path); + case EnumAssets::Nodestate: loadResourceFromFile_Nodestate (out, domain, key, path); return; + case EnumAssets::Particle: loadResourceFromFile_Particle (out, domain, key, path); return; + case EnumAssets::Animation: loadResourceFromFile_Animation (out, domain, key, path); return; + case EnumAssets::Model: loadResourceFromFile_Model (out, domain, key, path); return; + case EnumAssets::Texture: loadResourceFromFile_Texture (out, domain, key, path); return; + case EnumAssets::Sound: loadResourceFromFile_Sound (out, domain, key, path); return; + case EnumAssets::Font: loadResourceFromFile_Font (out, domain, key, path); return; default: std::unreachable(); } } -AssetsManager::Resource AssetsManager::loadResourceFromLua(EnumAssets type, const sol::table& profile) const { +void AssetsManager::loadResourceFromLua(EnumAssets type, ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { switch(type) { - case EnumAssets::Nodestate: return loadResourceFromLua_Nodestate(profile); - case EnumAssets::Particle: return loadResourceFromLua_Particle(profile); - case EnumAssets::Animation: return loadResourceFromLua_Animation(profile); - case EnumAssets::Model: return loadResourceFromLua_Model(profile); - case EnumAssets::Texture: return loadResourceFromLua_Texture(profile); - case EnumAssets::Sound: return loadResourceFromLua_Sound(profile); - case EnumAssets::Font: return loadResourceFromLua_Font(profile); + case EnumAssets::Nodestate: loadResourceFromLua_Nodestate(out, domain, key, profile); return; + case EnumAssets::Particle: loadResourceFromLua_Particle(out, domain, key, profile); return; + case EnumAssets::Animation: loadResourceFromLua_Animation(out, domain, key, profile); return; + case EnumAssets::Model: loadResourceFromLua_Model(out, domain, key, profile); return; + case EnumAssets::Texture: loadResourceFromLua_Texture(out, domain, key, profile); return; + case EnumAssets::Sound: loadResourceFromLua_Sound(out, domain, key, profile); return; + case EnumAssets::Font: loadResourceFromLua_Font(out, domain, key, profile); return; default: std::unreachable(); } } -AssetsManager::Resource AssetsManager::loadResourceFromFile_Nodestate(fs::path path) const { +void AssetsManager::loadResourceFromFile_Nodestate(ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const { std::unreachable(); } -AssetsManager::Resource AssetsManager::loadResourceFromFile_Particle(fs::path path) const { +void AssetsManager::loadResourceFromFile_Particle(ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const { std::unreachable(); } -AssetsManager::Resource AssetsManager::loadResourceFromFile_Animation(fs::path path) const { +void AssetsManager::loadResourceFromFile_Animation(ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const { std::unreachable(); } -AssetsManager::Resource AssetsManager::loadResourceFromFile_Model(fs::path path) const { +void AssetsManager::loadResourceFromFile_Model(ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const { /* json, obj, glTF */ std::unreachable(); } -AssetsManager::Resource AssetsManager::loadResourceFromFile_Texture(fs::path path) const { +void AssetsManager::loadResourceFromFile_Texture(ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const { Resource res(path); if(res.size() < 8) @@ -66,10 +66,14 @@ AssetsManager::Resource AssetsManager::loadResourceFromFile_Texture(fs::path pat if(png_check_sig(reinterpret_cast((unsigned char*) res.data()), 8)) { // Это png - return res; + fs::file_time_type lwt = fs::last_write_time(path); + out.NewOrChange[(int) EnumAssets::Texture][domain].emplace_back(key, res, lwt); + return; } else if((int) res.data()[0] == 0xFF && (int) res.data()[1] == 0xD8) { // Это jpeg - return res; + fs::file_time_type lwt = fs::last_write_time(path); + out.NewOrChange[(int) EnumAssets::Texture][domain].emplace_back(key, res, lwt); + return; } else { MAKE_ERROR("Файл не является текстурой png или jpeg"); } @@ -77,65 +81,72 @@ AssetsManager::Resource AssetsManager::loadResourceFromFile_Texture(fs::path pat std::unreachable(); } -AssetsManager::Resource AssetsManager::loadResourceFromFile_Sound(fs::path path) const { +void AssetsManager::loadResourceFromFile_Sound(ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const { std::unreachable(); } -AssetsManager::Resource AssetsManager::loadResourceFromFile_Font(fs::path path) const { +void AssetsManager::loadResourceFromFile_Font(ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const { std::unreachable(); } -AssetsManager::Resource AssetsManager::loadResourceFromLua_Nodestate(const sol::table& profile) const { +void AssetsManager::loadResourceFromLua_Nodestate(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - return AssetsManager::Resource(*path); + out.NewOrChange[(int) EnumAssets::Nodestate][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + return; } std::unreachable(); } -AssetsManager::Resource AssetsManager::loadResourceFromLua_Particle(const sol::table& profile) const { +void AssetsManager::loadResourceFromLua_Particle(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - return AssetsManager::Resource(*path); + out.NewOrChange[(int) EnumAssets::Particle][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + return; } std::unreachable(); } -AssetsManager::Resource AssetsManager::loadResourceFromLua_Animation(const sol::table& profile) const { +void AssetsManager::loadResourceFromLua_Animation(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - return AssetsManager::Resource(*path); + out.NewOrChange[(int) EnumAssets::Animation][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + return; } std::unreachable(); } -AssetsManager::Resource AssetsManager::loadResourceFromLua_Model(const sol::table& profile) const { +void AssetsManager::loadResourceFromLua_Model(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - return AssetsManager::Resource(*path); + out.NewOrChange[(int) EnumAssets::Model][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + return; } std::unreachable(); } -AssetsManager::Resource AssetsManager::loadResourceFromLua_Texture(const sol::table& profile) const { +void AssetsManager::loadResourceFromLua_Texture(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - return AssetsManager::Resource(*path); + out.NewOrChange[(int) EnumAssets::Texture][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + return; } std::unreachable(); } -AssetsManager::Resource AssetsManager::loadResourceFromLua_Sound(const sol::table& profile) const { +void AssetsManager::loadResourceFromLua_Sound(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - return AssetsManager::Resource(*path); + out.NewOrChange[(int) EnumAssets::Sound][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + return; } std::unreachable(); } -AssetsManager::Resource AssetsManager::loadResourceFromLua_Font(const sol::table& profile) const { +void AssetsManager::loadResourceFromLua_Font(ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const { if(std::optional path = profile.get>("path")) { - return AssetsManager::Resource(*path); + out.NewOrChange[(int) EnumAssets::Font][domain].emplace_back(key, AssetsManager::Resource(*path), fs::file_time_type::min()); + return; } std::unreachable(); @@ -165,28 +176,28 @@ std::tuple&> AssetsManager:: if(entry.Empty._Find_first() == entry.Empty.size()) entry.IsFull = true; - id = index*TableEntry::ChunkSize + pos; + id = index*TableEntry::ChunkSize + pos; data = &entry.Entries[pos]; } if(!data) { - table.emplace_back(std::make_unique()); - id = (table.size()-1)*TableEntry::ChunkSize; + table.emplace_back(std::make_unique>()); + id = (table.size()-1)*TableEntry::ChunkSize; data = &table.back()->Entries[0]; } return {id, *data}; } -AssetsManager::Out_recheckResources AssetsManager::recheckResources(const AssetsRegister& info) { - Out_recheckResources result; +AssetsManager::ResourceChangeObj AssetsManager::recheckResources(const AssetsRegister& info) { + ResourceChangeObj result; // Найти пропавшие ресурсы for(int type = 0; type < (int) EnumAssets::MAX_ENUM; type++) { auto lock = LocalObj.lock(); for(auto& [domain, resources] : lock->KeyToId[type]) { for(auto& [key, id] : resources) { - if(!lock->Table[type][id / TableEntry::ChunkSize]->Entries[id % TableEntry::ChunkSize]) + if(!lock->Table[type][id / TableEntry::ChunkSize]->Entries[id % TableEntry::ChunkSize]) continue; bool exists = false; @@ -234,7 +245,6 @@ AssetsManager::Out_recheckResources AssetsManager::recheckResources(const Assets // Найти новые или изменённые ресурсы for(int type = 0; type < (int) EnumAssets::MAX_ENUM; type++) { - for(auto& [domain, resources] : info.Custom[type]) { auto lock = LocalObj.lock(); const auto& keyToId = lock->KeyToId[type]; @@ -257,10 +267,10 @@ AssetsManager::Out_recheckResources AssetsManager::recheckResources(const Assets continue; else if(iterDomain->second.contains(key)) { // Ресурс уже есть, TODO: нужно проверить его изменение - result.NewOrChange[type][domain].emplace_back(key, loadResourceFromFile((EnumAssets) type, "assets/null"), fs::file_time_type::min()); + loadResourceFromFile((EnumAssets) type, result, domain, key, "assets/null"); } else { // Ресурс не был известен - result.NewOrChange[type][domain].emplace_back(key, loadResourceFromFile((EnumAssets) type, "assets/null"), fs::file_time_type::min()); + loadResourceFromFile((EnumAssets) type, result, domain, key, "assets/null"); } findList.insert(key); @@ -315,16 +325,15 @@ AssetsManager::Out_recheckResources AssetsManager::recheckResources(const Assets else if(iterDomain != lock->KeyToId[type].end() && iterDomain->second.contains(key)) { // Ресурс уже есть, TODO: нужно проверить его изменение ResourceId id = iterDomain->second.at(key); - DataEntry& entry = *lock->Table[type][id / TableEntry::ChunkSize]->Entries[id % TableEntry::ChunkSize]; + DataEntry& entry = *lock->Table[type][id / TableEntry::ChunkSize]->Entries[id % TableEntry::ChunkSize]; fs::file_time_type lwt = fs::last_write_time(file); if(lwt != entry.FileChangeTime) // Будем считать что ресурс изменился - result.NewOrChange[type][domain].emplace_back(key, loadResourceFromFile((EnumAssets) type, file), lwt); + loadResourceFromFile((EnumAssets) type, result, domain, key, file); } else { // Ресурс не был известен - fs::file_time_type lwt = fs::last_write_time(file); - result.NewOrChange[type][domain].emplace_back(key, loadResourceFromFile((EnumAssets) type, file), lwt); + loadResourceFromFile((EnumAssets) type, result, domain, key, file); } findList.insert(key); @@ -337,7 +346,7 @@ AssetsManager::Out_recheckResources AssetsManager::recheckResources(const Assets return result; } -AssetsManager::Out_applyResourceChange AssetsManager::applyResourceChange(const Out_recheckResources& orr) { +AssetsManager::Out_applyResourceChange AssetsManager::applyResourceChange(const ResourceChangeObj& orr) { // Потерянные и обновлённые идентификаторы Out_applyResourceChange result; @@ -362,8 +371,8 @@ AssetsManager::Out_applyResourceChange AssetsManager::applyResourceChange(const // keyToIdDomain.erase(iter); // lost[type].push_back(resId); - uint32_t localId = resId % TableEntry::ChunkSize; - auto& chunk = lock->Table[type][resId / TableEntry::ChunkSize]; + uint32_t localId = resId % TableEntry::ChunkSize; + auto& chunk = lock->Table[type][resId / TableEntry::ChunkSize]; // chunk->IsFull = false; // chunk->Empty.set(localId); chunk->Entries[localId].reset(); @@ -383,7 +392,7 @@ AssetsManager::Out_applyResourceChange AssetsManager::applyResourceChange(const if(auto iterId = keyToIdDomain.find(key); iterId != keyToIdDomain.end()) { id = iterId->second; - data = &lock->Table[(int) type][id / TableEntry::ChunkSize]->Entries[id % TableEntry::ChunkSize]; + data = &lock->Table[(int) type][id / TableEntry::ChunkSize]->Entries[id % TableEntry::ChunkSize]; } else { auto [_id, _data] = lock->nextId((EnumAssets) type); id = _id; diff --git a/Src/Server/AssetsManager.hpp b/Src/Server/AssetsManager.hpp index 51ce53b..df9668d 100644 --- a/Src/Server/AssetsManager.hpp +++ b/Src/Server/AssetsManager.hpp @@ -16,6 +16,10 @@ namespace LV::Server { namespace fs = std::filesystem; +struct DefModel { + +}; + /* Работает с ресурсами из папок assets. Использует папку server_cache/assets для хранения @@ -56,6 +60,13 @@ public: Hash_t hash() const { return In->Hash; } }; + struct ResourceChangeObj { + // Потерянные ресурсы + std::unordered_map> Lost[(int) EnumAssets::MAX_ENUM]; + // Домен и ключ ресурса + std::unordered_map>> NewOrChange[(int) EnumAssets::MAX_ENUM]; + }; + private: // Данные об отслеживаемых файлах struct DataEntry { @@ -65,6 +76,7 @@ private: std::string Domain, Key; }; + template struct TableEntry { static constexpr size_t ChunkSize = 4096; bool IsFull = false; @@ -78,7 +90,12 @@ private: struct Local { // Связь ресурсов по идентификаторам - std::vector> Table[(int) EnumAssets::MAX_ENUM]; + std::vector>> Table[(int) EnumAssets::MAX_ENUM]; + + // Распаршенные ресурсы, для использования сервером + std::vector>> Table_NodeState; + std::vector>> Table_Model; + // Связь домены -> {ключ -> идентификатор} std::unordered_map> KeyToId[(int) EnumAssets::MAX_ENUM]; @@ -91,24 +108,24 @@ private: Загрузка ресурса с файла. При необходимости приводится к внутреннему формату и сохраняется в кеше */ - Resource loadResourceFromFile (EnumAssets type, fs::path path) const; - Resource loadResourceFromLua (EnumAssets type, const sol::table& profile) const; + void loadResourceFromFile (EnumAssets type, ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const; + void loadResourceFromLua (EnumAssets type, ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const; - Resource loadResourceFromFile_Nodestate (fs::path path) const; - Resource loadResourceFromFile_Particle (fs::path path) const; - Resource loadResourceFromFile_Animation (fs::path path) const; - Resource loadResourceFromFile_Model (fs::path path) const; - Resource loadResourceFromFile_Texture (fs::path path) const; - Resource loadResourceFromFile_Sound (fs::path path) const; - Resource loadResourceFromFile_Font (fs::path path) const; + void loadResourceFromFile_Nodestate (ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const; + void loadResourceFromFile_Particle (ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const; + void loadResourceFromFile_Animation (ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const; + void loadResourceFromFile_Model (ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const; + void loadResourceFromFile_Texture (ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const; + void loadResourceFromFile_Sound (ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const; + void loadResourceFromFile_Font (ResourceChangeObj& out, const std::string& domain, const std::string& key, fs::path path) const; - Resource loadResourceFromLua_Nodestate (const sol::table& profile) const; - Resource loadResourceFromLua_Particle (const sol::table& profile) const; - Resource loadResourceFromLua_Animation (const sol::table& profile) const; - Resource loadResourceFromLua_Model (const sol::table& profile) const; - Resource loadResourceFromLua_Texture (const sol::table& profile) const; - Resource loadResourceFromLua_Sound (const sol::table& profile) const; - Resource loadResourceFromLua_Font (const sol::table& profile) const; + void loadResourceFromLua_Nodestate (ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const; + void loadResourceFromLua_Particle (ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const; + void loadResourceFromLua_Animation (ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const; + void loadResourceFromLua_Model (ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const; + void loadResourceFromLua_Texture (ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const; + void loadResourceFromLua_Sound (ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const; + void loadResourceFromLua_Font (ResourceChangeObj& out, const std::string& domain, const std::string& key, const sol::table& profile) const; public: AssetsManager(asio::io_context& ioc); @@ -137,14 +154,7 @@ public: std::unordered_map> Custom[(int) EnumAssets::MAX_ENUM]; }; - struct Out_recheckResources { - // Потерянные ресурсы - std::unordered_map> Lost[(int) EnumAssets::MAX_ENUM]; - // Домен и ключ ресурса - std::unordered_map>> NewOrChange[(int) EnumAssets::MAX_ENUM]; - }; - - Out_recheckResources recheckResources(const AssetsRegister&); + ResourceChangeObj recheckResources(const AssetsRegister&); /* Применяет расчитанные изменения. @@ -155,7 +165,7 @@ public: std::vector> NewOrChange[(int) EnumAssets::MAX_ENUM]; }; - Out_applyResourceChange applyResourceChange(const Out_recheckResources& orr); + Out_applyResourceChange applyResourceChange(const ResourceChangeObj& orr); /* Выдаёт идентификатор ресурса, даже если он не существует или был удалён. @@ -177,8 +187,8 @@ public: std::optional> getResource(EnumAssets type, ResourceId id) { auto lock = LocalObj.lock(); - assert(id < lock->Table[(int) type].size()*TableEntry::ChunkSize); - auto& value = lock->Table[(int) type][id / TableEntry::ChunkSize]->Entries[id % TableEntry::ChunkSize]; + assert(id < lock->Table[(int) type].size()*TableEntry::ChunkSize); + auto& value = lock->Table[(int) type][id / TableEntry::ChunkSize]->Entries[id % TableEntry::ChunkSize]; if(value) return {{value->Res, value->Domain, value->Key}}; else diff --git a/Src/Server/RemoteClient.cpp b/Src/Server/RemoteClient.cpp index fe8f89f..d4165b3 100644 --- a/Src/Server/RemoteClient.cpp +++ b/Src/Server/RemoteClient.cpp @@ -798,7 +798,7 @@ void RemoteClient::onUpdate() { } std::vector> RemoteClient::getViewPoints() { - return {{0, CameraPos, 2}}; + return {{0, CameraPos, 1}}; } } \ No newline at end of file diff --git a/Src/assets.py b/Src/assets.py index 5cb81c5..64ed10d 100755 --- a/Src/assets.py +++ b/Src/assets.py @@ -2,22 +2,28 @@ import sys import re -output_file = "resources.cpp" -with open(output_file, "w") as f: +if len(sys.argv) < 3: + print("Usage: assets.py [file2 ...]") + sys.exit(1) + +output_cpp = sys.argv[1] +symbols = sys.argv[2:] + +with open(output_cpp, "w") as f: f.write("#include \n#include \n#include \n\nextern \"C\" {\n") - for symbol in sys.argv[1:]: + for symbol in symbols: var_name = "_binary_" + re.sub('[^a-zA-Z0-9]', '_', symbol) f.write(f"\textern const char {var_name}_start[];\n\textern const char {var_name}_end[];\n") - f.write("}") + f.write("}\n\n") - f.write("\n\nstd::unordered_map> _binary_assets_symbols = {\n") + f.write("std::unordered_map> _binary_assets_symbols = {\n") - for symbol in sys.argv[1:]: + for symbol in symbols: var_name = "_binary_" + re.sub('[^a-zA-Z0-9]', '_', symbol) f.write(f"\t{{\"{symbol}\", {{(const char*) &{var_name}_start, (const char*) &{var_name}_end}}}},\n") f.write("};\n") -print(f"File {output_file} is generated.") +print(f"File {output_cpp} is generated.")