relax sector unload criteria

This commit is contained in:
Kae 2024-07-28 10:53:14 +10:00
parent e1be2ab429
commit 5398190030
3 changed files with 32 additions and 18 deletions

View File

@ -660,10 +660,10 @@ void WorldServer::update(float dt) {
m_fallingBlocksAgent->update(); m_fallingBlocksAgent->update();
if (auto delta = shouldRunThisStep("blockDamageUpdate")) if (auto delta = shouldRunThisStep("blockDamageUpdate"))
updateDamagedBlocks(*delta * GlobalTimestep); updateDamagedBlocks(*delta * dt);
if (auto delta = shouldRunThisStep("worldStorageTick")) if (auto delta = shouldRunThisStep("worldStorageTick"))
m_worldStorage->tick(*delta * GlobalTimestep); m_worldStorage->tick(*delta * GlobalTimestep, &m_worldId);
if (auto delta = shouldRunThisStep("worldStorageGenerate")) { if (auto delta = shouldRunThisStep("worldStorageGenerate")) {
m_worldStorage->generateQueue(m_fidelityConfig.optUInt("worldStorageGenerationLevelLimit"), [this](WorldStorage::Sector a, WorldStorage::Sector b) { m_worldStorage->generateQueue(m_fidelityConfig.optUInt("worldStorageGenerationLevelLimit"), [this](WorldStorage::Sector a, WorldStorage::Sector b) {

View File

@ -273,7 +273,7 @@ void WorldStorage::generateQueue(Maybe<size_t> sectorGenerationLevelLimit, funct
} }
} }
void WorldStorage::tick(float dt) { void WorldStorage::tick(float dt, String const* worldId) {
try { try {
// Tick down generation queue entries, and erase any that are expired. // Tick down generation queue entries, and erase any that are expired.
eraseWhere(m_generationQueue, [dt](auto& p) { eraseWhere(m_generationQueue, [dt](auto& p) {
@ -289,6 +289,7 @@ void WorldStorage::tick(float dt) {
// unloaded, kept alive by a keep-alive entity, or has any entities that need // unloaded, kept alive by a keep-alive entity, or has any entities that need
// to be stored because they moved into an entity-unloaded sector (zombies). // to be stored because they moved into an entity-unloaded sector (zombies).
auto entityFactory = Root::singleton().entityFactory(); auto entityFactory = Root::singleton().entityFactory();
unsigned unloaded = 0, skipped = 0;
for (auto const& p : m_sectorMetadata.pairs()) { for (auto const& p : m_sectorMetadata.pairs()) {
auto const& sector = p.first; auto const& sector = p.first;
auto const& metadata = p.second; auto const& metadata = p.second;
@ -315,7 +316,7 @@ void WorldStorage::tick(float dt) {
if (keepAlive) { if (keepAlive) {
setSectorTimeToLive(sector, randomizedSectorTTL()); setSectorTimeToLive(sector, randomizedSectorTTL());
} else if (needsUnload) { } else if (needsUnload) {
unloadSectorToLevel(sector, SectorLoadLevel::None); (unloadSectorToLevel(sector, SectorLoadLevel::None) ? unloaded : skipped)++;
} else if (!zombieEntities.empty()) { } else if (!zombieEntities.empty()) {
List<EntityPtr> zombiesToStore; List<EntityPtr> zombiesToStore;
List<EntityPtr> zombiesToRemove; List<EntityPtr> zombiesToRemove;
@ -349,6 +350,10 @@ void WorldStorage::tick(float dt) {
} }
} }
} }
if (worldId) {
LogMap::set(strf("server_{}_storage", *worldId),
strf("{} active, {}/{} unloaded ({} held)", m_sectorMetadata.size(), unloaded, skipped + unloaded, skipped));
}
} catch (std::exception const& e) { } catch (std::exception const& e) {
m_db.rollback(); m_db.rollback();
m_db.close(); m_db.close();
@ -712,9 +717,9 @@ void WorldStorage::loadSectorToLevel(Sector const& sector, SectorLoadLevel targe
} }
} }
void WorldStorage::unloadSectorToLevel(Sector const& sector, SectorLoadLevel targetLoadLevel, bool force) { bool WorldStorage::unloadSectorToLevel(Sector const& sector, SectorLoadLevel targetLoadLevel, bool force) {
if (!m_tileArray->sectorValid(sector) || targetLoadLevel == SectorLoadLevel::Loaded) if (!m_tileArray->sectorValid(sector) || targetLoadLevel == SectorLoadLevel::Loaded)
return; return true;
auto entityFactory = Root::singleton().entityFactory(); auto entityFactory = Root::singleton().entityFactory();
@ -728,14 +733,18 @@ void WorldStorage::unloadSectorToLevel(Sector const& sector, SectorLoadLevel tar
// Only store / remove entities who belong to this sector. If an entity // Only store / remove entities who belong to this sector. If an entity
// overlaps with this sector but does not belong to it, we may not want to // overlaps with this sector but does not belong to it, we may not want to
// completely unload it. // completely unload it.
if (!belongsInSector(sector, entity->position())) { auto position = entity->position();
entitiesOverlap = true; if (!belongsInSector(sector, position)) {
if (auto entitySector = sectorForPosition(Vec2I(position))) {
if (auto p = m_sectorMetadata.ptr(*entitySector))
entitiesOverlap |= p->timeToLive > 0.0f;
}
continue; continue;
} }
bool keepAlive = m_generatorFacade->entityKeepAlive(this, entity); bool keepAlive = m_generatorFacade->entityKeepAlive(this, entity);
if (keepAlive && !force) if (keepAlive && !force)
return; return false;
if (m_generatorFacade->entityPersistent(this, entity)) if (m_generatorFacade->entityPersistent(this, entity))
entitiesToStore.append(std::move(entity)); entitiesToStore.append(std::move(entity));
@ -780,14 +789,19 @@ void WorldStorage::unloadSectorToLevel(Sector const& sector, SectorLoadLevel tar
} }
} }
if (targetLoadLevel == SectorLoadLevel::None && metadata.loadLevel > SectorLoadLevel::None && !entitiesOverlap) { if (targetLoadLevel == SectorLoadLevel::None) {
if (metadata.loadLevel > SectorLoadLevel::None && !entitiesOverlap) {
TileSectorStore sectorStore; TileSectorStore sectorStore;
sectorStore.tiles = m_tileArray->unloadSector(sector); sectorStore.tiles = m_tileArray->unloadSector(sector);
sectorStore.generationLevel = metadata.generationLevel; sectorStore.generationLevel = metadata.generationLevel;
m_db.insert(tileSectorKey(sector), writeTileSector(sectorStore)); m_db.insert(tileSectorKey(sector), writeTileSector(sectorStore));
m_sectorMetadata.remove(sector); m_sectorMetadata.remove(sector);
m_generatorFacade->sectorLoadLevelChanged(this, sector, SectorLoadLevel::None); m_generatorFacade->sectorLoadLevelChanged(this, sector, SectorLoadLevel::None);
return true;
} }
return false;
}
return true;
} }
void WorldStorage::syncSector(Sector const& sector) { void WorldStorage::syncSector(Sector const& sector) {

View File

@ -161,7 +161,7 @@ public:
// Ticks down the TTL on sectors and generation queue entries, stores old // Ticks down the TTL on sectors and generation queue entries, stores old
// sectors, expires old generation queue entries, and unloads any zombie // sectors, expires old generation queue entries, and unloads any zombie
// entities. // entities.
void tick(float dt); void tick(float dt, String const* worldId = nullptr);
// Unload all sectors that can be unloaded (if force is specified, ALWAYS // Unload all sectors that can be unloaded (if force is specified, ALWAYS
// unloads all sectors) // unloads all sectors)
@ -265,7 +265,7 @@ private:
// Store and unload the given sector to the given level, given the state of // Store and unload the given sector to the given level, given the state of
// the surrounding sectors. If force is true, will always unload to the // the surrounding sectors. If force is true, will always unload to the
// given level. // given level.
void unloadSectorToLevel(Sector const& sector, SectorLoadLevel targetLoadLevel, bool force = false); bool unloadSectorToLevel(Sector const& sector, SectorLoadLevel targetLoadLevel, bool force = false);
// Sync this sector to disk without unloading it. // Sync this sector to disk without unloading it.
void syncSector(Sector const& sector); void syncSector(Sector const& sector);