| 720 | } |
| 721 | |
| 722 | bool WorldStorage::unloadSectorToLevel(Sector const& sector, SectorLoadLevel targetLoadLevel, bool force) { |
| 723 | if (!m_tileArray->sectorValid(sector) || targetLoadLevel == SectorLoadLevel::Loaded) |
| 724 | return true; |
| 725 | |
| 726 | auto& metadata = m_sectorMetadata[sector]; |
| 727 | bool entitiesOverlap = false; |
| 728 | if (m_entityMap) { |
| 729 | auto entityFactory = Root::singleton().entityFactory(); |
| 730 | List<EntityPtr> entitiesToStore; |
| 731 | List<EntityPtr> entitiesToRemove; |
| 732 | |
| 733 | for (auto& entity : m_entityMap->entityQuery(RectF(m_tileArray->sectorRegion(sector)))) { |
| 734 | // Only store / remove entities who belong to this sector. If an entity |
| 735 | // overlaps with this sector but does not belong to it, we may not want to |
| 736 | // completely unload it. |
| 737 | auto position = entity->position(); |
| 738 | if (!belongsInSector(sector, position)) { |
| 739 | if (auto entitySector = sectorForPosition(Vec2I(position))) { |
| 740 | if (auto p = m_sectorMetadata.ptr(*entitySector)) |
| 741 | entitiesOverlap |= p->timeToLive > 0.0f; |
| 742 | } |
| 743 | continue; |
| 744 | } |
| 745 | |
| 746 | bool keepAlive = m_generatorFacade->entityKeepAlive(this, entity); |
| 747 | if (keepAlive && !force) |
| 748 | return false; |
| 749 | |
| 750 | if (m_generatorFacade->entityPersistent(this, entity)) |
| 751 | entitiesToStore.append(std::move(entity)); |
| 752 | else |
| 753 | entitiesToRemove.append(std::move(entity)); |
| 754 | } |
| 755 | |
| 756 | for (auto const& entity : entitiesToRemove) { |
| 757 | m_entityMap->removeEntity(entity->entityId()); |
| 758 | m_generatorFacade->destructEntity(this, entity); |
| 759 | } |
| 760 | |
| 761 | if (metadata.loadLevel == SectorLoadLevel::Entities || !entitiesToStore.empty()) { |
| 762 | EntitySectorStore sectorStore; |
| 763 | |
| 764 | // If our current load level indicates that we might have entities that are |
| 765 | // not loaded, we need to load and merge with them, otherwise we should be |
| 766 | // overwriting them. |
| 767 | if (metadata.loadLevel < SectorLoadLevel::Entities) { |
| 768 | if (auto res = m_db.find(entitySectorKey(sector))) |
| 769 | sectorStore = readEntitySector(*res); |
| 770 | } |
| 771 | |
| 772 | UniqueIndexStore storedUniques; |
| 773 | for (auto const& entity : entitiesToStore) { |
| 774 | m_entityMap->removeEntity(entity->entityId()); |
| 775 | m_generatorFacade->destructEntity(this, entity); |
| 776 | auto position = entity->position(); |
| 777 | if (auto uniqueId = entity->uniqueId()) |
| 778 | storedUniques.add(*uniqueId, {sector, position}); |
| 779 | sectorStore.append(entityFactory->storeVersionedEntity(entity)); |
nothing calls this directly
no test coverage detected