1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-27 08:45:00 +01:00

Split free id's into seperate vector (#13924)

This commit is contained in:
Duncan
2021-01-26 07:42:56 +00:00
committed by GitHub
parent c1a1f8f639
commit 8c5cd61b69
7 changed files with 48 additions and 25 deletions

View File

@@ -28,6 +28,7 @@
static rct_sprite _spriteList[MAX_SPRITES];
static std::array<std::list<uint16_t>, EnumValue(EntityListId::Count)> gEntityLists;
static std::vector<uint16_t> _freeIdList;
static bool _spriteFlashingList[MAX_SPRITES];
@@ -105,6 +106,11 @@ uint16_t GetEntityListCount(EntityListId list)
return static_cast<uint16_t>(gEntityLists[static_cast<uint8_t>(list)].size());
}
uint16_t GetNumFreeEntities()
{
return static_cast<uint16_t>(_freeIdList.size());
}
std::string rct_sprite_checksum::ToString() const
{
std::string result;
@@ -221,11 +227,22 @@ void RebuildEntityLists()
list.clear();
}
_freeIdList.clear();
for (auto& ent : _spriteList)
{
// auto listId = EntityIdentifierToListId(ent.misc.sprite_identifier);
gEntityLists[EnumValue(ent.misc.linked_list_index)].push_back(ent.misc.sprite_index);
if (ent.misc.sprite_identifier == SpriteIdentifier::Null)
{
_freeIdList.push_back(ent.misc.sprite_index);
}
else
{
// auto listId = EntityIdentifierToListId(ent.misc.sprite_identifier);
gEntityLists[EnumValue(ent.misc.linked_list_index)].push_back(ent.misc.sprite_index);
}
}
// List needs to be back to front to simplify removing
std::sort(std::begin(_freeIdList), std::end(_freeIdList), std::greater<uint16_t>());
}
const std::list<uint16_t>& GetEntityList(const EntityListId id)
@@ -241,7 +258,6 @@ void reset_sprite_list()
{
gSavedAge = 0;
std::memset(static_cast<void*>(_spriteList), 0, sizeof(_spriteList));
for (int32_t i = 0; i < MAX_SPRITES; ++i)
{
auto* spr = GetEntity(i);
@@ -256,7 +272,6 @@ void reset_sprite_list()
_spriteFlashingList[i] = false;
}
RebuildEntityLists();
reset_sprite_spatial_index();
}
@@ -373,12 +388,17 @@ static void sprite_reset(SpriteBase* sprite)
*/
void sprite_clear_all_unused()
{
for (auto sprite : EntityList(EntityListId::Free))
for (auto index : _freeIdList)
{
sprite_reset(sprite);
sprite->linked_list_index = EntityListId::Free;
auto* entity = GetEntity(index);
if (entity == nullptr)
{
continue;
}
sprite_reset(entity);
entity->linked_list_index = EntityListId::Free;
_spriteFlashingList[sprite->sprite_index] = false;
_spriteFlashingList[entity->sprite_index] = false;
}
}
@@ -391,6 +411,12 @@ static void AddToEntityList(const EntityListId linkedListIndex, SpriteBase* enti
list.insert(std::lower_bound(std::begin(list), std::end(list), entity->sprite_index), entity->sprite_index);
}
static void AddToFreeList(uint16_t index)
{
// Free list must be in reverse sprite_index order to prevent desync issues
_freeIdList.insert(std::upper_bound(std::rbegin(_freeIdList), std::rend(_freeIdList), index).base(), index);
}
static void RemoveFromEntityList(SpriteBase* entity)
{
auto& list = gEntityLists[EnumValue(entity->linked_list_index)];
@@ -403,7 +429,7 @@ static void RemoveFromEntityList(SpriteBase* entity)
rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier, EntityListId linkedListIndex)
{
if (GetEntityListCount(EntityListId::Free) == 0)
if (_freeIdList.size() == 0)
{
// No free sprites.
return nullptr;
@@ -415,19 +441,19 @@ rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier, EntityListId linked
// free it will fail to keep slots for more relevant sprites.
// Also there can't be more than MAX_MISC_SPRITES sprites in this list.
uint16_t miscSlotsRemaining = MAX_MISC_SPRITES - GetEntityListCount(EntityListId::Misc);
if (miscSlotsRemaining >= GetEntityListCount(EntityListId::Free))
if (miscSlotsRemaining >= _freeIdList.size())
{
return nullptr;
}
}
auto* sprite = GetEntity(gEntityLists[static_cast<uint8_t>(EntityListId::Free)].front());
auto* sprite = GetEntity(_freeIdList.back());
if (sprite == nullptr)
{
return nullptr;
}
gEntityLists[static_cast<uint8_t>(EntityListId::Free)].pop_front();
RemoveFromEntityList(sprite); // remove from Free list
_freeIdList.pop_back();
AddToEntityList(linkedListIndex, sprite);
// Need to reset all sprite data, as the uninitialised values
// may contain garbage and cause a desync later on.
@@ -686,7 +712,7 @@ void sprite_remove(SpriteBase* sprite)
EntityTweener::Get().RemoveEntity(sprite);
RemoveFromEntityList(sprite); // remove from existing list
AddToEntityList(EntityListId::Free, sprite);
AddToFreeList(sprite->sprite_index);
SpriteSpatialRemove(sprite);
sprite_reset(sprite);