*
This commit is contained in:
@@ -31,11 +31,11 @@ project(LuaVox VERSION 0.0 DESCRIPTION "LuaVox Description")
|
|||||||
add_library(luavox_common INTERFACE)
|
add_library(luavox_common INTERFACE)
|
||||||
target_compile_features(luavox_common INTERFACE cxx_std_23)
|
target_compile_features(luavox_common INTERFACE cxx_std_23)
|
||||||
|
|
||||||
# if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
# target_compile_options(luavox_common INTERFACE -fsanitize=address,undefined -fno-omit-frame-pointer -fno-sanitize-recover=all)
|
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)
|
target_link_options(luavox_common INTERFACE -fsanitize=address,undefined)
|
||||||
# set(ENV{ASAN_OPTIONS} detect_leaks=0)
|
set(ENV{ASAN_OPTIONS} detect_leaks=0)
|
||||||
# endif()
|
endif()
|
||||||
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
|
||||||
target_compile_options(luavox_common INTERFACE -fcoroutines)
|
target_compile_options(luavox_common INTERFACE -fcoroutines)
|
||||||
|
|||||||
@@ -1440,7 +1440,7 @@ std::pair<float, std::variant<PreparedNodeState::Model, PreparedNodeState::Vecto
|
|||||||
if(const auto model_key = model.try_as_string()) {
|
if(const auto model_key = model.try_as_string()) {
|
||||||
// Одна модель
|
// Одна модель
|
||||||
Model result;
|
Model result;
|
||||||
result.UVLock = uvlock;
|
result.UVLock = false;
|
||||||
result.Transforms = std::move(transforms);
|
result.Transforms = std::move(transforms);
|
||||||
|
|
||||||
auto [domain, key] = parseDomainKey((std::string) *model_key, modid);
|
auto [domain, key] = parseDomainKey((std::string) *model_key, modid);
|
||||||
@@ -1548,8 +1548,8 @@ PreparedModel::PreparedModel(const std::string_view modid, const js::object& pro
|
|||||||
GuiLight = EnumGuiLight::Default;
|
GuiLight = EnumGuiLight::Default;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(profile.contains("AmbientOcclusion")) {
|
if(profile.contains("ambient_occlusion")) {
|
||||||
AmbientOcclusion = profile.at("ambientocclusion").as_bool();
|
AmbientOcclusion = profile.at("ambient_occlusion").as_bool();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(profile.contains("display")) {
|
if(profile.contains("display")) {
|
||||||
@@ -1588,7 +1588,6 @@ PreparedModel::PreparedModel(const std::string_view modid, const js::object& pro
|
|||||||
|
|
||||||
Display[key] = result;
|
Display[key] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(boost::system::result<const js::value&> textures_val = profile.try_at("textures")) {
|
if(boost::system::result<const js::value&> textures_val = profile.try_at("textures")) {
|
||||||
@@ -1745,13 +1744,22 @@ PreparedModel::PreparedModel(const std::string_view modid, const js::object& pro
|
|||||||
|
|
||||||
for(const js::value& sub_val : subModels) {
|
for(const js::value& sub_val : subModels) {
|
||||||
SubModel result;
|
SubModel result;
|
||||||
const js::object& sub = sub_val.as_object();
|
|
||||||
auto [domain, key] = parseDomainKey((std::string) sub.at("path").as_string(), modid);
|
|
||||||
result.Domain = std::move(domain);
|
|
||||||
result.Key = std::move(key);
|
|
||||||
|
|
||||||
if(boost::system::result<const js::value&> scene_val = profile.try_at("scene"))
|
if(auto path = sub_val.try_as_string()) {
|
||||||
result.Scene = scene_val->to_number<uint16_t>();
|
auto [domain, key] = parseDomainKey((std::string) path.value(), modid);
|
||||||
|
result.Domain = std::move(domain);
|
||||||
|
result.Key = std::move(key);
|
||||||
|
} else {
|
||||||
|
const js::object& sub = sub_val.as_object();
|
||||||
|
auto [domain, key] = parseDomainKey((std::string) sub.at("path").as_string(), modid);
|
||||||
|
result.Domain = std::move(domain);
|
||||||
|
result.Key = std::move(key);
|
||||||
|
|
||||||
|
if(boost::system::result<const js::value&> scene_val = profile.try_at("scene"))
|
||||||
|
result.Scene = scene_val->to_number<uint16_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
SubModels.emplace_back(std::move(result));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -673,7 +673,7 @@ enum struct TexturePipelineCMD : uint8_t {
|
|||||||
using Hash_t = std::array<uint8_t, 32>;
|
using Hash_t = std::array<uint8_t, 32>;
|
||||||
|
|
||||||
inline std::pair<std::string, std::string> parseDomainKey(const std::string& value, const std::string_view defaultDomain = "core") {
|
inline std::pair<std::string, std::string> parseDomainKey(const std::string& value, const std::string_view defaultDomain = "core") {
|
||||||
auto regResult = TOS::Str::match(value, "(?:([\\w\\d_]+):)?([\\w\\d_]+)");
|
auto regResult = TOS::Str::match(value, "(?:([\\w\\d_]+):)?([\\w\\d/_.]+)");
|
||||||
if(!regResult)
|
if(!regResult)
|
||||||
MAKE_ERROR("Недействительный домен:ключ");
|
MAKE_ERROR("Недействительный домен:ключ");
|
||||||
|
|
||||||
|
|||||||
@@ -116,17 +116,19 @@ void AssetsManager::loadResourceFromFile_Model(ResourceChangeObj& out, const std
|
|||||||
std::filesystem::file_time_type ftt = fs::last_write_time(path);
|
std::filesystem::file_time_type ftt = fs::last_write_time(path);
|
||||||
PreparedModel pmc;
|
PreparedModel pmc;
|
||||||
|
|
||||||
if(path.extension() == "json") {
|
auto extension = path.extension();
|
||||||
|
|
||||||
|
if(extension == ".json") {
|
||||||
js::object obj = js::parse(std::string_view((const char*) res.data(), res.size())).as_object();
|
js::object obj = js::parse(std::string_view((const char*) res.data(), res.size())).as_object();
|
||||||
LV::PreparedModel pm(domain, obj);
|
LV::PreparedModel pm(domain, obj);
|
||||||
std::u8string data = pm.dump();
|
std::u8string data = pm.dump();
|
||||||
pmc = PreparedModel(domain, pm);
|
pmc = PreparedModel(domain, pm);
|
||||||
out.NewOrChange[(int) EnumAssets::Model][domain].emplace_back(key, Resource((const uint8_t*) data.data(), data.size()), ftt);
|
out.NewOrChange[(int) EnumAssets::Model][domain].emplace_back(key, Resource((const uint8_t*) data.data(), data.size()), ftt);
|
||||||
} else if(path.extension() == "gltf") {
|
} else if(extension == ".gltf") {
|
||||||
js::object obj = js::parse(std::string_view((const char*) res.data(), res.size())).as_object();
|
js::object obj = js::parse(std::string_view((const char*) res.data(), res.size())).as_object();
|
||||||
pmc = PreparedModel(domain, obj);
|
pmc = PreparedModel(domain, obj);
|
||||||
out.NewOrChange[(int) EnumAssets::Model][domain].emplace_back(key, res, ftt);
|
out.NewOrChange[(int) EnumAssets::Model][domain].emplace_back(key, res, ftt);
|
||||||
} else if(path.extension() == "glb") {
|
} else if(extension == ".glb") {
|
||||||
pmc = PreparedModel(domain, res);
|
pmc = PreparedModel(domain, res);
|
||||||
out.NewOrChange[(int) EnumAssets::Model][domain].emplace_back(key, res, ftt);
|
out.NewOrChange[(int) EnumAssets::Model][domain].emplace_back(key, res, ftt);
|
||||||
} else {
|
} else {
|
||||||
@@ -251,7 +253,7 @@ std::tuple<ResourceId, std::optional<AssetsManager::DataEntry>&> AssetsManager::
|
|||||||
uint32_t pos = entry.Empty._Find_first();
|
uint32_t pos = entry.Empty._Find_first();
|
||||||
entry.Empty.reset(pos);
|
entry.Empty.reset(pos);
|
||||||
|
|
||||||
if(entry.Empty._Find_first() == entry.Empty.size())
|
if(entry.Empty._Find_next(pos) == entry.Empty.size())
|
||||||
entry.IsFull = true;
|
entry.IsFull = true;
|
||||||
|
|
||||||
id = index*TableEntry<DataEntry>::ChunkSize + pos;
|
id = index*TableEntry<DataEntry>::ChunkSize + pos;
|
||||||
@@ -262,6 +264,7 @@ std::tuple<ResourceId, std::optional<AssetsManager::DataEntry>&> AssetsManager::
|
|||||||
table.emplace_back(std::make_unique<TableEntry<DataEntry>>());
|
table.emplace_back(std::make_unique<TableEntry<DataEntry>>());
|
||||||
id = (table.size()-1)*TableEntry<DataEntry>::ChunkSize;
|
id = (table.size()-1)*TableEntry<DataEntry>::ChunkSize;
|
||||||
data = &table.back()->Entries[0];
|
data = &table.back()->Entries[0];
|
||||||
|
table.back()->Empty.reset(0);
|
||||||
|
|
||||||
// Расширяем таблицу с ресурсами, если необходимо
|
// Расширяем таблицу с ресурсами, если необходимо
|
||||||
if(type == EnumAssets::Nodestate)
|
if(type == EnumAssets::Nodestate)
|
||||||
@@ -517,8 +520,8 @@ AssetsManager::Out_applyResourceChange AssetsManager::applyResourceChange(const
|
|||||||
|
|
||||||
std::vector<AssetsModel> models;
|
std::vector<AssetsModel> models;
|
||||||
|
|
||||||
for(auto& [domain, key] : value.ModelToLocalId) {
|
for(auto& [domain2, key2] : value.ModelToLocalId) {
|
||||||
models.push_back(lock->getId(EnumAssets::Model, domain, key));
|
models.push_back(lock->getId(EnumAssets::Model, domain2, key2));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -542,14 +545,18 @@ AssetsManager::Out_applyResourceChange AssetsManager::applyResourceChange(const
|
|||||||
ResourceId resId = lock->getId(EnumAssets::Model, domain, key);
|
ResourceId resId = lock->getId(EnumAssets::Model, domain, key);
|
||||||
|
|
||||||
ModelDependency deps;
|
ModelDependency deps;
|
||||||
for(auto& [domain, list] : value.ModelDependencies) {
|
for(auto& [domain2, list] : value.ModelDependencies) {
|
||||||
ResourceId subResId = lock->getId(EnumAssets::Model, domain, key);
|
for(const std::string& key2 : list) {
|
||||||
deps.ModelDeps.push_back(subResId);
|
ResourceId subResId = lock->getId(EnumAssets::Model, domain2, key2);
|
||||||
|
deps.ModelDeps.push_back(subResId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& [domain, list] : value.TextureDependencies) {
|
for(auto& [domain2, list] : value.TextureDependencies) {
|
||||||
ResourceId subResId = lock->getId(EnumAssets::Texture, domain, key);
|
for(const std::string& key2 : list) {
|
||||||
deps.TextureDeps.push_back(subResId);
|
ResourceId subResId = lock->getId(EnumAssets::Texture, domain2, key2);
|
||||||
|
deps.TextureDeps.push_back(subResId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lock->Table_Model[resId / TableEntry<DataEntry>::ChunkSize]
|
lock->Table_Model[resId / TableEntry<DataEntry>::ChunkSize]
|
||||||
@@ -574,7 +581,8 @@ AssetsManager::Out_applyResourceChange AssetsManager::applyResourceChange(const
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Вычисляем зависимости
|
// Вычисляем зависимости
|
||||||
std::function<void(AssetsModel resId, ModelDependency&)> calcDeps = [&](AssetsModel resId, ModelDependency& entry) {
|
std::function<void(AssetsModel resId, ModelDependency&)> calcDeps;
|
||||||
|
calcDeps = [&](AssetsModel resId, ModelDependency& entry) {
|
||||||
for(AssetsModel subResId : entry.ModelDeps) {
|
for(AssetsModel subResId : entry.ModelDeps) {
|
||||||
auto& model = lock->Table_Model[subResId / TableEntry<ModelDependency>::ChunkSize]
|
auto& model = lock->Table_Model[subResId / TableEntry<ModelDependency>::ChunkSize]
|
||||||
->Entries[subResId % TableEntry<ModelDependency>::ChunkSize];
|
->Entries[subResId % TableEntry<ModelDependency>::ChunkSize];
|
||||||
@@ -582,6 +590,14 @@ AssetsManager::Out_applyResourceChange AssetsManager::applyResourceChange(const
|
|||||||
if(!model)
|
if(!model)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if(resId == subResId) {
|
||||||
|
const auto object1 = lock->getResource(EnumAssets::Model, resId);
|
||||||
|
const auto object2 = lock->getResource(EnumAssets::Model, subResId);
|
||||||
|
LOG.warn() << "В моделе " << std::get<1>(*object1) << ':' << std::get<2>(*object1)
|
||||||
|
<< " обнаружена циклическая зависимость с самой собою";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(!model->Ready)
|
if(!model->Ready)
|
||||||
calcDeps(subResId, *model);
|
calcDeps(subResId, *model);
|
||||||
|
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ public:
|
|||||||
getNodeDependency(const std::string& domain, const std::string& key)
|
getNodeDependency(const std::string& domain, const std::string& key)
|
||||||
{
|
{
|
||||||
auto lock = LocalObj.lock();
|
auto lock = LocalObj.lock();
|
||||||
AssetsNodestate nodestateId = lock->getId(EnumAssets::Nodestate, domain, key);
|
AssetsNodestate nodestateId = lock->getId(EnumAssets::Nodestate, domain, key+".json");
|
||||||
|
|
||||||
std::vector<AssetsModel> models;
|
std::vector<AssetsModel> models;
|
||||||
std::vector<AssetsTexture> textures;
|
std::vector<AssetsTexture> textures;
|
||||||
|
|||||||
@@ -1444,13 +1444,13 @@ void GameServer::init(fs::path worldPath) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
sol::table t = LuaMainState.create_table();
|
sol::table t = LuaMainState.create_table();
|
||||||
Content.CM.registerBase(EnumDefContent::Node, "core", "test0", t);
|
Content.CM.registerBase(EnumDefContent::Node, "test", "test0", t);
|
||||||
Content.CM.registerBase(EnumDefContent::Node, "core", "test1", t);
|
Content.CM.registerBase(EnumDefContent::Node, "test", "test1", t);
|
||||||
Content.CM.registerBase(EnumDefContent::Node, "core", "test2", t);
|
Content.CM.registerBase(EnumDefContent::Node, "test", "test2", t);
|
||||||
Content.CM.registerBase(EnumDefContent::Node, "core", "test3", t);
|
Content.CM.registerBase(EnumDefContent::Node, "test", "test3", t);
|
||||||
Content.CM.registerBase(EnumDefContent::Node, "core", "test4", t);
|
Content.CM.registerBase(EnumDefContent::Node, "test", "test4", t);
|
||||||
Content.CM.registerBase(EnumDefContent::Node, "core", "test5", t);
|
Content.CM.registerBase(EnumDefContent::Node, "test", "test5", t);
|
||||||
Content.CM.registerBase(EnumDefContent::World, "core", "devel_world", t);
|
Content.CM.registerBase(EnumDefContent::World, "test", "devel_world", t);
|
||||||
}
|
}
|
||||||
|
|
||||||
initLuaPre();
|
initLuaPre();
|
||||||
@@ -1513,15 +1513,15 @@ void GameServer::prerun() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GameServer::run() {
|
void GameServer::run() {
|
||||||
{
|
// {
|
||||||
IWorldSaveBackend::TickSyncInfo_In in;
|
// IWorldSaveBackend::TickSyncInfo_In in;
|
||||||
for(int x = -1; x <= 1; x++)
|
// for(int x = -1; x <= 1; x++)
|
||||||
for(int y = -1; y <= 1; y++)
|
// for(int y = -1; y <= 1; y++)
|
||||||
for(int z = -1; z <= 1; z++)
|
// for(int z = -1; z <= 1; z++)
|
||||||
in.Load[0].push_back(Pos::GlobalChunk(x, y, z));
|
// in.Load[0].push_back(Pos::GlobalChunk(x, y, z));
|
||||||
|
|
||||||
stepGeneratorAndLuaAsync(SaveBackend.World->tickSync(std::move(in)));
|
// stepGeneratorAndLuaAsync(SaveBackend.World->tickSync(std::move(in)));
|
||||||
}
|
// }
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
((uint32_t&) Game.AfterStartTime) += (uint32_t) (CurrentTickDuration*256);
|
((uint32_t&) Game.AfterStartTime) += (uint32_t) (CurrentTickDuration*256);
|
||||||
@@ -2467,13 +2467,20 @@ void GameServer::stepSyncContent() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for(std::shared_ptr<RemoteClient>& remoteClient : Game.RemoteClients) {
|
for(std::shared_ptr<RemoteClient>& remoteClient : Game.RemoteClients) {
|
||||||
remoteClient->informateAssets(resources);
|
if(!resources.empty())
|
||||||
remoteClient->informateDefVoxel(voxels);
|
remoteClient->informateAssets(resources);
|
||||||
remoteClient->informateDefNode(nodes);
|
if(!voxels.empty())
|
||||||
remoteClient->informateDefWorld(worlds);
|
remoteClient->informateDefVoxel(voxels);
|
||||||
remoteClient->informateDefPortal(portals);
|
if(!nodes.empty())
|
||||||
remoteClient->informateDefEntity(entities);
|
remoteClient->informateDefNode(nodes);
|
||||||
remoteClient->informateDefItem(items);
|
if(!worlds.empty())
|
||||||
|
remoteClient->informateDefWorld(worlds);
|
||||||
|
if(!portals.empty())
|
||||||
|
remoteClient->informateDefPortal(portals);
|
||||||
|
if(!entities.empty())
|
||||||
|
remoteClient->informateDefEntity(entities);
|
||||||
|
if(!items.empty())
|
||||||
|
remoteClient->informateDefItem(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user