codex-5.2: Обработчик ресурсов на стороне клиента

This commit is contained in:
2026-01-04 20:11:14 +06:00
parent 7c54f429ba
commit 51cc68e1b2
11 changed files with 3614 additions and 2221 deletions

View File

@@ -364,7 +364,7 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
for(AssetEntry& entry : assets) {
entry.Hash = entry.Res.hash();
if(const AssetsManager::BindInfo* bind = AM->getBind(entry.Type, entry.Id))
entry.Dependencies = AM->rebindHeader(bind->Header);
entry.Dependencies = AM->rebindHeader(entry.Type, bind->Header);
else
entry.Dependencies.clear();
@@ -451,7 +451,7 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
std::vector<uint8_t> deps;
if(const AssetsManager::BindInfo* bind = AM->getBind(key.Type, key.Id))
deps = AM->rebindHeader(bind->Header);
deps = AM->rebindHeader(key.Type, bind->Header);
AssetEntry entry {
.Type = key.Type,
@@ -575,7 +575,13 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
// Под рукой нет ресурса, отправим на проверку в AssetsManager
if(needQuery) {
AsyncContext.ResourceWait[(int) bind.Type][bind.Domain].emplace_back(bind.Key, bind.Hash);
needToLoad.emplace_back(bind.Hash, bind.Type, bind.Domain, bind.Key, bind.Id);
needToLoad.push_back(AssetsManager::ResourceKey{
.Hash = bind.Hash,
.Type = bind.Type,
.Domain = bind.Domain,
.Key = bind.Key,
.Id = bind.Id
});
}
}
@@ -978,7 +984,7 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
for(AssetBindEntry& entry : abc.Binds) {
std::vector<uint8_t> deps;
if(!entry.Header.empty())
deps = AM->rebindHeader(entry.Header);
deps = AM->rebindHeader(entry.Type, entry.Header);
MyAssets.ExistBinds[(int) entry.Type].insert(entry.Id);
result.Assets_ChangeOrAdd[entry.Type].push_back(entry.Id);
@@ -1270,179 +1276,142 @@ void ServerSession::protocolError() {
coro<> ServerSession::readPacket(Net::AsyncSocket &sock) {
uint8_t first = co_await sock.read<uint8_t>();
switch((ToClient::L1) first) {
case ToClient::L1::System: co_await rP_System(sock); co_return;
case ToClient::L1::Resource: co_await rP_Resource(sock); co_return;
case ToClient::L1::Definition: co_await rP_Definition(sock); co_return;
case ToClient::L1::Content: co_await rP_Content(sock); co_return;
default:
protocolError();
}
}
coro<> ServerSession::rP_System(Net::AsyncSocket &sock) {
uint8_t second = co_await sock.read<uint8_t>();
switch((ToClient::L2System) second) {
case ToClient::L2System::Init:
switch((ToClient) first) {
case ToClient::Init:
co_return;
case ToClient::L2System::Disconnect:
{
EnumDisconnect type = (EnumDisconnect) co_await sock.read<uint8_t>();
std::string reason = co_await sock.read<std::string>();
if(type == EnumDisconnect::ByInterface)
reason = "по запросу интерфейса " + reason;
else if(type == EnumDisconnect::CriticalError)
reason = "на сервере произошла критическая ошибка " + reason;
else if(type == EnumDisconnect::ProtocolError)
reason = "ошибка протокола (сервер) " + reason;
LOG.info() << "Отключение от сервера: " << reason;
case ToClient::Disconnect:
co_await rP_Disconnect(sock);
co_return;
}
case ToClient::L2System::LinkCameraToEntity:
case ToClient::AssetsBindDK:
co_await rP_AssetsBindDK(sock);
co_return;
case ToClient::L2System::UnlinkCamera:
case ToClient::AssetsBindHH:
co_await rP_AssetsBindHH(sock);
co_return;
case ToClient::L2System::SyncTick:
AsyncContext.TickSequence.lock()->push_back(std::move(AsyncContext.ThisTickEntry));
case ToClient::AssetsInitSend:
co_await rP_AssetsInitSend(sock);
co_return;
case ToClient::AssetsNextSend:
co_await rP_AssetsNextSend(sock);
co_return;
case ToClient::DefinitionsUpdate:
co_await rP_DefinitionsUpdate(sock);
co_return;
case ToClient::ChunkVoxels:
co_await rP_ChunkVoxels(sock);
co_return;
case ToClient::ChunkNodes:
co_await rP_ChunkNodes(sock);
co_return;
case ToClient::ChunkLightPrism:
co_await rP_ChunkLightPrism(sock);
co_return;
case ToClient::RemoveRegion:
co_await rP_RemoveRegion(sock);
co_return;
case ToClient::Tick:
co_await rP_Tick(sock);
co_return;
case ToClient::TestLinkCameraToEntity:
co_await rP_TestLinkCameraToEntity(sock);
co_return;
case ToClient::TestUnlinkCamera:
co_await rP_TestUnlinkCamera(sock);
co_return;
default:
protocolError();
}
}
coro<> ServerSession::rP_Resource(Net::AsyncSocket &sock) {
static std::atomic<uint32_t> debugResourceLogCount = 0;
uint8_t second = co_await sock.read<uint8_t>();
coro<> ServerSession::rP_Disconnect(Net::AsyncSocket &sock) {
EnumDisconnect type = (EnumDisconnect) co_await sock.read<uint8_t>();
std::string reason = co_await sock.read<std::string>();
switch((ToClient::L2Resource) second) {
case ToClient::L2Resource::Bind:
{
uint32_t count = co_await sock.read<uint32_t>();
std::vector<AssetBindEntry> binds;
binds.reserve(count);
if(type == EnumDisconnect::ByInterface)
reason = "по запросу интерфейса " + reason;
else if(type == EnumDisconnect::CriticalError)
reason = "на сервере произошла критическая ошибка " + reason;
else if(type == EnumDisconnect::ProtocolError)
reason = "ошибка протокола (сервер) " + reason;
for(size_t iter = 0; iter < count; iter++) {
uint8_t type = co_await sock.read<uint8_t>();
LOG.info() << "Отключение от сервера: " << reason;
co_return;
}
if(type >= (int) EnumAssets::MAX_ENUM)
protocolError();
coro<> ServerSession::rP_AssetsBindDK(Net::AsyncSocket &sock) {
std::string compressed = co_await sock.read<std::string>();
std::u8string in((const char8_t*) compressed.data(), compressed.size());
std::u8string data = unCompressLinear(in);
Net::LinearReader lr(data);
uint32_t id = co_await sock.read<uint32_t>();
std::string domain, key;
domain = co_await sock.read<std::string>();
key = co_await sock.read<std::string>();
Hash_t hash;
co_await sock.read((std::byte*) hash.data(), hash.size());
uint32_t headerSize = co_await sock.read<uint32_t>();
std::vector<uint8_t> header;
if(headerSize > 0) {
header.resize(headerSize);
co_await sock.read((std::byte*) header.data(), header.size());
}
uint16_t domainsCount = lr.read<uint16_t>();
std::vector<std::string> domains;
domains.reserve(domainsCount);
for(uint16_t i = 0; i < domainsCount; ++i)
domains.push_back(lr.read<std::string>());
AssetsManager::BindResult bindResult = AM->bindServerResource(
(EnumAssets) type, (ResourceId) id, domain, key, hash, header);
if(!bindResult.Changed)
for(size_t type = 0; type < static_cast<size_t>(EnumAssets::MAX_ENUM); ++type) {
uint32_t count = lr.read<uint32_t>();
for(uint32_t i = 0; i < count; ++i) {
uint16_t domainId = lr.read<uint16_t>();
std::string key = lr.read<std::string>();
if(domainId >= domains.size())
continue;
binds.emplace_back(AssetBindEntry{
.Type = (EnumAssets) type,
.Id = bindResult.LocalId,
.Domain = std::move(domain),
.Key = std::move(key),
.Hash = hash,
.Header = std::move(header)
});
if(binds.back().Domain == "test"
&& (binds.back().Type == EnumAssets::Nodestate
|| binds.back().Type == EnumAssets::Model
|| binds.back().Type == EnumAssets::Texture))
{
uint32_t idx = debugResourceLogCount.fetch_add(1);
if(idx < 128) {
LOG.debug() << "Bind asset type=" << assetTypeName(binds.back().Type)
<< " id=" << binds.back().Id
<< " key=" << binds.back().Domain << ':' << binds.back().Key
<< " hash=" << int(binds.back().Hash[0]) << '.'
<< int(binds.back().Hash[1]) << '.'
<< int(binds.back().Hash[2]) << '.'
<< int(binds.back().Hash[3]);
}
}
}
AsyncContext.AssetsBinds.lock()->push_back(AssetsBindsChange(binds, {}));
co_return;
}
case ToClient::L2Resource::BindDK:
{
uint32_t count = co_await sock.read<uint32_t>();
for(size_t iter = 0; iter < count; iter++) {
uint8_t type = co_await sock.read<uint8_t>();
if(type >= (int) EnumAssets::MAX_ENUM)
protocolError();
std::string domain = co_await sock.read<std::string>();
std::string key = co_await sock.read<std::string>();
ResourceId serverId = NextServerId[type]++;
auto& table = ServerIdToDK[type];
if(table.size() <= serverId)
table.resize(serverId+1);
table[serverId] = {std::move(domain), std::move(key)};
table.resize(serverId + 1);
table[serverId] = {domains[domainId], std::move(key)};
}
co_return;
}
case ToClient::L2Resource::BindHash:
{
co_return;
}
coro<> ServerSession::rP_AssetsBindHH(Net::AsyncSocket &sock) {
static std::atomic<uint32_t> debugResourceLogCount = 0;
AssetsBindsChange abc;
for(size_t typeIndex = 0; typeIndex < static_cast<size_t>(EnumAssets::MAX_ENUM); ++typeIndex) {
uint32_t count = co_await sock.read<uint32_t>();
if(count == 0)
continue;
std::vector<AssetBindEntry> binds;
binds.reserve(count);
for(size_t iter = 0; iter < count; iter++) {
uint8_t type = co_await sock.read<uint8_t>();
if(type >= (int) EnumAssets::MAX_ENUM)
protocolError();
for(size_t iter = 0; iter < count; ++iter) {
uint32_t id = co_await sock.read<uint32_t>();
Hash_t hash;
co_await sock.read((std::byte*) hash.data(), hash.size());
uint32_t headerSize = co_await sock.read<uint32_t>();
std::vector<uint8_t> header;
if(headerSize > 0) {
header.resize(headerSize);
co_await sock.read((std::byte*) header.data(), header.size());
}
std::string headerStr = co_await sock.read<std::string>();
std::vector<uint8_t> header(headerStr.begin(), headerStr.end());
auto& table = ServerIdToDK[type];
auto& table = ServerIdToDK[typeIndex];
if(id >= table.size()) {
LOG.warn() << "BindHash without domain/key for id=" << id;
LOG.warn() << "AssetsBindHH without domain/key for id=" << id;
continue;
}
const auto& [domain, key] = table[id];
if(domain.empty() && key.empty()) {
LOG.warn() << "BindHash missing domain/key for id=" << id;
LOG.warn() << "AssetsBindHH missing domain/key for id=" << id;
continue;
}
EnumAssets type = static_cast<EnumAssets>(typeIndex);
AssetsManager::BindResult bindResult = AM->bindServerResource(
(EnumAssets) type, (ResourceId) id, domain, key, hash, header);
type, (ResourceId) id, domain, key, hash, header);
if(!bindResult.Changed)
if(bindResult.ReboundFrom)
abc.Lost[typeIndex].push_back(*bindResult.ReboundFrom);
if(!bindResult.Changed && !bindResult.ReboundFrom)
continue;
binds.emplace_back(AssetBindEntry{
.Type = (EnumAssets) type,
.Type = type,
.Id = bindResult.LocalId,
.Domain = domain,
.Key = key,
@@ -1468,307 +1437,264 @@ coro<> ServerSession::rP_Resource(Net::AsyncSocket &sock) {
}
}
if(!binds.empty())
AsyncContext.AssetsBinds.lock()->push_back(AssetsBindsChange(binds, {}));
if(!binds.empty()) {
abc.Binds.append_range(binds);
binds.clear();
}
}
bool hasLost = false;
for(const auto& list : abc.Lost) {
if(!list.empty()) {
hasLost = true;
break;
}
}
if(!abc.Binds.empty() || hasLost)
AsyncContext.AssetsBinds.lock()->push_back(std::move(abc));
else
co_return;
co_return;
}
coro<> ServerSession::rP_AssetsInitSend(Net::AsyncSocket &sock) {
static std::atomic<uint32_t> debugResourceLogCount = 0;
uint32_t size = co_await sock.read<uint32_t>();
Hash_t hash;
co_await sock.read((std::byte*) hash.data(), hash.size());
bool found = false;
EnumAssets type = EnumAssets::Texture;
std::string domain;
std::string key;
for(int typeIndex = 0; typeIndex < (int) EnumAssets::MAX_ENUM && !found; ++typeIndex) {
auto& waitingByDomain = AsyncContext.ResourceWait[typeIndex];
for(auto iterDomain = waitingByDomain.begin(); iterDomain != waitingByDomain.end() && !found; ) {
auto& entries = iterDomain->second;
for(size_t i = 0; i < entries.size(); ++i) {
if(entries[i].second == hash) {
type = static_cast<EnumAssets>(typeIndex);
domain = iterDomain->first;
key = entries[i].first;
entries.erase(entries.begin() + i);
if(entries.empty())
iterDomain = waitingByDomain.erase(iterDomain);
else
++iterDomain;
found = true;
break;
}
}
if(!found)
++iterDomain;
}
}
if(!found) {
LOG.warn() << "AssetsInitSend for unknown hash " << int(hash[0]) << '.'
<< int(hash[1]) << '.' << int(hash[2]) << '.' << int(hash[3]);
AsyncContext.AssetsLoading[hash] = AssetLoading{
EnumAssets::Texture, 0, {}, {},
std::u8string(size, '\0'), 0
};
co_return;
}
case ToClient::L2Resource::Lost:
ResourceId localId = AM->getOrCreateLocalId(type, domain, key);
if(domain == "test"
&& (type == EnumAssets::Nodestate
|| type == EnumAssets::Model
|| type == EnumAssets::Texture))
{
uint32_t count = co_await sock.read<uint32_t>();
AssetsBindsChange abc;
for(size_t iter = 0; iter < count; iter++) {
uint8_t type = co_await sock.read<uint8_t>();
uint32_t id = co_await sock.read<uint32_t>();
if(type >= (int) EnumAssets::MAX_ENUM)
protocolError();
auto localId = AM->unbindServerResource((EnumAssets) type, id);
if(!localId)
continue;
abc.Lost[(int) type].push_back(*localId);
uint32_t idx = debugResourceLogCount.fetch_add(1);
if(idx < 128) {
LOG.debug() << "AssetsInitSend type=" << assetTypeName(type)
<< " id=" << localId
<< " key=" << domain << ':' << key
<< " size=" << size;
}
}
AsyncContext.AssetsBinds.lock()->emplace_back(std::move(abc));
AsyncContext.AssetsLoading[hash] = AssetLoading{
type, localId, std::move(domain), std::move(key),
std::u8string(size, '\0'), 0
};
co_return;
}
coro<> ServerSession::rP_AssetsNextSend(Net::AsyncSocket &sock) {
static std::atomic<uint32_t> debugResourceLogCount = 0;
Hash_t hash;
co_await sock.read((std::byte*) hash.data(), hash.size());
uint32_t size = co_await sock.read<uint32_t>();
if(!AsyncContext.AssetsLoading.contains(hash)) {
std::vector<std::byte> discard(size);
co_await sock.read(discard.data(), size);
co_return;
}
case ToClient::L2Resource::InitResSend:
{
uint32_t size = co_await sock.read<uint32_t>();
Hash_t hash;
co_await sock.read((std::byte*) hash.data(), hash.size());
ResourceId id = co_await sock.read<uint32_t>();
EnumAssets type = (EnumAssets) co_await sock.read<uint8_t>();
if(type >= EnumAssets::MAX_ENUM)
protocolError();
AssetLoading& al = AsyncContext.AssetsLoading.at(hash);
if(al.Data.size() - al.Offset < size)
MAKE_ERROR("Несоответствие ожидаемого размера ресурса");
std::string domain = co_await sock.read<std::string>();
std::string key = co_await sock.read<std::string>();
ResourceId localId = 0;
if(auto mapped = AM->getLocalIdFromServer(type, id)) {
localId = *mapped;
} else {
localId = AM->getId(type, domain, key);
AM->bindServerResource(type, id, domain, key, hash, {});
}
co_await sock.read((std::byte*) al.Data.data() + al.Offset, size);
al.Offset += size;
if(domain == "test"
&& (type == EnumAssets::Nodestate
|| type == EnumAssets::Model
|| type == EnumAssets::Texture))
if(al.Offset != al.Data.size())
co_return;
if(!al.Domain.empty() || !al.Key.empty()) {
if(al.Domain == "test"
&& (al.Type == EnumAssets::Nodestate
|| al.Type == EnumAssets::Model
|| al.Type == EnumAssets::Texture))
{
uint32_t idx = debugResourceLogCount.fetch_add(1);
if(idx < 128) {
LOG.debug() << "InitResSend type=" << assetTypeName(type)
<< " id=" << localId
<< " key=" << domain << ':' << key
<< " size=" << size;
LOG.debug() << "Resource loaded type=" << assetTypeName(al.Type)
<< " id=" << al.Id
<< " key=" << al.Domain << ':' << al.Key
<< " size=" << al.Data.size();
}
}
AsyncContext.AssetsLoading[hash] = AssetLoading{
type, localId, std::move(domain), std::move(key),
std::u8string(size, '\0'), 0
};
co_return;
AsyncContext.LoadedAssets.lock()->emplace_back(AssetEntry{
.Type = al.Type,
.Id = al.Id,
.Domain = std::move(al.Domain),
.Key = std::move(al.Key),
.Res = std::move(al.Data),
.Hash = hash
});
}
case ToClient::L2Resource::ChunkSend:
{
Hash_t hash;
co_await sock.read((std::byte*) hash.data(), hash.size());
try {
uint32_t size = co_await sock.read<uint32_t>();
assert(AsyncContext.AssetsLoading.contains(hash));
AssetLoading& al = AsyncContext.AssetsLoading.at(hash);
if(al.Data.size()-al.Offset < size)
MAKE_ERROR("Несоответствие ожидаемого размера ресурса");
co_await sock.read((std::byte*) al.Data.data() + al.Offset, size);
al.Offset += size;
AsyncContext.AssetsLoading.erase(AsyncContext.AssetsLoading.find(hash));
if(al.Offset == al.Data.size()) {
// Ресурс полностью загружен
if(al.Domain == "test"
&& (al.Type == EnumAssets::Nodestate
|| al.Type == EnumAssets::Model
|| al.Type == EnumAssets::Texture))
{
uint32_t idx = debugResourceLogCount.fetch_add(1);
if(idx < 128) {
LOG.debug() << "Resource loaded type=" << assetTypeName(al.Type)
<< " id=" << al.Id
<< " key=" << al.Domain << ':' << al.Key
<< " size=" << al.Data.size();
auto iter = std::lower_bound(AsyncContext.AlreadyLoading.begin(), AsyncContext.AlreadyLoading.end(), hash);
if(iter != AsyncContext.AlreadyLoading.end() && *iter == hash)
AsyncContext.AlreadyLoading.erase(iter);
co_return;
}
coro<> ServerSession::rP_DefinitionsUpdate(Net::AsyncSocket &sock) {
static std::atomic<uint32_t> debugDefLogCount = 0;
uint32_t typeCount = co_await sock.read<uint32_t>();
typeCount = std::min<uint32_t>(typeCount, static_cast<uint32_t>(EnumDefContent::MAX_ENUM));
for(uint32_t type = 0; type < typeCount; ++type) {
uint32_t count = co_await sock.read<uint32_t>();
for(uint32_t i = 0; i < count; ++i) {
ResourceId id = co_await sock.read<ResourceId>();
std::string dataStr = co_await sock.read<std::string>();
(void)dataStr;
if(type == static_cast<uint32_t>(EnumDefContent::Node)) {
DefNode_t def;
def.NodestateId = 0;
def.TexId = id;
AsyncContext.ThisTickEntry.Profile_Node_AddOrChange.emplace_back(id, def);
if(id < 32) {
uint32_t idx = debugDefLogCount.fetch_add(1);
if(idx < 64) {
LOG.debug() << "DefNode id=" << id
<< " nodestate=" << def.NodestateId
<< " tex=" << def.TexId;
}
}
AsyncContext.LoadedAssets.lock()->emplace_back(AssetEntry{
.Type = al.Type,
.Id = al.Id,
.Domain = std::move(al.Domain),
.Key = std::move(al.Key),
.Res = std::move(al.Data),
.Hash = hash
});
AsyncContext.AssetsLoading.erase(AsyncContext.AssetsLoading.find(hash));
auto iter = std::lower_bound(AsyncContext.AlreadyLoading.begin(), AsyncContext.AlreadyLoading.end(), hash);
if(iter != AsyncContext.AlreadyLoading.end() && *iter == hash)
AsyncContext.AlreadyLoading.erase(iter);
}
} catch(const std::exception& exc) {
std::string err = exc.what();
int g = 0;
}
co_return;
}
default:
protocolError();
}
}
coro<> ServerSession::rP_Definition(Net::AsyncSocket &sock) {
static std::atomic<uint32_t> debugDefLogCount = 0;
uint8_t second = co_await sock.read<uint8_t>();
switch((ToClient::L2Definition) second) {
case ToClient::L2Definition::World: {
DefWorldId cdId = co_await sock.read<DefWorldId>();
co_return;
}
case ToClient::L2Definition::FreeWorld: {
DefWorldId cdId = co_await sock.read<DefWorldId>();
co_return;
}
case ToClient::L2Definition::Voxel: {
DefVoxelId cdId = co_await sock.read<DefVoxelId>();
co_return;
}
case ToClient::L2Definition::FreeVoxel: {
DefVoxelId cdId = co_await sock.read<DefVoxelId>();
co_return;
}
case ToClient::L2Definition::Node:
{
DefNode_t def;
DefNodeId id = co_await sock.read<DefNodeId>();
ResourceId serverNodestate = co_await sock.read<uint32_t>();
if(auto localId = AM->getLocalIdFromServer(EnumAssets::Nodestate, serverNodestate))
def.NodestateId = *localId;
else
def.NodestateId = 0;
def.TexId = id;
if(id < 32) {
uint32_t idx = debugDefLogCount.fetch_add(1);
if(idx < 64) {
LOG.debug() << "DefNode id=" << id
<< " nodestate=" << def.NodestateId
<< " tex=" << def.TexId;
}
}
}
AsyncContext.ThisTickEntry.Profile_Node_AddOrChange.emplace_back(id, def);
uint32_t lostCount = co_await sock.read<uint32_t>();
lostCount = std::min<uint32_t>(lostCount, static_cast<uint32_t>(EnumDefContent::MAX_ENUM));
for(uint32_t type = 0; type < lostCount; ++type) {
uint32_t count = co_await sock.read<uint32_t>();
for(uint32_t i = 0; i < count; ++i) {
ResourceId id = co_await sock.read<ResourceId>();
if(type == static_cast<uint32_t>(EnumDefContent::Node))
AsyncContext.ThisTickEntry.Profile_Node_Lost.push_back(id);
}
}
co_return;
uint32_t dkCount = co_await sock.read<uint32_t>();
dkCount = std::min<uint32_t>(dkCount, static_cast<uint32_t>(EnumDefContent::MAX_ENUM));
for(uint32_t type = 0; type < dkCount; ++type) {
uint32_t count = co_await sock.read<uint32_t>();
for(uint32_t i = 0; i < count; ++i) {
std::string key = co_await sock.read<std::string>();
std::string domain = co_await sock.read<std::string>();
(void)key;
(void)domain;
}
}
case ToClient::L2Definition::FreeNode:
{
DefNodeId id = co_await sock.read<DefNodeId>();
AsyncContext.ThisTickEntry.Profile_Node_Lost.push_back(id);
co_return;
}
case ToClient::L2Definition::Portal:
co_return;
case ToClient::L2Definition::FreePortal:
co_return;
case ToClient::L2Definition::Entity:
{
DefEntityId id = co_await sock.read<DefEntityId>();
DefEntityInfo def;
AsyncContext.ThisTickEntry.Profile_Entity_AddOrChange.emplace_back(id, def);
co_return;
}
case ToClient::L2Definition::FreeEntity:
{
DefEntityId id = co_await sock.read<DefEntityId>();
AsyncContext.ThisTickEntry.Profile_Entity_Lost.push_back(id);
co_return;
}
default:
protocolError();
}
co_return;
}
coro<> ServerSession::rP_Content(Net::AsyncSocket &sock) {
uint8_t second = co_await sock.read<uint8_t>();
coro<> ServerSession::rP_ChunkVoxels(Net::AsyncSocket &sock) {
WorldId_t wcId = co_await sock.read<WorldId_t>();
Pos::GlobalChunk pos;
pos.unpack(co_await sock.read<Pos::GlobalChunk::Pack>());
switch((ToClient::L2Content) second) {
case ToClient::L2Content::World: {
WorldId_t wId = co_await sock.read<uint32_t>();
AsyncContext.ThisTickEntry.Worlds_AddOrChange.emplace_back(wId, nullptr);
co_return;
}
case ToClient::L2Content::RemoveWorld: {
WorldId_t wId = co_await sock.read<uint32_t>();
AsyncContext.ThisTickEntry.Worlds_Lost.push_back(wId);
co_return;
}
case ToClient::L2Content::Portal:
uint32_t compressedSize = co_await sock.read<uint32_t>();
assert(compressedSize <= std::pow(2, 24));
std::u8string compressed(compressedSize, '\0');
co_await sock.read((std::byte*) compressed.data(), compressedSize);
co_return;
case ToClient::L2Content::RemovePortal:
co_return;
case ToClient::L2Content::Entity:
{
EntityId_t id = co_await sock.read<EntityId_t>();
DefEntityId defId = co_await sock.read<DefEntityId>();
WorldId_t worldId = co_await sock.read<WorldId_t>();
AsyncContext.ThisTickEntry.Chunks_AddOrChange_Voxel[wcId].insert({pos, std::move(compressed)});
co_return;
}
Pos::Object pos;
pos.x = co_await sock.read<decltype(pos.x)>();
pos.y = co_await sock.read<decltype(pos.y)>();
pos.z = co_await sock.read<decltype(pos.z)>();
coro<> ServerSession::rP_ChunkNodes(Net::AsyncSocket &sock) {
WorldId_t wcId = co_await sock.read<WorldId_t>();
Pos::GlobalChunk pos;
pos.unpack(co_await sock.read<Pos::GlobalChunk::Pack>());
ToServer::PacketQuat q;
for(int iter = 0; iter < 5; iter++)
q.Data[iter] = co_await sock.read<uint8_t>();
uint32_t compressedSize = co_await sock.read<uint32_t>();
assert(compressedSize <= std::pow(2, 24));
std::u8string compressed(compressedSize, '\0');
co_await sock.read((std::byte*) compressed.data(), compressedSize);
EntityInfo info;
info.DefId = defId;
info.WorldId = worldId;
info.Pos = pos;
info.Quat = q.toQuat();
AsyncContext.ThisTickEntry.Chunks_AddOrChange_Node[wcId].insert({pos, std::move(compressed)});
co_return;
}
AsyncContext.ThisTickEntry.Entity_AddOrChange.emplace_back(id, info);
co_return;
}
case ToClient::L2Content::RemoveEntity:
{
EntityId_t id = co_await sock.read<EntityId_t>();
AsyncContext.ThisTickEntry.Entity_Lost.push_back(id);
co_return;
}
case ToClient::L2Content::ChunkVoxels:
{
WorldId_t wcId = co_await sock.read<WorldId_t>();
Pos::GlobalChunk pos;
pos.unpack(co_await sock.read<Pos::GlobalChunk::Pack>());
coro<> ServerSession::rP_ChunkLightPrism(Net::AsyncSocket &sock) {
(void)sock;
co_return;
}
uint32_t compressedSize = co_await sock.read<uint32_t>();
assert(compressedSize <= std::pow(2, 24));
std::u8string compressed(compressedSize, '\0');
co_await sock.read((std::byte*) compressed.data(), compressedSize);
coro<> ServerSession::rP_RemoveRegion(Net::AsyncSocket &sock) {
WorldId_t wcId = co_await sock.read<WorldId_t>();
Pos::GlobalRegion pos;
pos.unpack(co_await sock.read<Pos::GlobalRegion::Pack>());
AsyncContext.ThisTickEntry.Chunks_AddOrChange_Node[wcId].insert({pos, std::move(compressed)});
AsyncContext.ThisTickEntry.Regions_Lost[wcId].push_back(pos);
co_return;
}
co_return;
}
coro<> ServerSession::rP_Tick(Net::AsyncSocket &sock) {
(void)sock;
AsyncContext.TickSequence.lock()->push_back(std::move(AsyncContext.ThisTickEntry));
AsyncContext.ThisTickEntry = {};
co_return;
}
case ToClient::L2Content::ChunkNodes:
{
WorldId_t wcId = co_await sock.read<WorldId_t>();
Pos::GlobalChunk pos;
pos.unpack(co_await sock.read<Pos::GlobalChunk::Pack>());
coro<> ServerSession::rP_TestLinkCameraToEntity(Net::AsyncSocket &sock) {
(void) sock;
co_return;
}
uint32_t compressedSize = co_await sock.read<uint32_t>();
assert(compressedSize <= std::pow(2, 24));
std::u8string compressed(compressedSize, '\0');
co_await sock.read((std::byte*) compressed.data(), compressedSize);
AsyncContext.ThisTickEntry.Chunks_AddOrChange_Node[wcId].insert({pos, std::move(compressed)});
co_return;
}
case ToClient::L2Content::ChunkLightPrism:
co_return;
case ToClient::L2Content::RemoveRegion: {
WorldId_t wcId = co_await sock.read<WorldId_t>();
Pos::GlobalRegion pos;
pos.unpack(co_await sock.read<Pos::GlobalRegion::Pack>());
AsyncContext.ThisTickEntry.Regions_Lost[wcId].push_back(pos);
co_return;
}
default:
protocolError();
}
coro<> ServerSession::rP_TestUnlinkCamera(Net::AsyncSocket &sock) {
(void) sock;
co_return;
}
}