mirror of https://github.com/OpenRCT2/OpenRCT2.git
Change the spatial insert to make it ordered (#11252)
* Change the spatial insert to make it ordered This is so that the spatial index can be rebuilt and gauranteed to be in the correct order * Increment Network Version * Make review changes * Remove the gSpriteSpatialIndex from the network * Use safer get function * Final little tweak
This commit is contained in:
parent
c0486e250e
commit
fdf98060cf
|
@ -31,7 +31,7 @@
|
||||||
// This string specifies which version of network stream current build uses.
|
// This string specifies which version of network stream current build uses.
|
||||||
// It is used for making sure only compatible builds get connected, even within
|
// It is used for making sure only compatible builds get connected, even within
|
||||||
// single OpenRCT2 version.
|
// single OpenRCT2 version.
|
||||||
#define NETWORK_STREAM_VERSION "12"
|
#define NETWORK_STREAM_VERSION "13"
|
||||||
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
|
#define NETWORK_STREAM_ID OPENRCT2_VERSION "-" NETWORK_STREAM_VERSION
|
||||||
|
|
||||||
static Peep* _pickup_peep = nullptr;
|
static Peep* _pickup_peep = nullptr;
|
||||||
|
@ -2726,7 +2726,6 @@ bool Network::LoadMap(IStream* stream)
|
||||||
[[maybe_unused]] uint32_t checksum = stream->ReadValue<uint32_t>();
|
[[maybe_unused]] uint32_t checksum = stream->ReadValue<uint32_t>();
|
||||||
|
|
||||||
// Read other data not in normal save files
|
// Read other data not in normal save files
|
||||||
stream->Read(gSpriteSpatialIndex, SPATIAL_INDEX_SIZE * sizeof(uint16_t));
|
|
||||||
gGamePaused = stream->ReadValue<uint32_t>();
|
gGamePaused = stream->ReadValue<uint32_t>();
|
||||||
_guestGenerationProbability = stream->ReadValue<uint32_t>();
|
_guestGenerationProbability = stream->ReadValue<uint32_t>();
|
||||||
_suggestedGuestMaximum = stream->ReadValue<uint32_t>();
|
_suggestedGuestMaximum = stream->ReadValue<uint32_t>();
|
||||||
|
@ -2775,7 +2774,6 @@ bool Network::SaveMap(IStream* stream, const std::vector<const ObjectRepositoryI
|
||||||
s6exporter->SaveGame(stream);
|
s6exporter->SaveGame(stream);
|
||||||
|
|
||||||
// Write other data not in normal save files
|
// Write other data not in normal save files
|
||||||
stream->Write(gSpriteSpatialIndex, SPATIAL_INDEX_SIZE * sizeof(uint16_t));
|
|
||||||
stream->WriteValue<uint32_t>(gGamePaused);
|
stream->WriteValue<uint32_t>(gGamePaused);
|
||||||
stream->WriteValue<uint32_t>(_guestGenerationProbability);
|
stream->WriteValue<uint32_t>(_guestGenerationProbability);
|
||||||
stream->WriteValue<uint32_t>(_suggestedGuestMaximum);
|
stream->WriteValue<uint32_t>(_suggestedGuestMaximum);
|
||||||
|
|
|
@ -92,8 +92,7 @@ rct_sprite* get_sprite(size_t sprite_idx)
|
||||||
|
|
||||||
uint16_t sprite_get_first_in_quadrant(int32_t x, int32_t y)
|
uint16_t sprite_get_first_in_quadrant(int32_t x, int32_t y)
|
||||||
{
|
{
|
||||||
int32_t offset = ((x & 0x1FE0) << 3) | (y >> 5);
|
return gSpriteSpatialIndex[GetSpatialIndexOffset(x, y)];
|
||||||
return gSpriteSpatialIndex[offset];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void invalidate_sprite_max_zoom(SpriteBase* sprite, int32_t maxZoom)
|
static void invalidate_sprite_max_zoom(SpriteBase* sprite, int32_t maxZoom)
|
||||||
|
@ -220,7 +219,10 @@ static size_t GetSpatialIndexOffset(int32_t x, int32_t y)
|
||||||
index = (flooredX << 3) | tileY;
|
index = (flooredX << 3) | tileY;
|
||||||
}
|
}
|
||||||
|
|
||||||
openrct2_assert(index < sizeof(gSpriteSpatialIndex), "GetSpatialIndexOffset out of range");
|
if (index >= sizeof(gSpriteSpatialIndex))
|
||||||
|
{
|
||||||
|
return SPATIAL_INDEX_LOCATION_NULL;
|
||||||
|
}
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,6 +354,8 @@ void sprite_clear_all_unused()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SpriteSpatialInsert(SpriteBase* sprite, const CoordsXY& newLoc);
|
||||||
|
|
||||||
static constexpr uint16_t MAX_MISC_SPRITES = 300;
|
static constexpr uint16_t MAX_MISC_SPRITES = 300;
|
||||||
|
|
||||||
rct_sprite* create_sprite(SPRITE_IDENTIFIER spriteIdentifier)
|
rct_sprite* create_sprite(SPRITE_IDENTIFIER spriteIdentifier)
|
||||||
|
@ -411,8 +415,7 @@ rct_sprite* create_sprite(SPRITE_IDENTIFIER spriteIdentifier)
|
||||||
sprite->flags = 0;
|
sprite->flags = 0;
|
||||||
sprite->sprite_left = LOCATION_NULL;
|
sprite->sprite_left = LOCATION_NULL;
|
||||||
|
|
||||||
sprite->next_in_quadrant = gSpriteSpatialIndex[SPATIAL_INDEX_LOCATION_NULL];
|
SpriteSpatialInsert(sprite, { LOCATION_NULL, 0 });
|
||||||
gSpriteSpatialIndex[SPATIAL_INDEX_LOCATION_NULL] = sprite->sprite_index;
|
|
||||||
|
|
||||||
return (rct_sprite*)sprite;
|
return (rct_sprite*)sprite;
|
||||||
}
|
}
|
||||||
|
@ -613,6 +616,58 @@ void sprite_misc_update_all()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Performs a search to ensure that insert keeps next_in_quadrant in sprite_index order
|
||||||
|
static void SpriteSpatialInsert(SpriteBase* sprite, const CoordsXY& newLoc)
|
||||||
|
{
|
||||||
|
size_t newIndex = GetSpatialIndexOffset(newLoc.x, newLoc.y);
|
||||||
|
|
||||||
|
auto* next = &gSpriteSpatialIndex[newIndex];
|
||||||
|
while (sprite->sprite_index < *next && *next != SPRITE_INDEX_NULL)
|
||||||
|
{
|
||||||
|
auto sprite2 = &get_sprite(*next)->generic;
|
||||||
|
next = &sprite2->next_in_quadrant;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprite->next_in_quadrant = *next;
|
||||||
|
*next = sprite->sprite_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SpriteSpatialRemove(SpriteBase* sprite)
|
||||||
|
{
|
||||||
|
size_t currentIndex = GetSpatialIndexOffset(sprite->x, sprite->y);
|
||||||
|
auto* index = &gSpriteSpatialIndex[currentIndex];
|
||||||
|
|
||||||
|
// This indicates that the spatial index data is incorrect.
|
||||||
|
if (*index == SPRITE_INDEX_NULL)
|
||||||
|
{
|
||||||
|
log_warning("Bad sprite spatial index. Rebuilding the spatial index...");
|
||||||
|
reset_sprite_spatial_index();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* sprite2 = &get_sprite(*index)->generic;
|
||||||
|
while (sprite != sprite2)
|
||||||
|
{
|
||||||
|
index = &sprite2->next_in_quadrant;
|
||||||
|
if (*index == SPRITE_INDEX_NULL)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sprite2 = &get_sprite(*index)->generic;
|
||||||
|
}
|
||||||
|
*index = sprite->next_in_quadrant;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SpriteSpatialMove(SpriteBase* sprite, const CoordsXY& newLoc)
|
||||||
|
{
|
||||||
|
size_t newIndex = GetSpatialIndexOffset(newLoc.x, newLoc.y);
|
||||||
|
size_t currentIndex = GetSpatialIndexOffset(sprite->x, sprite->y);
|
||||||
|
if (newIndex == currentIndex)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SpriteSpatialRemove(sprite);
|
||||||
|
SpriteSpatialInsert(sprite, newLoc);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves a sprite to a new location.
|
* Moves a sprite to a new location.
|
||||||
* rct2: 0x0069E9D3
|
* rct2: 0x0069E9D3
|
||||||
|
@ -629,30 +684,7 @@ void sprite_move(int16_t x, int16_t y, int16_t z, SpriteBase* sprite)
|
||||||
x = LOCATION_NULL;
|
x = LOCATION_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t newIndex = GetSpatialIndexOffset(x, y);
|
SpriteSpatialMove(sprite, { x, y });
|
||||||
size_t currentIndex = GetSpatialIndexOffset(sprite->x, sprite->y);
|
|
||||||
if (newIndex != currentIndex)
|
|
||||||
{
|
|
||||||
uint16_t* spriteIndex = &gSpriteSpatialIndex[currentIndex];
|
|
||||||
if (*spriteIndex != SPRITE_INDEX_NULL)
|
|
||||||
{
|
|
||||||
rct_sprite* sprite2 = get_sprite(*spriteIndex);
|
|
||||||
while (sprite != &sprite2->generic)
|
|
||||||
{
|
|
||||||
spriteIndex = &sprite2->generic.next_in_quadrant;
|
|
||||||
if (*spriteIndex == SPRITE_INDEX_NULL)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
sprite2 = get_sprite(*spriteIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*spriteIndex = sprite->next_in_quadrant;
|
|
||||||
|
|
||||||
int32_t tempSpriteIndex = gSpriteSpatialIndex[newIndex];
|
|
||||||
gSpriteSpatialIndex[newIndex] = sprite->sprite_index;
|
|
||||||
sprite->next_in_quadrant = tempSpriteIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x == LOCATION_NULL)
|
if (x == LOCATION_NULL)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue