Rework how entity export works to allow for easier changes in future

This commit is contained in:
duncanspumpkin 2021-02-21 12:39:52 +00:00
parent 3f8386e122
commit b9173642ba
2 changed files with 244 additions and 206 deletions

View File

@ -188,7 +188,7 @@ void S6Exporter::Export()
// Map elements must be reorganised prior to saving otherwise save may be invalid // Map elements must be reorganised prior to saving otherwise save may be invalid
map_reorganise_elements(); map_reorganise_elements();
ExportTileElements(); ExportTileElements();
ExportSprites(); ExportEntitys();
ExportParkName(); ExportParkName();
_s6.initial_cash = gInitialCash; _s6.initial_cash = gInitialCash;
@ -937,21 +937,6 @@ void S6Exporter::ExportMarketingCampaigns()
} }
} }
void S6Exporter::ExportSprites()
{
// Sprites needs to be reset before they get used.
// Might as well reset them in here to zero out the space and improve
// compression ratios. Especially useful for multiplayer servers that
// use zlib on the sent stream.
sprite_clear_all_unused();
for (int32_t i = 0; i < RCT2_MAX_SPRITES; i++)
{
ExportSprite(&_s6.sprites[i], reinterpret_cast<const rct_sprite*>(GetEntity(i)));
}
RebuildEntityLinks();
}
void S6Exporter::RebuildEntityLinks() void S6Exporter::RebuildEntityLinks()
{ {
// Rebuild next/previous linked list entity indexs // Rebuild next/previous linked list entity indexs
@ -1002,33 +987,6 @@ void S6Exporter::RebuildEntityLinks()
} }
} }
void S6Exporter::ExportSprite(RCT2Sprite* dst, const rct_sprite* src)
{
std::memset(dst, 0, sizeof(rct_sprite));
switch (src->misc.sprite_identifier)
{
case SpriteIdentifier::Null:
ExportSpriteCommonProperties(&dst->unknown, &src->misc);
break;
case SpriteIdentifier::Vehicle:
ExportSpriteVehicle(&dst->vehicle, &src->vehicle);
break;
case SpriteIdentifier::Peep:
ExportSpritePeep(&dst->peep, &src->peep);
break;
case SpriteIdentifier::Misc:
ExportSpriteMisc(&dst->unknown, &src->misc);
break;
case SpriteIdentifier::Litter:
ExportSpriteLitter(&dst->litter, &src->litter);
break;
default:
ExportSpriteCommonProperties(&dst->unknown, &src->misc);
log_warning("Sprite identifier %d can not be exported.", src->misc.sprite_identifier);
break;
}
}
constexpr RCT12EntityLinkListOffset GetRCT2LinkListOffset(const SpriteBase* src) constexpr RCT12EntityLinkListOffset GetRCT2LinkListOffset(const SpriteBase* src)
{ {
RCT12EntityLinkListOffset output = RCT12EntityLinkListOffset::Free; RCT12EntityLinkListOffset output = RCT12EntityLinkListOffset::Free;
@ -1082,92 +1040,102 @@ void S6Exporter::ExportSpriteCommonProperties(RCT12SpriteBase* dst, const Sprite
dst->sprite_direction = src->sprite_direction; dst->sprite_direction = src->sprite_direction;
} }
void S6Exporter::ExportSpriteVehicle(RCT2SpriteVehicle* dst, const Vehicle* src) template<> void S6Exporter::ExportEntity(RCT12SpriteBase* dst, const Vehicle* src)
{ {
auto* cdst = static_cast<RCT2SpriteVehicle*>(dst);
const auto* ride = src->GetRide(); const auto* ride = src->GetRide();
ExportSpriteCommonProperties(dst, static_cast<const SpriteBase*>(src)); ExportSpriteCommonProperties(dst, static_cast<const SpriteBase*>(src));
dst->type = EnumValue(src->SubType); cdst->type = EnumValue(src->SubType);
dst->vehicle_sprite_type = src->vehicle_sprite_type; cdst->vehicle_sprite_type = src->vehicle_sprite_type;
dst->bank_rotation = src->bank_rotation; cdst->bank_rotation = src->bank_rotation;
dst->remaining_distance = src->remaining_distance; cdst->remaining_distance = src->remaining_distance;
dst->velocity = src->velocity; cdst->velocity = src->velocity;
dst->acceleration = src->acceleration; cdst->acceleration = src->acceleration;
dst->ride = src->ride; cdst->ride = src->ride;
dst->vehicle_type = src->vehicle_type; cdst->vehicle_type = src->vehicle_type;
dst->colours = src->colours; cdst->colours = src->colours;
dst->track_progress = src->track_progress; cdst->track_progress = src->track_progress;
if (ride != nullptr && ride->mode == RideMode::BoatHire && src->status == Vehicle::Status::TravellingBoat) if (ride != nullptr && ride->mode == RideMode::BoatHire && src->status == Vehicle::Status::TravellingBoat)
{ {
if (src->BoatLocation.isNull()) if (src->BoatLocation.isNull())
{ {
dst->boat_location.setNull(); cdst->boat_location.setNull();
} }
else else
{ {
dst->boat_location = { static_cast<uint8_t>(src->BoatLocation.x / COORDS_XY_STEP), cdst->boat_location = { static_cast<uint8_t>(src->BoatLocation.x / COORDS_XY_STEP),
static_cast<uint8_t>(src->BoatLocation.y / COORDS_XY_STEP) }; static_cast<uint8_t>(src->BoatLocation.y / COORDS_XY_STEP) };
} }
} }
else else
{ {
auto trackType = OpenRCT2TrackTypeToRCT2(src->GetTrackType()); auto trackType = OpenRCT2TrackTypeToRCT2(src->GetTrackType());
// Track direction and type are in the same field // Track direction and type are in the same field
dst->SetTrackType(trackType); cdst->SetTrackType(trackType);
dst->SetTrackDirection(src->GetTrackDirection()); cdst->SetTrackDirection(src->GetTrackDirection());
} }
dst->track_x = src->TrackLocation.x; cdst->track_x = src->TrackLocation.x;
dst->track_y = src->TrackLocation.y; cdst->track_y = src->TrackLocation.y;
dst->track_z = src->TrackLocation.z; cdst->track_z = src->TrackLocation.z;
dst->next_vehicle_on_train = src->next_vehicle_on_train; cdst->next_vehicle_on_train = src->next_vehicle_on_train;
dst->prev_vehicle_on_ride = src->prev_vehicle_on_ride; cdst->prev_vehicle_on_ride = src->prev_vehicle_on_ride;
dst->next_vehicle_on_ride = src->next_vehicle_on_ride; cdst->next_vehicle_on_ride = src->next_vehicle_on_ride;
dst->var_44 = src->var_44; cdst->var_44 = src->var_44;
dst->mass = src->mass; cdst->mass = src->mass;
dst->update_flags = src->update_flags; cdst->update_flags = src->update_flags;
dst->SwingSprite = src->SwingSprite; cdst->SwingSprite = src->SwingSprite;
dst->current_station = src->current_station; cdst->current_station = src->current_station;
dst->current_time = src->current_time; cdst->current_time = src->current_time;
dst->crash_z = src->crash_z; cdst->crash_z = src->crash_z;
dst->status = static_cast<uint8_t>(src->status); cdst->status = static_cast<uint8_t>(src->status);
dst->sub_state = src->sub_state; cdst->sub_state = src->sub_state;
for (size_t i = 0; i < std::size(src->peep); i++) for (size_t i = 0; i < std::size(src->peep); i++)
{ {
dst->peep[i] = src->peep[i]; cdst->peep[i] = src->peep[i];
dst->peep_tshirt_colours[i] = src->peep_tshirt_colours[i]; cdst->peep_tshirt_colours[i] = src->peep_tshirt_colours[i];
} }
dst->num_seats = src->num_seats; cdst->num_seats = src->num_seats;
dst->num_peeps = src->num_peeps; cdst->num_peeps = src->num_peeps;
dst->next_free_seat = src->next_free_seat; cdst->next_free_seat = src->next_free_seat;
dst->restraints_position = src->restraints_position; cdst->restraints_position = src->restraints_position;
dst->crash_x = src->crash_x; cdst->crash_x = src->crash_x;
dst->sound2_flags = src->sound2_flags; cdst->sound2_flags = src->sound2_flags;
dst->spin_sprite = src->spin_sprite; cdst->spin_sprite = src->spin_sprite;
dst->sound1_id = static_cast<uint8_t>(src->sound1_id); cdst->sound1_id = static_cast<uint8_t>(src->sound1_id);
dst->sound1_volume = src->sound1_volume; cdst->sound1_volume = src->sound1_volume;
dst->sound2_id = static_cast<uint8_t>(src->sound2_id); cdst->sound2_id = static_cast<uint8_t>(src->sound2_id);
dst->sound2_volume = src->sound2_volume; cdst->sound2_volume = src->sound2_volume;
dst->sound_vector_factor = src->sound_vector_factor; cdst->sound_vector_factor = src->sound_vector_factor;
dst->time_waiting = src->time_waiting; cdst->time_waiting = src->time_waiting;
dst->speed = src->speed; cdst->speed = src->speed;
dst->powered_acceleration = src->powered_acceleration; cdst->powered_acceleration = src->powered_acceleration;
dst->dodgems_collision_direction = src->dodgems_collision_direction; cdst->dodgems_collision_direction = src->dodgems_collision_direction;
dst->animation_frame = src->animation_frame; cdst->animation_frame = src->animation_frame;
dst->var_C8 = src->var_C8; cdst->var_C8 = src->var_C8;
dst->var_CA = src->var_CA; cdst->var_CA = src->var_CA;
dst->scream_sound_id = static_cast<uint8_t>(src->scream_sound_id); cdst->scream_sound_id = static_cast<uint8_t>(src->scream_sound_id);
dst->TrackSubposition = static_cast<uint8_t>(src->TrackSubposition); cdst->TrackSubposition = static_cast<uint8_t>(src->TrackSubposition);
dst->var_CE = src->var_CE; cdst->var_CE = src->var_CE;
dst->var_CF = src->var_CF; cdst->var_CF = src->var_CF;
dst->lost_time_out = src->lost_time_out; cdst->lost_time_out = src->lost_time_out;
dst->vertical_drop_countdown = src->vertical_drop_countdown; cdst->vertical_drop_countdown = src->vertical_drop_countdown;
dst->var_D3 = src->var_D3; cdst->var_D3 = src->var_D3;
dst->mini_golf_current_animation = src->mini_golf_current_animation; cdst->mini_golf_current_animation = src->mini_golf_current_animation;
dst->mini_golf_flags = src->mini_golf_flags; cdst->mini_golf_flags = src->mini_golf_flags;
dst->ride_subtype = OpenRCT2EntryIndexToRCTEntryIndex(src->ride_subtype); cdst->ride_subtype = OpenRCT2EntryIndexToRCTEntryIndex(src->ride_subtype);
dst->colours_extended = src->colours_extended; cdst->colours_extended = src->colours_extended;
dst->seat_rotation = src->seat_rotation; cdst->seat_rotation = src->seat_rotation;
dst->target_seat_rotation = src->target_seat_rotation; cdst->target_seat_rotation = src->target_seat_rotation;
}
template<> void S6Exporter::ExportEntity(RCT12SpriteBase* dst, const Guest* src)
{
ExportSpritePeep(static_cast<RCT2SpritePeep*>(dst), src);
}
template<> void S6Exporter::ExportEntity(RCT12SpriteBase* dst, const Staff* src)
{
ExportSpritePeep(static_cast<RCT2SpritePeep*>(dst), src);
} }
void S6Exporter::ExportSpritePeep(RCT2SpritePeep* dst, const Peep* src) void S6Exporter::ExportSpritePeep(RCT2SpritePeep* dst, const Peep* src)
@ -1322,104 +1290,177 @@ void S6Exporter::ExportSpritePeep(RCT2SpritePeep* dst, const Peep* src)
dst->item_standard_flags = static_cast<uint32_t>(src->GetItemFlags()); dst->item_standard_flags = static_cast<uint32_t>(src->GetItemFlags());
} }
void S6Exporter::ExportSpriteMisc(RCT12SpriteBase* cdst, const MiscEntity* csrc) template<> void S6Exporter::ExportEntity(RCT12SpriteBase* dst, const SteamParticle* src)
{ {
ExportSpriteCommonProperties(cdst, csrc); auto* cdst = static_cast<RCT12SpriteSteamParticle*>(dst);
cdst->type = EnumValue(csrc->SubType); ExportSpriteCommonProperties(dst, src);
switch (csrc->SubType) cdst->type = EnumValue(src->SubType);
{ cdst->time_to_move = src->time_to_move;
case MiscEntityType::SteamParticle: cdst->frame = src->frame;
{ }
auto src = static_cast<const SteamParticle*>(csrc); template<> void S6Exporter::ExportEntity(RCT12SpriteBase* dst, const MoneyEffect* src)
auto dst = static_cast<RCT12SpriteSteamParticle*>(cdst); {
dst->time_to_move = src->time_to_move; auto* cdst = static_cast<RCT12SpriteMoneyEffect*>(dst);
dst->frame = src->frame; ExportSpriteCommonProperties(dst, src);
break; cdst->type = EnumValue(src->SubType);
} cdst->move_delay = src->MoveDelay;
case MiscEntityType::MoneyEffect: cdst->num_movements = src->NumMovements;
{ cdst->vertical = src->Vertical;
auto src = static_cast<const MoneyEffect*>(csrc); cdst->value = src->Value;
auto dst = static_cast<RCT12SpriteMoneyEffect*>(cdst); cdst->offset_x = src->OffsetX;
dst->move_delay = src->MoveDelay; cdst->wiggle = src->Wiggle;
dst->num_movements = src->NumMovements; }
dst->vertical = src->Vertical; template<> void S6Exporter::ExportEntity(RCT12SpriteBase* dst, const VehicleCrashParticle* src)
dst->value = src->Value; {
dst->offset_x = src->OffsetX; auto* cdst = static_cast<RCT12SpriteCrashedVehicleParticle*>(dst);
dst->wiggle = src->Wiggle; ExportSpriteCommonProperties(dst, src);
break; cdst->type = EnumValue(src->SubType);
} cdst->frame = src->frame;
case MiscEntityType::CrashedVehicleParticle: cdst->time_to_live = src->time_to_live;
{ cdst->frame = src->frame;
auto src = static_cast<const VehicleCrashParticle*>(csrc); cdst->colour[0] = src->colour[0];
auto dst = static_cast<RCT12SpriteCrashedVehicleParticle*>(cdst); cdst->colour[1] = src->colour[1];
dst->frame = src->frame; cdst->crashed_sprite_base = src->crashed_sprite_base;
dst->time_to_live = src->time_to_live; cdst->velocity_x = src->velocity_x;
dst->frame = src->frame; cdst->velocity_y = src->velocity_y;
dst->colour[0] = src->colour[0]; cdst->velocity_z = src->velocity_z;
dst->colour[1] = src->colour[1]; cdst->acceleration_x = src->acceleration_x;
dst->crashed_sprite_base = src->crashed_sprite_base; cdst->acceleration_y = src->acceleration_y;
dst->velocity_x = src->velocity_x; cdst->acceleration_z = src->acceleration_z;
dst->velocity_y = src->velocity_y; }
dst->velocity_z = src->velocity_z; template<> void S6Exporter::ExportEntity(RCT12SpriteBase* dst, const JumpingFountain* src)
dst->acceleration_x = src->acceleration_x; {
dst->acceleration_y = src->acceleration_y; auto* cdst = static_cast<RCT12SpriteJumpingFountain*>(dst);
dst->acceleration_z = src->acceleration_z; ExportSpriteCommonProperties(dst, src);
break; cdst->type = EnumValue(src->SubType);
} cdst->num_ticks_alive = src->NumTicksAlive;
case MiscEntityType::ExplosionCloud: cdst->frame = src->frame;
case MiscEntityType::ExplosionFlare: cdst->fountain_flags = src->FountainFlags;
case MiscEntityType::CrashSplash: cdst->target_x = src->TargetX;
{ cdst->target_y = src->TargetY;
auto src = static_cast<const MiscEntity*>(csrc); cdst->target_y = src->TargetY;
auto dst = static_cast<RCT12SpriteParticle*>(cdst); cdst->iteration = src->Iteration;
dst->frame = src->frame; }
break; template<> void S6Exporter::ExportEntity(RCT12SpriteBase* dst, const Balloon* src)
} {
case MiscEntityType::JumpingFountainWater: auto* cdst = static_cast<RCT12SpriteBalloon*>(dst);
case MiscEntityType::JumpingFountainSnow: ExportSpriteCommonProperties(dst, src);
{ cdst->type = EnumValue(src->SubType);
auto* src = static_cast<const JumpingFountain*>(csrc); cdst->popped = src->popped;
auto* dst = static_cast<RCT12SpriteJumpingFountain*>(cdst); cdst->time_to_move = src->time_to_move;
dst->num_ticks_alive = src->NumTicksAlive; cdst->frame = src->frame;
dst->frame = src->frame; cdst->colour = src->colour;
dst->fountain_flags = src->FountainFlags; }
dst->target_x = src->TargetX; template<> void S6Exporter::ExportEntity(RCT12SpriteBase* dst, const Duck* src)
dst->target_y = src->TargetY; {
dst->target_y = src->TargetY; auto* cdst = static_cast<RCT12SpriteDuck*>(dst);
dst->iteration = src->Iteration; ExportSpriteCommonProperties(dst, src);
break; cdst->type = EnumValue(src->SubType);
} cdst->frame = src->frame;
case MiscEntityType::Balloon: cdst->target_x = src->target_x;
{ cdst->target_y = src->target_y;
auto src = static_cast<const Balloon*>(csrc); cdst->state = EnumValue(src->state);
auto dst = static_cast<RCT12SpriteBalloon*>(cdst); }
dst->popped = src->popped; template<> void S6Exporter::ExportEntity(RCT12SpriteBase* dst, const ExplosionCloud* src)
dst->time_to_move = src->time_to_move; {
dst->frame = src->frame; auto* cdst = static_cast<RCT12SpriteParticle*>(dst);
dst->colour = src->colour; ExportSpriteCommonProperties(dst, src);
break; cdst->type = EnumValue(src->SubType);
} cdst->frame = src->frame;
case MiscEntityType::Duck: }
{ template<> void S6Exporter::ExportEntity(RCT12SpriteBase* dst, const ExplosionFlare* src)
auto src = static_cast<const Duck*>(csrc); {
auto dst = static_cast<RCT12SpriteDuck*>(cdst); auto* cdst = static_cast<RCT12SpriteParticle*>(dst);
dst->frame = src->frame; ExportSpriteCommonProperties(dst, src);
dst->target_x = src->target_x; cdst->type = EnumValue(src->SubType);
dst->target_y = src->target_y; cdst->frame = src->frame;
dst->state = EnumValue(src->state); }
break; template<> void S6Exporter::ExportEntity(RCT12SpriteBase* dst, const CrashSplashParticle* src)
} {
default: auto* cdst = static_cast<RCT12SpriteParticle*>(dst);
log_warning("Misc. sprite type %d can not be exported.", cdst->type); ExportSpriteCommonProperties(dst, src);
break; cdst->type = EnumValue(src->SubType);
} cdst->frame = src->frame;
} }
void S6Exporter::ExportSpriteLitter(RCT12SpriteLitter* dst, const Litter* src) template<> void S6Exporter::ExportEntity(RCT12SpriteBase* dst, const Litter* src)
{ {
auto* cdst = static_cast<RCT12SpriteLitter*>(dst);
ExportSpriteCommonProperties(dst, src); ExportSpriteCommonProperties(dst, src);
dst->type = EnumValue(src->SubType); cdst->type = EnumValue(src->SubType);
dst->creationTick = src->creationTick; cdst->creationTick = src->creationTick;
}
void S6Exporter::ExportEntitys()
{
// Clear everything to free
for (int32_t i = 0; i < RCT2_MAX_SPRITES; i++)
{
auto& entity = _s6.sprites[i];
std::memset(&entity, 0, sizeof(entity));
entity.unknown.sprite_identifier = SpriteIdentifier::Null;
entity.unknown.sprite_index = i;
entity.unknown.linked_list_type_offset = RCT12EntityLinkListOffset::Free;
}
for (auto* entity : EntityList<Guest>(EntityListId::Peep))
{
ExportEntity<Guest>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
for (auto* entity : EntityList<Staff>(EntityListId::Peep))
{
ExportEntity<Staff>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
for (auto* entity : EntityList<Vehicle>(EntityListId::Vehicle))
{
ExportEntity<Vehicle>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
for (auto* entity : EntityList<Vehicle>(EntityListId::TrainHead))
{
ExportEntity<Vehicle>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
for (auto* entity : EntityList<Litter>(EntityListId::Litter))
{
ExportEntity<Litter>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
for (auto* entity : EntityList<Duck>(EntityListId::Misc))
{
ExportEntity<Duck>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
for (auto* entity : EntityList<SteamParticle>(EntityListId::Misc))
{
ExportEntity<SteamParticle>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
for (auto* entity : EntityList<MoneyEffect>(EntityListId::Misc))
{
ExportEntity<MoneyEffect>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
for (auto* entity : EntityList<VehicleCrashParticle>(EntityListId::Misc))
{
ExportEntity<VehicleCrashParticle>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
for (auto* entity : EntityList<JumpingFountain>(EntityListId::Misc))
{
ExportEntity<JumpingFountain>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
for (auto* entity : EntityList<Balloon>(EntityListId::Misc))
{
ExportEntity<Balloon>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
for (auto* entity : EntityList<ExplosionCloud>(EntityListId::Misc))
{
ExportEntity<ExplosionCloud>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
for (auto* entity : EntityList<ExplosionFlare>(EntityListId::Misc))
{
ExportEntity<ExplosionFlare>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
for (auto* entity : EntityList<CrashSplashParticle>(EntityListId::Misc))
{
ExportEntity<CrashSplashParticle>(&_s6.sprites[entity->sprite_index].unknown, entity);
}
RebuildEntityLinks();
} }
void S6Exporter::ExportBanners() void S6Exporter::ExportBanners()

View File

@ -46,13 +46,10 @@ public:
void ExportParkName(); void ExportParkName();
void ExportRides(); void ExportRides();
void ExportRide(rct2_ride* dst, const Ride* src); void ExportRide(rct2_ride* dst, const Ride* src);
void ExportSprites(); void ExportEntitys();
void ExportSprite(RCT2Sprite* dst, const rct_sprite* src); template<typename T> void ExportEntity(RCT12SpriteBase* dst, const T* src);
void ExportSpriteCommonProperties(RCT12SpriteBase* dst, const SpriteBase* src); void ExportSpriteCommonProperties(RCT12SpriteBase* dst, const SpriteBase* src);
void ExportSpriteVehicle(RCT2SpriteVehicle* dst, const Vehicle* src);
void ExportSpritePeep(RCT2SpritePeep* dst, const Peep* src); void ExportSpritePeep(RCT2SpritePeep* dst, const Peep* src);
void ExportSpriteMisc(RCT12SpriteBase* dst, const MiscEntity* src);
void ExportSpriteLitter(RCT12SpriteLitter* dst, const Litter* src);
private: private:
rct_s6_data _s6{}; rct_s6_data _s6{};