Отправка идентификаторов при подключении клиентов

This commit is contained in:
2026-01-04 20:47:48 +06:00
parent 01ea7eee74
commit 6dd1f93221
4 changed files with 65 additions and 67 deletions

View File

@@ -38,69 +38,6 @@ const char* assetTypeName(EnumAssets type) {
} }
} }
std::optional<DefNodeId> debugExpectedGeneratedNodeId(int rx, int ry, int rz) {
if(ry == 1 && rz == 0)
return DefNodeId(0);
if(rx == 0 && ry == 1)
return DefNodeId(0);
if(rx == 0 && rz == 0)
return DefNodeId(1);
if(ry == 0 && rz == 0)
return DefNodeId(2);
if(rx == 0 && ry == 0)
return DefNodeId(3);
return std::nullopt;
}
void debugCheckGeneratedChunkNodes(WorldId_t worldId,
Pos::GlobalChunk chunkPos,
const std::array<Node, 16 * 16 * 16>& chunk)
{
if(chunkPos[0] != 0 && chunkPos[1] != 0 && chunkPos[2] != 0)
return;
static std::atomic<uint32_t> warnCount = 0;
if(warnCount.load() >= 16)
return;
Pos::bvec4u localChunk = chunkPos & 0x3;
const int baseX = int(localChunk[0]) * 16;
const int baseY = int(localChunk[1]) * 16;
const int baseZ = int(localChunk[2]) * 16;
const int globalBaseX = int(chunkPos[0]) * 16;
const int globalBaseY = int(chunkPos[1]) * 16;
const int globalBaseZ = int(chunkPos[2]) * 16;
for(int z = 0; z < 16; z++)
for(int y = 0; y < 16; y++)
for(int x = 0; x < 16; x++) {
int rx = baseX + x;
int ry = baseY + y;
int rz = baseZ + z;
int gx = globalBaseX + x;
int gy = globalBaseY + y;
int gz = globalBaseZ + z;
std::optional<DefNodeId> expected = debugExpectedGeneratedNodeId(rx, ry, rz);
if(!expected)
continue;
const Node& node = chunk[x + y * 16 + z * 16 * 16];
if(node.NodeId != *expected) {
uint32_t index = warnCount.fetch_add(1);
if(index < 16) {
TOS::Logger("Client>WorldDebug").warn()
<< "Generated node mismatch world " << worldId
<< " chunk " << int(chunkPos[0]) << ',' << int(chunkPos[1]) << ',' << int(chunkPos[2])
<< " at local " << rx << ',' << ry << ',' << rz
<< " global " << gx << ',' << gy << ',' << gz
<< " expected " << *expected
<< " got " << node.NodeId;
}
return;
}
}
}
} }
ServerSession::ServerSession(asio::io_context &ioc, std::unique_ptr<Net::AsyncSocket>&& socket) ServerSession::ServerSession(asio::io_context &ioc, std::unique_ptr<Net::AsyncSocket>&& socket)
@@ -919,7 +856,6 @@ void ServerSession::update(GlobalTime gTime, float dTime) {
auto& chunkNodes = caocvr[pos]; auto& chunkNodes = caocvr[pos];
unCompressNodes(val, chunkNodes.data()); unCompressNodes(val, chunkNodes.data());
debugCheckGeneratedChunkNodes(wId, pos, chunkNodes);
c.push_back(pos); c.push_back(pos);
} }
} }

View File

