*
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -1266,7 +1266,7 @@ void VulkanRenderSession::pushStage(EnumRenderStage stage) {
|
||||
VKCTX->ThreadVertexObj.join();
|
||||
}
|
||||
|
||||
std::vector<VoxelVertexPoint> VulkanRenderSession::generateMeshForVoxelChunks(const std::vector<VoxelCube> cubes) {
|
||||
std::vector<VoxelVertexPoint> VulkanRenderSession::generateMeshForVoxelChunks(const std::vector<VoxelCube>& cubes) {
|
||||
std::vector<VoxelVertexPoint> out;
|
||||
out.reserve(cubes.size()*6);
|
||||
|
||||
|
||||
@@ -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<VoxelVertexPoint> generateMeshForVoxelChunks(const std::vector<VoxelCube> cubes);
|
||||
static std::vector<VoxelVertexPoint> generateMeshForVoxelChunks(const std::vector<VoxelCube>& cubes);
|
||||
static std::vector<NodeVertexStatic> generateMeshForNodeChunks(const Node* nodes);
|
||||
|
||||
private:
|
||||
|
||||
@@ -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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,10 +9,15 @@
|
||||
#include <memory>
|
||||
#include <sol/forward.hpp>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <boost/json.hpp>
|
||||
|
||||
|
||||
namespace LV {
|
||||
|
||||
namespace js = boost::json;
|
||||
|
||||
namespace Pos {
|
||||
|
||||
template<typename T, size_t BitsPerComponent>
|
||||
@@ -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<Num, Var, Unary, Binary> v;
|
||||
};
|
||||
|
||||
struct Transformation {
|
||||
int a; float b;
|
||||
};
|
||||
|
||||
struct Model {
|
||||
uint16_t Id;
|
||||
bool UVLock = false;
|
||||
std::vector<Transformation> Transforms;
|
||||
};
|
||||
|
||||
struct VectorModel {
|
||||
std::vector<Model> Models;
|
||||
bool UVLock = false;
|
||||
// Может добавить возможность использовать переменную рандома в трансформациях?
|
||||
std::vector<Transformation> Transforms;
|
||||
};
|
||||
|
||||
// Локальный идентификатор в именной ресурс
|
||||
std::vector<std::pair<std::string, std::string>> ResourceToLocalId;
|
||||
// Ноды выражений
|
||||
std::vector<Node> Nodes;
|
||||
// Условия -> вариации модели + веса
|
||||
std::vector<
|
||||
std::pair<uint16_t,
|
||||
boost::container::small_vector<
|
||||
std::pair<std::variant<Model, VectorModel>, 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<AssetsTexture> 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<uint8_t, 32>;
|
||||
|
||||
}
|
||||
|
||||
@@ -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<png_bytep>((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<std::string> path = profile.get<std::optional<std::string>>("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<std::string> path = profile.get<std::optional<std::string>>("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<std::string> path = profile.get<std::optional<std::string>>("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<std::string> path = profile.get<std::optional<std::string>>("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<std::string> path = profile.get<std::optional<std::string>>("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<std::string> path = profile.get<std::optional<std::string>>("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<std::string> path = profile.get<std::optional<std::string>>("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<ResourceId, std::optional<AssetsManager::DataEntry>&> AssetsManager::
|
||||
if(entry.Empty._Find_first() == entry.Empty.size())
|
||||
entry.IsFull = true;
|
||||
|
||||
id = index*TableEntry::ChunkSize + pos;
|
||||
id = index*TableEntry<DataEntry>::ChunkSize + pos;
|
||||
data = &entry.Entries[pos];
|
||||
}
|
||||
|
||||
if(!data) {
|
||||
table.emplace_back(std::make_unique<TableEntry>());
|
||||
id = (table.size()-1)*TableEntry::ChunkSize;
|
||||
table.emplace_back(std::make_unique<TableEntry<DataEntry>>());
|
||||
id = (table.size()-1)*TableEntry<DataEntry>::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<DataEntry>::ChunkSize]->Entries[id % TableEntry<DataEntry>::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<DataEntry>::ChunkSize]->Entries[id % TableEntry<DataEntry>::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<DataEntry>::ChunkSize;
|
||||
auto& chunk = lock->Table[type][resId / TableEntry<DataEntry>::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<DataEntry>::ChunkSize]->Entries[id % TableEntry<DataEntry>::ChunkSize];
|
||||
} else {
|
||||
auto [_id, _data] = lock->nextId((EnumAssets) type);
|
||||
id = _id;
|
||||
|
||||
@@ -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<std::string, std::vector<std::string>> Lost[(int) EnumAssets::MAX_ENUM];
|
||||
// Домен и ключ ресурса
|
||||
std::unordered_map<std::string, std::vector<std::tuple<std::string, Resource, fs::file_time_type>>> NewOrChange[(int) EnumAssets::MAX_ENUM];
|
||||
};
|
||||
|
||||
private:
|
||||
// Данные об отслеживаемых файлах
|
||||
struct DataEntry {
|
||||
@@ -65,6 +76,7 @@ private:
|
||||
std::string Domain, Key;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct TableEntry {
|
||||
static constexpr size_t ChunkSize = 4096;
|
||||
bool IsFull = false;
|
||||
@@ -78,7 +90,12 @@ private:
|
||||
|
||||
struct Local {
|
||||
// Связь ресурсов по идентификаторам
|
||||
std::vector<std::unique_ptr<TableEntry>> Table[(int) EnumAssets::MAX_ENUM];
|
||||
std::vector<std::unique_ptr<TableEntry<DataEntry>>> Table[(int) EnumAssets::MAX_ENUM];
|
||||
|
||||
// Распаршенные ресурсы, для использования сервером
|
||||
std::vector<std::unique_ptr<TableEntry<DefNodeState>>> Table_NodeState;
|
||||
std::vector<std::unique_ptr<TableEntry<DefModel>>> Table_Model;
|
||||
|
||||
// Связь домены -> {ключ -> идентификатор}
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, ResourceId>> 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<std::string, std::unordered_map<std::string, void*>> Custom[(int) EnumAssets::MAX_ENUM];
|
||||
};
|
||||
|
||||
struct Out_recheckResources {
|
||||
// Потерянные ресурсы
|
||||
std::unordered_map<std::string, std::vector<std::string>> Lost[(int) EnumAssets::MAX_ENUM];
|
||||
// Домен и ключ ресурса
|
||||
std::unordered_map<std::string, std::vector<std::tuple<std::string, Resource, fs::file_time_type>>> NewOrChange[(int) EnumAssets::MAX_ENUM];
|
||||
};
|
||||
|
||||
Out_recheckResources recheckResources(const AssetsRegister&);
|
||||
ResourceChangeObj recheckResources(const AssetsRegister&);
|
||||
|
||||
/*
|
||||
Применяет расчитанные изменения.
|
||||
@@ -155,7 +165,7 @@ public:
|
||||
std::vector<std::pair<ResourceId, Resource>> 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<std::tuple<Resource, const std::string&, const std::string&>> 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<DataEntry>::ChunkSize);
|
||||
auto& value = lock->Table[(int) type][id / TableEntry<DataEntry>::ChunkSize]->Entries[id % TableEntry<DataEntry>::ChunkSize];
|
||||
if(value)
|
||||
return {{value->Res, value->Domain, value->Key}};
|
||||
else
|
||||
|
||||
@@ -798,7 +798,7 @@ void RemoteClient::onUpdate() {
|
||||
}
|
||||
|
||||
std::vector<std::tuple<WorldId_t, Pos::Object, uint8_t>> RemoteClient::getViewPoints() {
|
||||
return {{0, CameraPos, 2}};
|
||||
return {{0, CameraPos, 1}};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 <output_cpp> <file1> [file2 ...]")
|
||||
sys.exit(1)
|
||||
|
||||
output_cpp = sys.argv[1]
|
||||
symbols = sys.argv[2:]
|
||||
|
||||
with open(output_cpp, "w") as f:
|
||||
f.write("#include <unordered_map>\n#include <string>\n#include <tuple>\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<std::string, std::tuple<const char*, const char*>> _binary_assets_symbols = {\n")
|
||||
f.write("std::unordered_map<std::string, std::tuple<const char*, const char*>> _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.")
|
||||
|
||||
Reference in New Issue
Block a user