Переработка интерфейса предоставления данных клиентам
This commit is contained in:
@@ -71,7 +71,7 @@ PrecompiledTexturePipeline compileTexturePipeline(const std::string &cmd, std::s
|
||||
}
|
||||
|
||||
|
||||
CompressedVoxels compressVoxels_byte(const std::vector<VoxelCube>& voxels) {
|
||||
std::u8string compressVoxels_byte(const std::vector<VoxelCube>& voxels) {
|
||||
std::u8string compressed;
|
||||
std::vector<DefVoxelId> defines;
|
||||
DefVoxelId maxValue = 0;
|
||||
@@ -164,10 +164,10 @@ CompressedVoxels compressVoxels_byte(const std::vector<VoxelCube>& voxels) {
|
||||
}
|
||||
}
|
||||
|
||||
return {compressLinear(compressed), defines};
|
||||
return compressLinear(compressed);
|
||||
}
|
||||
|
||||
CompressedVoxels compressVoxels_bit(const std::vector<VoxelCube>& voxels) {
|
||||
std::u8string compressVoxels_bit(const std::vector<VoxelCube>& voxels) {
|
||||
std::vector<DefVoxelId> profile;
|
||||
std::vector<DefVoxelId> one_byte[7];
|
||||
|
||||
@@ -310,10 +310,10 @@ CompressedVoxels compressVoxels_bit(const std::vector<VoxelCube>& voxels) {
|
||||
for(size_t iter = 0; iter < buff.size(); iter++)
|
||||
compressed[iter / 8] |= (buff[iter] << (iter % 8));
|
||||
|
||||
return {compressLinear(compressed), profile};
|
||||
return compressLinear(compressed);
|
||||
}
|
||||
|
||||
CompressedVoxels compressVoxels(const std::vector<VoxelCube>& voxels, bool fast) {
|
||||
std::u8string compressVoxels(const std::vector<VoxelCube>& voxels, bool fast) {
|
||||
if(fast)
|
||||
return compressVoxels_byte(voxels);
|
||||
else
|
||||
@@ -697,24 +697,8 @@ CompressedNodes compressNodes_bit(const Node* nodes) {
|
||||
return {compressLinear(compressed), profiles};
|
||||
}
|
||||
|
||||
CompressedNodes compressNodes(const Node* nodes, bool fast) {
|
||||
std::u8string data(16*16*16*sizeof(Node), '\0');
|
||||
const char8_t *ptr = (const char8_t*) nodes;
|
||||
std::copy(ptr, ptr+16*16*16*4, data.data());
|
||||
|
||||
std::vector<DefNodeId> node(16*16*16);
|
||||
for(int iter = 0; iter < 16*16*16; iter++) {
|
||||
node[iter] = nodes[iter].NodeId;
|
||||
}
|
||||
|
||||
{
|
||||
std::sort(node.begin(), node.end());
|
||||
auto last = std::unique(node.begin(), node.end());
|
||||
node.erase(last, node.end());
|
||||
node.shrink_to_fit();
|
||||
}
|
||||
|
||||
return {compressLinear(data), std::move(node)};
|
||||
std::u8string compressNodes(const Node* nodes, bool fast) {
|
||||
return compressLinear(std::u8string_view((const char8_t*) nodes, 16*16*16*sizeof(Node)));
|
||||
|
||||
// if(fast)
|
||||
// return compressNodes_byte(nodes);
|
||||
@@ -854,7 +838,7 @@ void unCompressNodes(const std::u8string& compressed, Node* ptr) {
|
||||
// return unCompressNodes_bit(next, ptr);
|
||||
}
|
||||
|
||||
std::u8string compressLinear(const std::u8string& data) {
|
||||
std::u8string compressLinear(std::u8string_view data) {
|
||||
std::stringstream in;
|
||||
in.write((const char*) data.data(), data.size());
|
||||
|
||||
@@ -869,7 +853,7 @@ std::u8string compressLinear(const std::u8string& data) {
|
||||
return *(std::u8string*) &outString;
|
||||
}
|
||||
|
||||
std::u8string unCompressLinear(const std::u8string& data) {
|
||||
std::u8string unCompressLinear(std::u8string_view data) {
|
||||
std::stringstream in;
|
||||
in.write((const char*) data.data(), data.size());
|
||||
|
||||
@@ -1488,7 +1472,7 @@ uint16_t PreparedNodeState::parseCondition(const std::string_view expression) {
|
||||
// };
|
||||
}
|
||||
|
||||
std::pair<float, std::variant<PreparedNodeState::Model, PreparedNodeState::VectorModel>> PreparedNodeState::parseModel(const std::string_view modid, const js::object& obj) {
|
||||
std::pair<float, std::variant<HeadlessNodeState::Model, HeadlessNodeState::VectorModel>> HeadlessNodeState::parseModel(const std::string_view modid, const js::object& obj) {
|
||||
// ModelToLocalId
|
||||
|
||||
bool uvlock;
|
||||
|
||||
@@ -469,13 +469,7 @@ struct VoxelCube {
|
||||
}
|
||||
};
|
||||
|
||||
struct CompressedVoxels {
|
||||
std::u8string Compressed;
|
||||
// Уникальный сортированный список идентификаторов вокселей
|
||||
std::vector<DefVoxelId> Defines;
|
||||
};
|
||||
|
||||
CompressedVoxels compressVoxels(const std::vector<VoxelCube>& voxels, bool fast = true);
|
||||
std::u8string compressVoxels(const std::vector<VoxelCube>& voxels, bool fast = true);
|
||||
std::vector<VoxelCube> unCompressVoxels(const std::u8string& compressed);
|
||||
|
||||
struct Node {
|
||||
@@ -493,11 +487,11 @@ struct CompressedNodes {
|
||||
std::vector<DefNodeId> Defines;
|
||||
};
|
||||
|
||||
CompressedNodes compressNodes(const Node* nodes, bool fast = true);
|
||||
void unCompressNodes(const std::u8string& compressed, Node* ptr);
|
||||
std::u8string compressNodes(const Node* nodes, bool fast = true);
|
||||
void unCompressNodes(std::u8string_view compressed, Node* ptr);
|
||||
|
||||
std::u8string compressLinear(const std::u8string& data);
|
||||
std::u8string unCompressLinear(const std::u8string& data);
|
||||
std::u8string compressLinear(std::u8string_view data);
|
||||
std::u8string unCompressLinear(std::u8string_view data);
|
||||
|
||||
inline std::pair<std::string_view, std::string_view> parseDomainKey(const std::string_view value, const std::string_view defaultDomain = "core") {
|
||||
size_t pos = value.find(':');
|
||||
|
||||
@@ -262,7 +262,7 @@ AssetsPreloader::Out_reloadResources AssetsPreloader::_reloadResources(const Ass
|
||||
// Домен неизвестен движку, все ресурсы в нём новые
|
||||
for(const auto& [key, info] : table) {
|
||||
PendingResource resource = buildResource(static_cast<AssetType>(type), domain, key, info);
|
||||
result.NewOrChange[(int) type][domain].push_back(std::move(resource));
|
||||
result.NewOrChange[type][domain].push_back(std::move(resource));
|
||||
}
|
||||
} else {
|
||||
for(const auto& [key, info] : table) {
|
||||
@@ -354,14 +354,14 @@ AssetsPreloader::Out_applyResourceChange AssetsPreloader::applyResourceChange(co
|
||||
// Связали с хешем
|
||||
HashToId[resource.Hash] = {static_cast<AssetType>(type), pending.Id};
|
||||
// Осведомили о новом/изменённом ресурсе
|
||||
result.NewOrChange[type].push_back({pending.Id, std::move(resource)});
|
||||
result.NewOrChange[type].emplace_back(pending.Id, resource.Hash, std::move(resource.Header));
|
||||
}
|
||||
}
|
||||
|
||||
// Не должно быть ресурсов, которые были помечены как потерянные
|
||||
#ifndef NDEBUG
|
||||
std::unordered_set<uint32_t> changed;
|
||||
for(const auto& [id, _] : result.NewOrChange[type])
|
||||
for(const auto& [id, _, _] : result.NewOrChange[type])
|
||||
changed.insert(id);
|
||||
|
||||
auto& lost = result.Lost[type];
|
||||
@@ -421,4 +421,4 @@ AssetsPreloader::Out_bakeId AssetsPreloader::bakeIdTables() {
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,19 +145,40 @@ public:
|
||||
std::u8string Header;
|
||||
};
|
||||
|
||||
struct BindDomainKeyInfo {
|
||||
std::string Domain;
|
||||
std::string Key;
|
||||
};
|
||||
|
||||
struct BindHashHeaderInfo {
|
||||
ResourceId Id;
|
||||
Hash_t Hash;
|
||||
std::u8string Header;
|
||||
};
|
||||
|
||||
struct Out_reloadResources {
|
||||
std::unordered_map<std::string, std::vector<std::string>> Lost[(int) AssetType::MAX_ENUM];
|
||||
std::unordered_map<std::string, std::vector<PendingResource>> NewOrChange[(int) AssetType::MAX_ENUM];
|
||||
std::unordered_map<std::string, std::vector<std::string>> Lost[(int) AssetType::MAX_ENUM];
|
||||
};
|
||||
|
||||
struct Out_applyResourceChange {
|
||||
std::vector<uint32_t> Lost[(int) AssetType::MAX_ENUM];
|
||||
std::vector<std::pair<uint32_t, MediaResource>> NewOrChange[(int) AssetType::MAX_ENUM];
|
||||
std::array<
|
||||
std::vector<AssetsPreloader::BindHashHeaderInfo>,
|
||||
static_cast<size_t>(AssetType::MAX_ENUM)
|
||||
> NewOrChange;
|
||||
|
||||
std::array<
|
||||
std::vector<ResourceId>,
|
||||
static_cast<size_t>(AssetType::MAX_ENUM)
|
||||
> Lost;
|
||||
};
|
||||
|
||||
struct Out_bakeId {
|
||||
// Новые привязки
|
||||
std::array<std::vector<std::pair<std::string, std::string>>, static_cast<size_t>(AssetType::MAX_ENUM)> IdToDK;
|
||||
std::array<
|
||||
std::vector<BindDomainKeyInfo>,
|
||||
static_cast<size_t>(AssetType::MAX_ENUM)
|
||||
> IdToDK;
|
||||
};
|
||||
|
||||
struct ReloadStatus {
|
||||
@@ -297,7 +318,7 @@ private:
|
||||
Многопоточная таблица обратного резолва.
|
||||
Идентификатор -> домен+ключ
|
||||
*/
|
||||
std::array<std::vector<std::pair<std::string, std::string>>, static_cast<size_t>(AssetType::MAX_ENUM)> IdToDK;
|
||||
std::array<std::vector<BindDomainKeyInfo>, static_cast<size_t>(AssetType::MAX_ENUM)> IdToDK;
|
||||
|
||||
/*
|
||||
Таблица в которой выделяются новые идентификаторы, которых не нашлось в DKToId.
|
||||
@@ -313,7 +334,7 @@ private:
|
||||
Списки в которых пишутся новые привязки. Начала спиской исходят из LastSendId.
|
||||
Id + LastSendId -> домен+ключ
|
||||
*/
|
||||
std::array<TOS::SpinlockObject<std::vector<std::pair<std::string, std::string>>>, static_cast<size_t>(AssetType::MAX_ENUM)> NewIdToDK;
|
||||
std::array<TOS::SpinlockObject<std::vector<BindDomainKeyInfo>>, static_cast<size_t>(AssetType::MAX_ENUM)> NewIdToDK;
|
||||
|
||||
// Загруженные ресурсы
|
||||
std::array<std::unordered_map<ResourceId, MediaResource>, static_cast<size_t>(AssetType::MAX_ENUM)> MediaResources;
|
||||
@@ -370,7 +391,7 @@ inline ResourceId AssetsPreloader::_getIdNew(AssetType type, std::string_view do
|
||||
auto lock2 = NewIdToDK[static_cast<size_t>(type)].lock();
|
||||
lock.unlock();
|
||||
|
||||
lock2->emplace_back(domain, key);
|
||||
lock2->emplace_back((std::string) domain, (std::string) key);
|
||||
|
||||
return id;
|
||||
}
|
||||
@@ -389,17 +410,17 @@ inline std::optional<std::tuple<AssetType, uint32_t, const AssetsPreloader::Medi
|
||||
AssetsPreloader::getResource(const ResourceFile::Hash_t& hash)
|
||||
{
|
||||
auto iter = HashToId.find(hash);
|
||||
if (iter == HashToId.end())
|
||||
if(iter == HashToId.end())
|
||||
return std::nullopt;
|
||||
|
||||
auto [type, id] = iter->second;
|
||||
const MediaResource* res = getResource(type, id);
|
||||
if (!res) {
|
||||
if(!res) {
|
||||
HashToId.erase(iter);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (res->Hash != hash) {
|
||||
if(res->Hash != hash) {
|
||||
HashToId.erase(iter);
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -83,106 +83,26 @@ enum struct L2System : uint8_t {
|
||||
|
||||
}
|
||||
|
||||
namespace ToClient {
|
||||
enum struct ToClient : uint8_t {
|
||||
Init, // Первый пакет от сервера
|
||||
Disconnect, // Отключаем клиента
|
||||
|
||||
/*
|
||||
uint8_t+uint8_t
|
||||
0 - Системное
|
||||
0 - Инициализация WorldId_c+ObjectPos
|
||||
1 - Отключение от сервера String(Причина)
|
||||
2 - Привязка камеры к сущности EntityId_c
|
||||
3 - Отвязка камеры
|
||||
1 - Оповещение о доступном ресурсе
|
||||
0 - Текстура TextureId_c+Hash
|
||||
1 - Освобождение текстуры TextureId_c
|
||||
2 - Звук SoundId_c+Hash
|
||||
3 - Освобождение звука SoundId_c
|
||||
4 - Модель ModelId_c+Hash
|
||||
5 - Освобождение модели ModelId_c
|
||||
253 - Инициирование передачи ресурса StreamId+ResType+ResId+Size+Hash
|
||||
254 - Передача чанка данных StreamId+Size+Data
|
||||
255 - Передача отменена StreamId
|
||||
2 - Новые определения
|
||||
0 - Мир DefWorldId_c+определение
|
||||
1 - Освобождение мира DefWorldId_c
|
||||
2 - Воксель DefVoxelId_c+определение
|
||||
3 - Освобождение вокселя DefVoxelId_c
|
||||
4 - Нода DefNodeId_c+определение
|
||||
5 - Освобождение ноды DefNodeId_c
|
||||
6 - Портал DefPortalId_c+определение
|
||||
7 - Освобождение портала DefPortalId_c
|
||||
8 - Сущность DefEntityId_c+определение
|
||||
9 - Освобождение сущности DefEntityId_c
|
||||
3 - Новый контент
|
||||
0 - Мир, новый/изменён WorldId_c+...
|
||||
1 - Мир/Удалён WorldId_c
|
||||
2 - Портал, новый/изменён PortalId_c+...
|
||||
3 - Портал/Удалён PortalId_c
|
||||
4 - Сущность, новый/изменён EntityId_c+...
|
||||
5 - Сущность/Удалёна EntityId_c
|
||||
6 - Чанк/Воксели WorldId_c+GlobalChunk+...
|
||||
7 - Чанк/Ноды WorldId_c+GlobalChunk+...
|
||||
8 - Чанк/Призмы освещения WorldId_c+GlobalChunk+...
|
||||
9 - Чанк/Удалён WorldId_c+GlobalChunk
|
||||
AssetsBindDK, // Привязка AssetsId к домен+ключ
|
||||
AssetsBindHH, // Привязка AssetsId к hash+header
|
||||
AssetsInitSend, // Начало отправки запрошенного клиентом ресурса
|
||||
AssetsNextSend, // Продолжение отправки ресурса
|
||||
|
||||
DefinitionsUpdate, // Обновление и потеря профилей контента (воксели, ноды, сущности, миры, ...)
|
||||
|
||||
ChunkVoxels, // Обновление вокселей чанка
|
||||
ChunkNodes, // Обновление нод чанка
|
||||
ChunkLightPrism, //
|
||||
RemoveRegion, // Удаление региона из зоны видимости
|
||||
|
||||
*/
|
||||
Tick, // Новые или потерянные игровые объекты (миры, сущности), динамичные данные такта (положение сущностей)
|
||||
|
||||
// Первый уровень
|
||||
enum struct L1 : uint8_t {
|
||||
System,
|
||||
Resource,
|
||||
Definition,
|
||||
Content
|
||||
};
|
||||
|
||||
// Второй уровень
|
||||
enum struct L2System : uint8_t {
|
||||
Init,
|
||||
Disconnect,
|
||||
LinkCameraToEntity,
|
||||
UnlinkCamera,
|
||||
SyncTick
|
||||
};
|
||||
|
||||
enum struct L2Resource : uint8_t {
|
||||
Bind, // Привязка идентификаторов ресурсов к хешам
|
||||
Lost,
|
||||
InitResSend = 253,
|
||||
ChunkSend
|
||||
};
|
||||
|
||||
enum struct L2Definition : uint8_t {
|
||||
World,
|
||||
FreeWorld,
|
||||
Voxel,
|
||||
FreeVoxel,
|
||||
Node,
|
||||
FreeNode,
|
||||
Portal,
|
||||
FreePortal,
|
||||
Entity,
|
||||
FreeEntity,
|
||||
FuncEntity,
|
||||
FreeFuncEntity,
|
||||
Item,
|
||||
FreeItem
|
||||
};
|
||||
|
||||
enum struct L2Content : uint8_t {
|
||||
World,
|
||||
RemoveWorld,
|
||||
Portal,
|
||||
RemovePortal,
|
||||
Entity,
|
||||
RemoveEntity,
|
||||
ChunkVoxels,
|
||||
ChunkNodes,
|
||||
ChunkLightPrism,
|
||||
RemoveRegion
|
||||
TestLinkCameraToEntity, // Привязываем камеру к сущности
|
||||
TestUnlinkCamera, // Отвязываем от сущности
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user