@@ -421,6 +421,31 @@ AssetsPreloader::Out_bakeId AssetsPreloader::bakeIdTables() {
return result; return result;
} }
AssetsPreloader::Out_fullSync AssetsPreloader::collectFullSync() const {
Out_fullSync out;
for(size_t type = 0; type < static_cast<size_t>(AssetType::MAX_ENUM); ++type) {
out.IdToDK[type] = IdToDK[type];
}
for(size_t type = 0; type < static_cast<size_t>(AssetType::MAX_ENUM); ++type) {
for(const auto& [id, resource] : MediaResources[type]) {
out.HashHeaders[type].push_back(BindHashHeaderInfo{
.Id = id,
.Hash = resource.Hash,
.Header = resource.Header
});
out.Resources.emplace_back(
static_cast<AssetType>(type),
id,
&resource
);
}
}
return out;
}
std::tuple<AssetsNodestate, std::vector<AssetsModel>, std::vector<AssetsTexture>> std::tuple<AssetsNodestate, std::vector<AssetsModel>, std::vector<AssetsTexture>>
AssetsPreloader::getNodeDependency(const std::string& domain, const std::string& key) { AssetsPreloader::getNodeDependency(const std::string& domain, const std::string& key) {
(void)domain; (void)domain;

View File

@@ -143,6 +143,20 @@ public:
> IdToDK; > IdToDK;
}; };
struct Out_fullSync {
std::array<
std::vector<BindDomainKeyInfo>,
static_cast<size_t>(AssetType::MAX_ENUM)
> IdToDK;
std::array<
std::vector<BindHashHeaderInfo>,
static_cast<size_t>(AssetType::MAX_ENUM)
> HashHeaders;
std::vector<std::tuple<AssetType, ResourceId, const MediaResource*>> Resources;
};
struct ReloadStatus { struct ReloadStatus {
/// TODO: callback'и для обновления статусов /// TODO: callback'и для обновления статусов
/// TODO: многоуровневый статус std::vector<std::string>. Этапы/Шаги/Объекты /// TODO: многоуровневый статус std::vector<std::string>. Этапы/Шаги/Объекты
@@ -218,6 +232,9 @@ public:
*/ */
Out_bakeId bakeIdTables(); Out_bakeId bakeIdTables();
// Выдаёт полный список привязок и ресурсов для новых клиентов.
Out_fullSync collectFullSync() const;
/* /*
Выдаёт пакет со всеми текущими привязками id -> домен+ключ. Выдаёт пакет со всеми текущими привязками id -> домен+ключ.
Используется при подключении новых клиентов. Используется при подключении новых клиентов.

View File

@@ -1582,6 +1582,7 @@ void GameServer::requestModsReload() {
} }
void GameServer::stepConnections() { void GameServer::stepConnections() {
std::vector<std::shared_ptr<RemoteClient>> newClients;
// Подключить новых игроков // Подключить новых игроков
if(!External.NewConnectedPlayers.no_lock_readable().empty()) { if(!External.NewConnectedPlayers.no_lock_readable().empty()) {
auto lock = External.NewConnectedPlayers.lock_write(); auto lock = External.NewConnectedPlayers.lock_write();
@@ -1589,11 +1590,27 @@ void GameServer::stepConnections() {
for(std::shared_ptr<RemoteClient>& client : *lock) { for(std::shared_ptr<RemoteClient>& client : *lock) {
co_spawn(client->run()); co_spawn(client->run());
Game.RemoteClients.push_back(client); Game.RemoteClients.push_back(client);
newClients.push_back(client);
} }
lock->clear(); lock->clear();
} }
if(!newClients.empty()) {
AssetsPreloader::Out_fullSync fullSync = Content.AM.collectFullSync();
std::array<std::vector<ResourceId>, static_cast<size_t>(EnumAssets::MAX_ENUM)> lost{};
std::vector<Net::Packet> packets = RemoteClient::makePackets_informateAssets_DK(fullSync.IdToDK);
packets.push_back(RemoteClient::makePacket_informateAssets_HH(fullSync.HashHeaders, lost));
for(const std::shared_ptr<RemoteClient>& client : newClients) {
if(!packets.empty()) {
auto copy = packets;
client->pushPackets(&copy);
}
}
}
BackingChunkPressure.endCollectChanges(); BackingChunkPressure.endCollectChanges();
// Отключение игроков // Отключение игроков
@@ -1676,8 +1693,10 @@ void GameServer::reloadMods() {
{ {
AssetsPreloader::Out_bakeId baked = Content.AM.bakeIdTables(); AssetsPreloader::Out_bakeId baked = Content.AM.bakeIdTables();
if(!baked.IdToDK.empty()) if(!baked.IdToDK.empty()) {
packetsToSend.push_back(RemoteClient::makePacket_informateAssets_DK(baked.IdToDK)); std::vector<Net::Packet> dkPackets = RemoteClient::makePackets_informateAssets_DK(baked.IdToDK);
packetsToSend.insert(packetsToSend.end(), dkPackets.begin(), dkPackets.end());
}
} }
} }
@@ -2469,7 +2488,8 @@ void GameServer::stepSyncContent() {
{ {
AssetsPreloader::Out_bakeId baked = Content.AM.bakeIdTables(); AssetsPreloader::Out_bakeId baked = Content.AM.bakeIdTables();
if(!baked.IdToDK.empty()) { if(!baked.IdToDK.empty()) {
packetsToAll.push_back(RemoteClient::makePacket_informateAssets_DK(baked.IdToDK)); std::vector<Net::Packet> dkPackets = RemoteClient::makePackets_informateAssets_DK(baked.IdToDK);
packetsToAll.insert(packetsToAll.end(), dkPackets.begin(), dkPackets.end());
} }
} }