Compare commits
2 Commits
dbebf50552
...
6dd1f93221
| Author | SHA1 | Date | |
|---|---|---|---|
| 6dd1f93221 | |||
| 01ea7eee74 |
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 -> домен+ключ.
|
||||||
Используется при подключении новых клиентов.
|
Используется при подключении новых клиентов.
|
||||||
|
|||||||
@@ -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(©);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -258,6 +258,15 @@ void RemoteClient::shutdown(EnumDisconnect type, const std::string reason) {
|
|||||||
|
|
||||||
void RemoteClient::NetworkAndResource_t::prepareRegionsRemove(WorldId_t worldId, std::vector<Pos::GlobalRegion> regionPoses)
|
void RemoteClient::NetworkAndResource_t::prepareRegionsRemove(WorldId_t worldId, std::vector<Pos::GlobalRegion> regionPoses)
|
||||||
{
|
{
|
||||||
|
auto worldIter = ChunksToSend.find(worldId);
|
||||||
|
if(worldIter != ChunksToSend.end()) {
|
||||||
|
for(const Pos::GlobalRegion ®ionPos : regionPoses)
|
||||||
|
worldIter->second.erase(regionPos);
|
||||||
|
|
||||||
|
if(worldIter->second.empty())
|
||||||
|
ChunksToSend.erase(worldIter);
|
||||||
|
}
|
||||||
|
|
||||||
for(Pos::GlobalRegion regionPos : regionPoses) {
|
for(Pos::GlobalRegion regionPos : regionPoses) {
|
||||||
checkPacketBorder(16);
|
checkPacketBorder(16);
|
||||||
NextPacket << (uint8_t) ToClient::RemoveRegion
|
NextPacket << (uint8_t) ToClient::RemoveRegion
|
||||||
@@ -265,6 +274,60 @@ void RemoteClient::NetworkAndResource_t::prepareRegionsRemove(WorldId_t worldId,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoteClient::NetworkAndResource_t::flushChunksToPackets()
|
||||||
|
{
|
||||||
|
for(auto &worldPair : ChunksToSend) {
|
||||||
|
const WorldId_t worldId = worldPair.first;
|
||||||
|
auto ®ions = worldPair.second;
|
||||||
|
|
||||||
|
for(auto ®ionPair : regions) {
|
||||||
|
const Pos::GlobalRegion regionPos = regionPair.first;
|
||||||
|
auto &voxels = regionPair.second.first;
|
||||||
|
auto &nodes = regionPair.second.second;
|
||||||
|
|
||||||
|
for(auto &chunkPair : voxels) {
|
||||||
|
const Pos::bvec4u chunkPos = chunkPair.first;
|
||||||
|
const std::u8string &compressed = chunkPair.second;
|
||||||
|
|
||||||
|
Pos::GlobalChunk globalPos = (Pos::GlobalChunk) regionPos;
|
||||||
|
globalPos <<= 2;
|
||||||
|
globalPos += (Pos::GlobalChunk) chunkPos;
|
||||||
|
|
||||||
|
const size_t size = 1 + sizeof(WorldId_t)
|
||||||
|
+ sizeof(Pos::GlobalChunk::Pack)
|
||||||
|
+ sizeof(uint32_t)
|
||||||
|
+ compressed.size();
|
||||||
|
checkPacketBorder(static_cast<uint16_t>(std::min<size_t>(size, 64000)));
|
||||||
|
|
||||||
|
NextPacket << (uint8_t) ToClient::ChunkVoxels
|
||||||
|
<< worldId << globalPos.pack() << uint32_t(compressed.size());
|
||||||
|
NextPacket.write((const std::byte*) compressed.data(), compressed.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto &chunkPair : nodes) {
|
||||||
|
const Pos::bvec4u chunkPos = chunkPair.first;
|
||||||
|
const std::u8string &compressed = chunkPair.second;
|
||||||
|
|
||||||
|
Pos::GlobalChunk globalPos = (Pos::GlobalChunk) regionPos;
|
||||||
|
globalPos <<= 2;
|
||||||
|
globalPos += (Pos::GlobalChunk) chunkPos;
|
||||||
|
|
||||||
|
const size_t size = 1 + sizeof(WorldId_t)
|
||||||
|
+ sizeof(Pos::GlobalChunk::Pack)
|
||||||
|
+ sizeof(uint32_t)
|
||||||
|
+ compressed.size();
|
||||||
|
checkPacketBorder(static_cast<uint16_t>(std::min<size_t>(size, 64000)));
|
||||||
|
|
||||||
|
NextPacket << (uint8_t) ToClient::ChunkNodes
|
||||||
|
<< worldId << globalPos.pack() << uint32_t(compressed.size());
|
||||||
|
NextPacket.write((const std::byte*) compressed.data(), compressed.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ChunksToSend.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteClient::NetworkAndResource_t::prepareEntitiesUpdate(const std::vector<std::tuple<ServerEntityId_t, const Entity*>>& entities)
|
void RemoteClient::NetworkAndResource_t::prepareEntitiesUpdate(const std::vector<std::tuple<ServerEntityId_t, const Entity*>>& entities)
|
||||||
{
|
{
|
||||||
// for(auto& [entityId, entity] : entities) {
|
// for(auto& [entityId, entity] : entities) {
|
||||||
@@ -337,6 +400,7 @@ ResourceRequest RemoteClient::pushPreparedPackets() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
auto lock = NetworkAndResource.lock();
|
auto lock = NetworkAndResource.lock();
|
||||||
|
lock->flushChunksToPackets();
|
||||||
|
|
||||||
if(lock->NextPacket.size())
|
if(lock->NextPacket.size())
|
||||||
lock->SimplePackets.push_back(std::move(lock->NextPacket));
|
lock->SimplePackets.push_back(std::move(lock->NextPacket));
|
||||||
|
|||||||
@@ -233,6 +233,8 @@ class RemoteClient {
|
|||||||
ChunksToSend[worldId][regionPos].second[chunkPos] = compressed_nodes;
|
ChunksToSend[worldId][regionPos].second[chunkPos] = compressed_nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void flushChunksToPackets();
|
||||||
|
|
||||||
void prepareEntitiesRemove(const std::vector<ServerEntityId_t>& entityId);
|
void prepareEntitiesRemove(const std::vector<ServerEntityId_t>& entityId);
|
||||||
void prepareRegionsRemove(WorldId_t worldId, std::vector<Pos::GlobalRegion> regionPoses);
|
void prepareRegionsRemove(WorldId_t worldId, std::vector<Pos::GlobalRegion> regionPoses);
|
||||||
void prepareWorldRemove(WorldId_t worldId);
|
void prepareWorldRemove(WorldId_t worldId);
|
||||||
|
|||||||
Reference in New Issue
Block a user