Implement train view and remove linked_list_index (#13956)

* Make train manager view

* Remove linked list index field

* Remove merge mistake

* Fix further rebase errors

* Rename and add comments

* Update replays

* Fix Xcode project

* Increment network version

Co-authored-by: Michael Steenbeek <m.o.steenbeek@gmail.com>
This commit is contained in:
Duncan 2021-03-15 08:13:00 +00:00 committed by GitHub
parent cc68b8bf4d
commit 5474194905
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 166 additions and 85 deletions

View File

@ -48,8 +48,8 @@ set(TITLE_SEQUENCE_SHA1 "304d13a126c15bf2c86ff13b81a2f2cc1856ac8d")
set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0.21/objects.zip") set(OBJECTS_URL "https://github.com/OpenRCT2/objects/releases/download/v1.0.21/objects.zip")
set(OBJECTS_SHA1 "c38af45d51a6e440386180feacf76c64720b6ac5") set(OBJECTS_SHA1 "c38af45d51a6e440386180feacf76c64720b6ac5")
set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v0.0.31/replays.zip") set(REPLAYS_URL "https://github.com/OpenRCT2/replays/releases/download/v0.0.32/replays.zip")
set(REPLAYS_SHA1 "693BDD6F4B7C3B312AABEBCAEA4800FE97B33527") set(REPLAYS_SHA1 "45843591A8C6739CA1D60899B7E54FC0792EF896")
option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.") option(FORCE32 "Force 32-bit build. It will add `-m32` to compiler flags.")
option(WITH_TESTS "Build tests") option(WITH_TESTS "Build tests")

View File

@ -51,6 +51,7 @@
4C3B4236205914F7000C5BB7 /* InGameConsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3B4234205914F7000C5BB7 /* InGameConsole.cpp */; }; 4C3B4236205914F7000C5BB7 /* InGameConsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3B4234205914F7000C5BB7 /* InGameConsole.cpp */; };
4C724B2221F0AD790012ADD0 /* BenchSpriteSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C724B2121F0AD790012ADD0 /* BenchSpriteSort.cpp */; }; 4C724B2221F0AD790012ADD0 /* BenchSpriteSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C724B2121F0AD790012ADD0 /* BenchSpriteSort.cpp */; };
4C81F7E124672C4D000E61BF /* CustomListView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C81F7DF24672C4D000E61BF /* CustomListView.cpp */; }; 4C81F7E124672C4D000E61BF /* CustomListView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C81F7DF24672C4D000E61BF /* CustomListView.cpp */; };
4C882FBA25FEA80E0039D1C4 /* TrainManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C882FB825FEA80D0039D1C4 /* TrainManager.cpp */; };
4C8A6FF323EB5326001A8255 /* Http.cURL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C8A6FF223EB5326001A8255 /* Http.cURL.cpp */; }; 4C8A6FF323EB5326001A8255 /* Http.cURL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C8A6FF223EB5326001A8255 /* Http.cURL.cpp */; };
4C8BB67925533D4C005C8830 /* FileStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C8BB67825533D4C005C8830 /* FileStream.cpp */; }; 4C8BB67925533D4C005C8830 /* FileStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C8BB67825533D4C005C8830 /* FileStream.cpp */; };
4C8BB67C25533D59005C8830 /* JobPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C8BB67B25533D59005C8830 /* JobPool.cpp */; }; 4C8BB67C25533D59005C8830 /* JobPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C8BB67B25533D59005C8830 /* JobPool.cpp */; };
@ -1017,6 +1018,10 @@
4C81F7DF24672C4D000E61BF /* CustomListView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CustomListView.cpp; path = scripting/CustomListView.cpp; sourceTree = "<group>"; }; 4C81F7DF24672C4D000E61BF /* CustomListView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CustomListView.cpp; path = scripting/CustomListView.cpp; sourceTree = "<group>"; };
4C81F7E024672C4D000E61BF /* CustomListView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomListView.h; path = scripting/CustomListView.h; sourceTree = "<group>"; }; 4C81F7E024672C4D000E61BF /* CustomListView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomListView.h; path = scripting/CustomListView.h; sourceTree = "<group>"; };
4C81F7E224672C58000E61BF /* ScTileSelection.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ScTileSelection.hpp; path = scripting/ScTileSelection.hpp; sourceTree = "<group>"; }; 4C81F7E224672C58000E61BF /* ScTileSelection.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = ScTileSelection.hpp; path = scripting/ScTileSelection.hpp; sourceTree = "<group>"; };
4C882FB825FEA80D0039D1C4 /* TrainManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TrainManager.cpp; sourceTree = "<group>"; };
4C882FB925FEA80E0039D1C4 /* TrainManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TrainManager.h; sourceTree = "<group>"; };
4C882FBB25FEA8260039D1C4 /* VehicleColour.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VehicleColour.h; sourceTree = "<group>"; };
4C882FBC25FEA8270039D1C4 /* VehicleEntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VehicleEntry.h; sourceTree = "<group>"; };
4C8A6FF123EB5325001A8255 /* Http.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Http.h; sourceTree = "<group>"; }; 4C8A6FF123EB5325001A8255 /* Http.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Http.h; sourceTree = "<group>"; };
4C8A6FF223EB5326001A8255 /* Http.cURL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Http.cURL.cpp; sourceTree = "<group>"; }; 4C8A6FF223EB5326001A8255 /* Http.cURL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Http.cURL.cpp; sourceTree = "<group>"; };
4C8B426E1EEB1ABD00F015CA /* X8DrawingEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = X8DrawingEngine.cpp; sourceTree = "<group>"; }; 4C8B426E1EEB1ABD00F015CA /* X8DrawingEngine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = X8DrawingEngine.cpp; sourceTree = "<group>"; };
@ -3587,10 +3592,14 @@
F73E320E2011589F00C4D975 /* TrackDesignSave.cpp */, F73E320E2011589F00C4D975 /* TrackDesignSave.cpp */,
4C7B540B20060D8100A52E21 /* TrackPaint.cpp */, 4C7B540B20060D8100A52E21 /* TrackPaint.cpp */,
4C7B540C20060D8100A52E21 /* TrackPaint.h */, 4C7B540C20060D8100A52E21 /* TrackPaint.h */,
4C882FB825FEA80D0039D1C4 /* TrainManager.cpp */,
4C882FB925FEA80E0039D1C4 /* TrainManager.h */,
4CFE4E831F90AF41005243C2 /* Vehicle.cpp */, 4CFE4E831F90AF41005243C2 /* Vehicle.cpp */,
4CFE4E841F90AF41005243C2 /* Vehicle.h */, 4CFE4E841F90AF41005243C2 /* Vehicle.h */,
4C882FBB25FEA8260039D1C4 /* VehicleColour.h */,
4C7B54052005735F00A52E21 /* VehicleData.cpp */, 4C7B54052005735F00A52E21 /* VehicleData.cpp */,
4C7B540920060D7000A52E21 /* VehicleData.h */, 4C7B540920060D7000A52E21 /* VehicleData.h */,
4C882FBC25FEA8270039D1C4 /* VehicleEntry.h */,
4C7B54072005736700A52E21 /* VehiclePaint.cpp */, 4C7B54072005736700A52E21 /* VehiclePaint.cpp */,
4C7B540A20060D7900A52E21 /* VehiclePaint.h */, 4C7B540A20060D7900A52E21 /* VehiclePaint.h */,
4CB2716824195B45000CF9EE /* VehicleSubpositionData.cpp */, 4CB2716824195B45000CF9EE /* VehicleSubpositionData.cpp */,
@ -4502,6 +4511,7 @@
6341F4E12400AA0F0052902B /* Drawing.Sprite.RLE.cpp in Sources */, 6341F4E12400AA0F0052902B /* Drawing.Sprite.RLE.cpp in Sources */,
C666EE6C1F37ACB10061AA04 /* Changelog.cpp in Sources */, C666EE6C1F37ACB10061AA04 /* Changelog.cpp in Sources */,
C64644FC1F3FA4120026AC2D /* Footpath.cpp in Sources */, C64644FC1F3FA4120026AC2D /* Footpath.cpp in Sources */,
4C882FBA25FEA80E0039D1C4 /* TrainManager.cpp in Sources */,
F76C887C1EC5324E00FA49E2 /* MemoryAudioSource.cpp in Sources */, F76C887C1EC5324E00FA49E2 /* MemoryAudioSource.cpp in Sources */,
C654DF3D1F69C0430040F43D /* TrackDesignPlace.cpp in Sources */, C654DF3D1F69C0430040F43D /* TrackDesignPlace.cpp in Sources */,
C666EE721F37ACB10061AA04 /* Multiplayer.cpp in Sources */, C666EE721F37ACB10061AA04 /* Multiplayer.cpp in Sources */,

View File

@ -48,8 +48,8 @@
<TitleSequencesSha1>304d13a126c15bf2c86ff13b81a2f2cc1856ac8d</TitleSequencesSha1> <TitleSequencesSha1>304d13a126c15bf2c86ff13b81a2f2cc1856ac8d</TitleSequencesSha1>
<ObjectsUrl>https://github.com/OpenRCT2/objects/releases/download/v1.0.21/objects.zip</ObjectsUrl> <ObjectsUrl>https://github.com/OpenRCT2/objects/releases/download/v1.0.21/objects.zip</ObjectsUrl>
<ObjectsSha1>c38af45d51a6e440386180feacf76c64720b6ac5</ObjectsSha1> <ObjectsSha1>c38af45d51a6e440386180feacf76c64720b6ac5</ObjectsSha1>
<ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.31/replays.zip</ReplaysUrl> <ReplaysUrl>https://github.com/OpenRCT2/replays/releases/download/v0.0.32/replays.zip</ReplaysUrl>
<ReplaysSha1>693BDD6F4B7C3B312AABEBCAEA4800FE97B33527</ReplaysSha1> <ReplaysSha1>45843591A8C6739CA1D60899B7E54FC0792EF896</ReplaysSha1>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@ -26,6 +26,7 @@
#include <openrct2/localisation/Localisation.h> #include <openrct2/localisation/Localisation.h>
#include <openrct2/ride/RideData.h> #include <openrct2/ride/RideData.h>
#include <openrct2/ride/Track.h> #include <openrct2/ride/Track.h>
#include <openrct2/ride/TrainManager.h>
#include <openrct2/world/EntityList.h> #include <openrct2/world/EntityList.h>
#include <openrct2/world/Entrance.h> #include <openrct2/world/Entrance.h>
#include <openrct2/world/Footpath.h> #include <openrct2/world/Footpath.h>
@ -1118,7 +1119,7 @@ static void window_map_paint_peep_overlay(rct_drawpixelinfo* dpi)
*/ */
static void window_map_paint_train_overlay(rct_drawpixelinfo* dpi) static void window_map_paint_train_overlay(rct_drawpixelinfo* dpi)
{ {
for (auto train : EntityList<Vehicle>(EntityListId::TrainHead)) for (auto train : TrainManager::View())
{ {
for (Vehicle* vehicle = train; vehicle != nullptr; vehicle = GetEntity<Vehicle>(vehicle->next_vehicle_on_train)) for (Vehicle* vehicle = train; vehicle != nullptr; vehicle = GetEntity<Vehicle>(vehicle->next_vehicle_on_train))
{ {

View File

@ -201,7 +201,6 @@ struct GameStateSnapshots final : public IGameStateSnapshots
const SpriteBase& spriteBase, const SpriteBase& spriteCmp, GameStateSpriteChange_t& changeData) const const SpriteBase& spriteBase, const SpriteBase& spriteCmp, GameStateSpriteChange_t& changeData) const
{ {
COMPARE_FIELD(SpriteBase, sprite_identifier); COMPARE_FIELD(SpriteBase, sprite_identifier);
COMPARE_FIELD(SpriteBase, linked_list_index);
COMPARE_FIELD(SpriteBase, sprite_index); COMPARE_FIELD(SpriteBase, sprite_index);
COMPARE_FIELD(SpriteBase, flags); COMPARE_FIELD(SpriteBase, flags);
COMPARE_FIELD(SpriteBase, x); COMPARE_FIELD(SpriteBase, x);

View File

@ -142,7 +142,6 @@ GameActions::Result::Ptr StaffHireNewAction::QueryExecute(bool execute) const
} }
else else
{ {
newPeep->sprite_identifier = SpriteIdentifier::Peep;
newPeep->WindowInvalidateFlags = 0; newPeep->WindowInvalidateFlags = 0;
newPeep->Action = PeepActionType::None2; newPeep->Action = PeepActionType::None2;
newPeep->SpecialSprite = 0; newPeep->SpecialSprite = 0;

View File

@ -383,6 +383,7 @@
<ClInclude Include="ride\TrackDesign.h" /> <ClInclude Include="ride\TrackDesign.h" />
<ClInclude Include="ride\TrackDesignRepository.h" /> <ClInclude Include="ride\TrackDesignRepository.h" />
<ClInclude Include="ride\TrackPaint.h" /> <ClInclude Include="ride\TrackPaint.h" />
<ClInclude Include="ride\TrainManager.h" />
<ClInclude Include="ride\transport\meta\Chairlift.h" /> <ClInclude Include="ride\transport\meta\Chairlift.h" />
<ClInclude Include="ride\transport\meta\Lift.h" /> <ClInclude Include="ride\transport\meta\Lift.h" />
<ClInclude Include="ride\transport\meta\MiniatureRailway.h" /> <ClInclude Include="ride\transport\meta\MiniatureRailway.h" />
@ -815,6 +816,7 @@
<ClCompile Include="ride\TrackDesignRepository.cpp" /> <ClCompile Include="ride\TrackDesignRepository.cpp" />
<ClCompile Include="ride\TrackDesignSave.cpp" /> <ClCompile Include="ride\TrackDesignSave.cpp" />
<ClCompile Include="ride\TrackPaint.cpp" /> <ClCompile Include="ride\TrackPaint.cpp" />
<ClCompile Include="ride\TrainManager.cpp" />
<ClCompile Include="ride\transport\Chairlift.cpp" /> <ClCompile Include="ride\transport\Chairlift.cpp" />
<ClCompile Include="ride\transport\Lift.cpp" /> <ClCompile Include="ride\transport\Lift.cpp" />
<ClCompile Include="ride\transport\MiniatureRailway.cpp" /> <ClCompile Include="ride\transport\MiniatureRailway.cpp" />

View File

@ -36,7 +36,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 "1" #define NETWORK_STREAM_VERSION "2"
#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;

View File

@ -1612,7 +1612,6 @@ Peep* Peep::Generate(const CoordsXYZ& coords)
return nullptr; return nullptr;
Peep* peep = &create_sprite(SpriteIdentifier::Peep)->peep; Peep* peep = &create_sprite(SpriteIdentifier::Peep)->peep;
peep->sprite_identifier = SpriteIdentifier::Peep;
peep->SpriteType = PeepSpriteType::Normal; peep->SpriteType = PeepSpriteType::Normal;
peep->OutsideOfPark = true; peep->OutsideOfPark = true;
peep->State = PeepState::Falling; peep->State = PeepState::Falling;

View File

@ -37,6 +37,7 @@
#include "../ride/RideData.h" #include "../ride/RideData.h"
#include "../ride/Station.h" #include "../ride/Station.h"
#include "../ride/Track.h" #include "../ride/Track.h"
#include "../ride/TrainManager.h"
#include "../scenario/Scenario.h" #include "../scenario/Scenario.h"
#include "../scenario/ScenarioRepository.h" #include "../scenario/ScenarioRepository.h"
#include "../scenario/ScenarioSources.h" #include "../scenario/ScenarioSources.h"
@ -1136,11 +1137,7 @@ private:
rct1_vehicle* srcVehicle = &_s4.sprites[i].vehicle; rct1_vehicle* srcVehicle = &_s4.sprites[i].vehicle;
if (srcVehicle->x != LOCATION_NULL) if (srcVehicle->x != LOCATION_NULL)
{ {
// If vehicle is the first car on a train add to train list Vehicle* vehicle = reinterpret_cast<Vehicle*>(create_sprite(SpriteIdentifier::Vehicle));
auto isFirstCar = srcVehicle->type == static_cast<uint8_t>(Vehicle::Type::Head);
auto llt = isFirstCar ? EntityListId::TrainHead : EntityListId::Vehicle;
Vehicle* vehicle = reinterpret_cast<Vehicle*>(create_sprite(SpriteIdentifier::Vehicle, llt));
spriteIndexMap[i] = vehicle->sprite_index; spriteIndexMap[i] = vehicle->sprite_index;
vehicles.push_back(vehicle); vehicles.push_back(vehicle);

View File

@ -43,6 +43,7 @@
#include "../ride/ShopItem.h" #include "../ride/ShopItem.h"
#include "../ride/Station.h" #include "../ride/Station.h"
#include "../ride/Track.h" #include "../ride/Track.h"
#include "../ride/TrainManager.h"
#include "../scenario/Scenario.h" #include "../scenario/Scenario.h"
#include "../scenario/ScenarioRepository.h" #include "../scenario/ScenarioRepository.h"
#include "../util/SawyerCoding.h" #include "../util/SawyerCoding.h"
@ -1680,7 +1681,6 @@ public:
void ImportSpriteCommonProperties(SpriteBase* dst, const RCT12SpriteBase* src) void ImportSpriteCommonProperties(SpriteBase* dst, const RCT12SpriteBase* src)
{ {
dst->sprite_identifier = src->sprite_identifier; dst->sprite_identifier = src->sprite_identifier;
dst->linked_list_index = static_cast<EntityListId>(EnumValue(src->linked_list_type_offset) >> 1);
dst->sprite_height_negative = src->sprite_height_negative; dst->sprite_height_negative = src->sprite_height_negative;
dst->sprite_index = src->sprite_index; dst->sprite_index = src->sprite_index;
dst->flags = src->flags; dst->flags = src->flags;

View File

@ -24,9 +24,7 @@
Vehicle* cable_lift_segment_create( Vehicle* cable_lift_segment_create(
Ride& ride, int32_t x, int32_t y, int32_t z, int32_t direction, uint16_t var_44, int32_t remaining_distance, bool head) Ride& ride, int32_t x, int32_t y, int32_t z, int32_t direction, uint16_t var_44, int32_t remaining_distance, bool head)
{ {
Vehicle* current = &( Vehicle* current = &(create_sprite(SpriteIdentifier::Vehicle)->vehicle);
create_sprite(SpriteIdentifier::Vehicle, head ? EntityListId::TrainHead : EntityListId::Vehicle)->vehicle);
current->sprite_identifier = SpriteIdentifier::Vehicle;
current->ride = ride.id; current->ride = ride.id;
current->ride_subtype = RIDE_ENTRY_INDEX_NULL; current->ride_subtype = RIDE_ENTRY_INDEX_NULL;
if (head) if (head)

View File

@ -63,6 +63,7 @@
#include "Track.h" #include "Track.h"
#include "TrackData.h" #include "TrackData.h"
#include "TrackDesign.h" #include "TrackDesign.h"
#include "TrainManager.h"
#include "Vehicle.h" #include "Vehicle.h"
#include <algorithm> #include <algorithm>
@ -4092,12 +4093,10 @@ static Vehicle* vehicle_create_car(
return nullptr; return nullptr;
auto vehicleEntry = &rideEntry->vehicles[vehicleEntryIndex]; auto vehicleEntry = &rideEntry->vehicles[vehicleEntryIndex];
auto vehicle = &create_sprite(SpriteIdentifier::Vehicle, carIndex == 0 ? EntityListId::TrainHead : EntityListId::Vehicle) auto vehicle = &create_sprite(SpriteIdentifier::Vehicle)->vehicle;
->vehicle;
if (vehicle == nullptr) if (vehicle == nullptr)
return nullptr; return nullptr;
vehicle->sprite_identifier = SpriteIdentifier::Vehicle;
vehicle->ride = rideIndex; vehicle->ride = rideIndex;
vehicle->ride_subtype = ride->subtype; vehicle->ride_subtype = ride->subtype;

View File

@ -0,0 +1,37 @@
/*****************************************************************************
* Copyright (c) 2014-2021 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#include "TrainManager.h"
#include "../world/Entity.h"
#include "../world/EntityList.h"
#include "Vehicle.h"
namespace TrainManager
{
View::Iterator& View::Iterator::operator++()
{
Entity = nullptr;
while (iter != end && Entity == nullptr)
{
Entity = GetEntity<Vehicle>(*iter++);
if (Entity && !Entity->IsHead())
{
Entity = nullptr;
}
}
return *this;
}
View::View()
{
vec = &GetEntityList(EntityListId::Vehicle);
}
} // namespace TrainManager

View File

@ -0,0 +1,77 @@
/*****************************************************************************
* Copyright (c) 2014-2021 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#pragma once
#include <cstdint>
#include <list>
struct Vehicle;
namespace TrainManager
{
// Iteration of heads of trains
class View
{
private:
const std::list<uint16_t>* vec;
class Iterator
{
private:
std::list<uint16_t>::const_iterator iter;
std::list<uint16_t>::const_iterator end;
Vehicle* Entity = nullptr;
public:
Iterator(std::list<uint16_t>::const_iterator _iter, std::list<uint16_t>::const_iterator _end)
: iter(_iter)
, end(_end)
{
++(*this);
}
Iterator& operator++();
Iterator operator++(int)
{
Iterator retval = *this;
++(*this);
return retval;
}
bool operator==(Iterator other) const
{
return Entity == other.Entity;
}
bool operator!=(Iterator other) const
{
return !(*this == other);
}
Vehicle* operator*()
{
return Entity;
}
// iterator traits
using difference_type = std::ptrdiff_t;
using value_type = Vehicle;
using pointer = const Vehicle*;
using reference = const Vehicle&;
using iterator_category = std::forward_iterator_tag;
};
public:
View();
Iterator begin()
{
return Iterator(std::cbegin(*vec), std::cend(*vec));
}
Iterator end()
{
return Iterator(std::cend(*vec), std::cend(*vec));
}
};
} // namespace TrainManager

View File

@ -40,6 +40,7 @@
#include "Station.h" #include "Station.h"
#include "Track.h" #include "Track.h"
#include "TrackData.h" #include "TrackData.h"
#include "TrainManager.h"
#include "VehicleData.h" #include "VehicleData.h"
#include "VehicleSubpositionData.h" #include "VehicleSubpositionData.h"
@ -1295,7 +1296,7 @@ void vehicle_sounds_update()
vehicle_sounds_update_window_setup(); vehicle_sounds_update_window_setup();
for (auto vehicle : EntityList<Vehicle>(EntityListId::TrainHead)) for (auto vehicle : TrainManager::View())
{ {
vehicle->UpdateSoundParams(vehicleSoundParamsList); vehicle->UpdateSoundParams(vehicleSoundParamsList);
} }
@ -1378,7 +1379,7 @@ void vehicle_update_all()
if ((gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) && gS6Info.editor_step != EditorStep::RollercoasterDesigner) if ((gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) && gS6Info.editor_step != EditorStep::RollercoasterDesigner)
return; return;
for (auto vehicle : EntityList<Vehicle>(EntityListId::TrainHead)) for (auto vehicle : TrainManager::View())
{ {
vehicle->Update(); vehicle->Update();
} }
@ -7243,7 +7244,6 @@ static void steam_particle_create(const CoordsXYZ& coords)
steam->sprite_width = 20; steam->sprite_width = 20;
steam->sprite_height_negative = 18; steam->sprite_height_negative = 18;
steam->sprite_height_positive = 16; steam->sprite_height_positive = 16;
steam->sprite_identifier = SpriteIdentifier::Misc;
steam->SubType = MiscEntityType::SteamParticle; steam->SubType = MiscEntityType::SteamParticle;
steam->frame = 256; steam->frame = 256;
steam->time_to_move = 0; steam->time_to_move = 0;

View File

@ -13,6 +13,7 @@
# include "../common.h" # include "../common.h"
# include "../ride/Ride.h" # include "../ride/Ride.h"
# include "../ride/TrainManager.h"
# include "../world/EntityList.h" # include "../world/EntityList.h"
# include "../world/Map.h" # include "../world/Map.h"
# include "Duktape.hpp" # include "Duktape.hpp"
@ -108,7 +109,17 @@ namespace OpenRCT2::Scripting
} }
if (type == "car") if (type == "car")
{ {
targetList = EntityListId::TrainHead; std::vector<DukValue> result;
for (auto trainHead : TrainManager::View())
{
for (auto carId = trainHead->sprite_index; carId != SPRITE_INDEX_NULL;)
{
auto car = GetEntity<Vehicle>(carId);
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScVehicle>(carId)));
carId = car->next_vehicle_on_train;
}
}
return result;
} }
else if (type == "litter") else if (type == "litter")
{ {
@ -138,15 +149,6 @@ namespace OpenRCT2::Scripting
else else
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScGuest>(sprite->sprite_index))); result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScGuest>(sprite->sprite_index)));
} }
else if (targetList == EntityListId::TrainHead)
{
for (auto carId = sprite->sprite_index; carId != SPRITE_INDEX_NULL;)
{
auto car = GetEntity<Vehicle>(carId);
result.push_back(GetObjectAsDukValue(_context, std::make_shared<ScVehicle>(carId)));
carId = car->next_vehicle_on_train;
}
}
else if (targetList == EntityListId::Misc) else if (targetList == EntityListId::Misc)
{ {
auto* misc = sprite->As<MiscEntity>(); auto* misc = sprite->As<MiscEntity>();

View File

@ -85,7 +85,6 @@ void create_balloon(const CoordsXYZ& balloonPos, int32_t colour, bool isPopped)
rct_sprite* sprite = create_sprite(SpriteIdentifier::Misc); rct_sprite* sprite = create_sprite(SpriteIdentifier::Misc);
if (sprite == nullptr) if (sprite == nullptr)
return; return;
sprite->misc.sprite_identifier = SpriteIdentifier::Misc;
sprite->misc.SubType = MiscEntityType::Balloon; sprite->misc.SubType = MiscEntityType::Balloon;
auto balloon = sprite->misc.As<Balloon>(); auto balloon = sprite->misc.As<Balloon>();
if (balloon == nullptr) if (balloon == nullptr)

View File

@ -291,7 +291,6 @@ void create_duck(const CoordsXY& pos)
targetPos.x += offsetXY; targetPos.x += offsetXY;
targetPos.y += offsetXY; targetPos.y += offsetXY;
sprite->misc.sprite_identifier = SpriteIdentifier::Misc;
sprite->misc.SubType = MiscEntityType::Duck; sprite->misc.SubType = MiscEntityType::Duck;
auto duck = sprite->misc.As<Duck>(); auto duck = sprite->misc.As<Duck>();
if (duck == nullptr) if (duck == nullptr)

View File

@ -138,7 +138,6 @@ void JumpingFountain::Create(
jumpingFountain->sprite_width = 33; jumpingFountain->sprite_width = 33;
jumpingFountain->sprite_height_negative = 36; jumpingFountain->sprite_height_negative = 36;
jumpingFountain->sprite_height_positive = 12; jumpingFountain->sprite_height_positive = 12;
jumpingFountain->sprite_identifier = SpriteIdentifier::Misc;
jumpingFountain->MoveTo(newLoc); jumpingFountain->MoveTo(newLoc);
jumpingFountain->SubType = newType == JUMPING_FOUNTAIN_TYPE_SNOW ? MiscEntityType::JumpingFountainSnow jumpingFountain->SubType = newType == JUMPING_FOUNTAIN_TYPE_SNOW ? MiscEntityType::JumpingFountainSnow
: MiscEntityType::JumpingFountainWater; : MiscEntityType::JumpingFountainWater;

View File

@ -42,7 +42,6 @@ void MoneyEffect::CreateAt(money32 value, const CoordsXYZ& effectPos, bool verti
moneyEffect->sprite_width = 64; moneyEffect->sprite_width = 64;
moneyEffect->sprite_height_negative = 20; moneyEffect->sprite_height_negative = 20;
moneyEffect->sprite_height_positive = 30; moneyEffect->sprite_height_positive = 30;
moneyEffect->sprite_identifier = SpriteIdentifier::Misc;
moneyEffect->MoveTo(effectPos); moneyEffect->MoveTo(effectPos);
moneyEffect->SubType = MiscEntityType::MoneyEffect; moneyEffect->SubType = MiscEntityType::MoneyEffect;
moneyEffect->NumMovements = 0; moneyEffect->NumMovements = 0;

View File

@ -39,7 +39,6 @@ void crashed_vehicle_particle_create(rct_vehicle_colour colours, const CoordsXYZ
sprite->sprite_width = 8; sprite->sprite_width = 8;
sprite->sprite_height_negative = 8; sprite->sprite_height_negative = 8;
sprite->sprite_height_positive = 8; sprite->sprite_height_positive = 8;
sprite->sprite_identifier = SpriteIdentifier::Misc;
sprite->MoveTo(vehiclePos); sprite->MoveTo(vehiclePos);
sprite->SubType = MiscEntityType::CrashedVehicleParticle; sprite->SubType = MiscEntityType::CrashedVehicleParticle;
@ -128,7 +127,6 @@ void crash_splash_create(const CoordsXYZ& splashPos)
sprite->sprite_width = 33; sprite->sprite_width = 33;
sprite->sprite_height_negative = 51; sprite->sprite_height_negative = 51;
sprite->sprite_height_positive = 16; sprite->sprite_height_positive = 16;
sprite->sprite_identifier = SpriteIdentifier::Misc;
sprite->MoveTo(splashPos + CoordsXYZ{ 0, 0, 3 }); sprite->MoveTo(splashPos + CoordsXYZ{ 0, 0, 3 });
sprite->SubType = MiscEntityType::CrashSplash; sprite->SubType = MiscEntityType::CrashSplash;
sprite->frame = 0; sprite->frame = 0;

View File

@ -237,8 +237,8 @@ void RebuildEntityLists()
} }
else else
{ {
// auto listId = EntityIdentifierToListId(ent.misc.sprite_identifier); auto listId = EntityIdentifierToListId(ent.misc.sprite_identifier);
gEntityLists[EnumValue(ent.misc.linked_list_index)].push_back(ent.misc.sprite_index); gEntityLists[EnumValue(listId)].push_back(ent.misc.sprite_index);
} }
} }
// List needs to be back to front to simplify removing // List needs to be back to front to simplify removing
@ -268,7 +268,6 @@ void reset_sprite_list()
spr->sprite_identifier = SpriteIdentifier::Null; spr->sprite_identifier = SpriteIdentifier::Null;
spr->sprite_index = i; spr->sprite_index = i;
spr->linked_list_index = EntityListId::Free;
_spriteFlashingList[i] = false; _spriteFlashingList[i] = false;
} }
@ -371,13 +370,11 @@ rct_sprite_checksum sprite_checksum()
static void sprite_reset(SpriteBase* sprite) static void sprite_reset(SpriteBase* sprite)
{ {
// Need to retain how the sprite is linked in lists // Need to retain how the sprite is linked in lists
auto llto = sprite->linked_list_index;
uint16_t sprite_index = sprite->sprite_index; uint16_t sprite_index = sprite->sprite_index;
_spriteFlashingList[sprite_index] = false; _spriteFlashingList[sprite_index] = false;
std::memset(sprite, 0, sizeof(rct_sprite)); std::memset(sprite, 0, sizeof(rct_sprite));
sprite->linked_list_index = llto;
sprite->sprite_index = sprite_index; sprite->sprite_index = sprite_index;
sprite->sprite_identifier = SpriteIdentifier::Null; sprite->sprite_identifier = SpriteIdentifier::Null;
} }
@ -396,17 +393,16 @@ void sprite_clear_all_unused()
continue; continue;
} }
sprite_reset(entity); sprite_reset(entity);
entity->linked_list_index = EntityListId::Free;
_spriteFlashingList[entity->sprite_index] = false; _spriteFlashingList[entity->sprite_index] = false;
} }
} }
static constexpr uint16_t MAX_MISC_SPRITES = 300; static constexpr uint16_t MAX_MISC_SPRITES = 300;
static void AddToEntityList(const EntityListId linkedListIndex, SpriteBase* entity) static void AddToEntityList(SpriteBase* entity)
{ {
auto& list = gEntityLists[EnumValue(linkedListIndex)]; auto listId = EntityIdentifierToListId(entity->sprite_identifier);
entity->linked_list_index = linkedListIndex; auto& list = gEntityLists[EnumValue(listId)];
// Entity list must be in sprite_index order to prevent desync issues // Entity list must be in sprite_index order to prevent desync issues
list.insert(std::lower_bound(std::begin(list), std::end(list), entity->sprite_index), entity->sprite_index); list.insert(std::lower_bound(std::begin(list), std::end(list), entity->sprite_index), entity->sprite_index);
} }
@ -419,7 +415,8 @@ static void AddToFreeList(uint16_t index)
static void RemoveFromEntityList(SpriteBase* entity) static void RemoveFromEntityList(SpriteBase* entity)
{ {
auto& list = gEntityLists[EnumValue(entity->linked_list_index)]; auto listId = EntityIdentifierToListId(entity->sprite_identifier);
auto& list = gEntityLists[EnumValue(listId)];
auto ptr = std::lower_bound(std::begin(list), std::end(list), entity->sprite_index); auto ptr = std::lower_bound(std::begin(list), std::end(list), entity->sprite_index);
if (ptr != std::end(list) && *ptr == entity->sprite_index) if (ptr != std::end(list) && *ptr == entity->sprite_index)
{ {
@ -427,7 +424,7 @@ static void RemoveFromEntityList(SpriteBase* entity)
} }
} }
rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier, EntityListId linkedListIndex) rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier)
{ {
if (_freeIdList.size() == 0) if (_freeIdList.size() == 0)
{ {
@ -435,7 +432,7 @@ rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier, EntityListId linked
return nullptr; return nullptr;
} }
if (linkedListIndex == EntityListId::Misc) if (spriteIdentifier == SpriteIdentifier::Misc)
{ {
// Misc sprites are commonly used for effects, if there are less than MAX_MISC_SPRITES // Misc sprites are commonly used for effects, if there are less than MAX_MISC_SPRITES
// free it will fail to keep slots for more relevant sprites. // free it will fail to keep slots for more relevant sprites.
@ -454,11 +451,13 @@ rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier, EntityListId linked
} }
_freeIdList.pop_back(); _freeIdList.pop_back();
AddToEntityList(linkedListIndex, sprite);
// Need to reset all sprite data, as the uninitialised values // Need to reset all sprite data, as the uninitialised values
// may contain garbage and cause a desync later on. // may contain garbage and cause a desync later on.
sprite_reset(sprite); sprite_reset(sprite);
sprite->sprite_identifier = spriteIdentifier;
AddToEntityList(sprite);
sprite->x = LOCATION_NULL; sprite->x = LOCATION_NULL;
sprite->y = LOCATION_NULL; sprite->y = LOCATION_NULL;
sprite->z = 0; sprite->z = 0;
@ -473,30 +472,6 @@ rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier, EntityListId linked
return reinterpret_cast<rct_sprite*>(sprite); return reinterpret_cast<rct_sprite*>(sprite);
} }
rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier)
{
EntityListId linkedListIndex = EntityListId::Free;
switch (spriteIdentifier)
{
case SpriteIdentifier::Vehicle:
linkedListIndex = EntityListId::Vehicle;
break;
case SpriteIdentifier::Peep:
linkedListIndex = EntityListId::Peep;
break;
case SpriteIdentifier::Misc:
linkedListIndex = EntityListId::Misc;
break;
case SpriteIdentifier::Litter:
linkedListIndex = EntityListId::Litter;
break;
default:
Guard::Assert(false, "Invalid sprite identifier: 0x%02X", spriteIdentifier);
return nullptr;
}
return create_sprite(spriteIdentifier, linkedListIndex);
}
/** /**
* *
* rct2: 0x00673200 * rct2: 0x00673200
@ -530,7 +505,6 @@ void sprite_misc_explosion_cloud_create(const CoordsXYZ& cloudPos)
sprite->sprite_width = 44; sprite->sprite_width = 44;
sprite->sprite_height_negative = 32; sprite->sprite_height_negative = 32;
sprite->sprite_height_positive = 34; sprite->sprite_height_positive = 34;
sprite->sprite_identifier = SpriteIdentifier::Misc;
sprite->MoveTo(cloudPos + CoordsXYZ{ 0, 0, 4 }); sprite->MoveTo(cloudPos + CoordsXYZ{ 0, 0, 4 });
sprite->SubType = MiscEntityType::ExplosionCloud; sprite->SubType = MiscEntityType::ExplosionCloud;
sprite->frame = 0; sprite->frame = 0;
@ -563,7 +537,6 @@ void sprite_misc_explosion_flare_create(const CoordsXYZ& flarePos)
sprite->sprite_width = 25; sprite->sprite_width = 25;
sprite->sprite_height_negative = 85; sprite->sprite_height_negative = 85;
sprite->sprite_height_positive = 8; sprite->sprite_height_positive = 8;
sprite->sprite_identifier = SpriteIdentifier::Misc;
sprite->MoveTo(flarePos + CoordsXYZ{ 0, 0, 4 }); sprite->MoveTo(flarePos + CoordsXYZ{ 0, 0, 4 });
sprite->SubType = MiscEntityType::ExplosionFlare; sprite->SubType = MiscEntityType::ExplosionFlare;
sprite->frame = 0; sprite->frame = 0;
@ -787,7 +760,6 @@ void litter_create(const CoordsXYZD& litterPos, LitterType type)
litter->sprite_width = 6; litter->sprite_width = 6;
litter->sprite_height_negative = 6; litter->sprite_height_negative = 6;
litter->sprite_height_positive = 3; litter->sprite_height_positive = 3;
litter->sprite_identifier = SpriteIdentifier::Litter;
litter->SubType = type; litter->SubType = type;
litter->MoveTo(offsetLitterPos); litter->MoveTo(offsetLitterPos);
litter->creationTick = gScenarioTicks; litter->creationTick = gScenarioTicks;
@ -860,7 +832,6 @@ void EntityTweener::PreTick()
Reset(); Reset();
PopulateEntities(EntityListId::Peep); PopulateEntities(EntityListId::Peep);
PopulateEntities(EntityListId::Vehicle); PopulateEntities(EntityListId::Vehicle);
PopulateEntities(EntityListId::TrainHead);
} }
void EntityTweener::PostTick() void EntityTweener::PostTick()

View File

@ -204,7 +204,6 @@ constexpr const uint32_t SPATIAL_INDEX_LOCATION_NULL = SPATIAL_INDEX_SIZE - 1;
extern const rct_string_id litterNames[12]; extern const rct_string_id litterNames[12];
rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier); rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier);
rct_sprite* create_sprite(SpriteIdentifier spriteIdentifier, EntityListId linkedListIndex);
void reset_sprite_list(); void reset_sprite_list();
void reset_sprite_spatial_index(); void reset_sprite_spatial_index();
void sprite_clear_all_unused(); void sprite_clear_all_unused();

View File

@ -9,8 +9,6 @@ enum class SpriteIdentifier : uint8_t;
struct SpriteBase struct SpriteBase
{ {
SpriteIdentifier sprite_identifier; SpriteIdentifier sprite_identifier;
// Valid values are EntityListId::...
EntityListId linked_list_index;
// Height from centre of sprite to bottom // Height from centre of sprite to bottom
uint8_t sprite_height_negative; uint8_t sprite_height_negative;
uint16_t sprite_index; uint16_t sprite_index;

View File

@ -131,7 +131,6 @@ static void AdvanceGameTicks(uint32_t ticks, std::unique_ptr<IContext>& context)
static void CompareSpriteDataCommon(const SpriteBase& left, const SpriteBase& right) static void CompareSpriteDataCommon(const SpriteBase& left, const SpriteBase& right)
{ {
COMPARE_FIELD(sprite_identifier); COMPARE_FIELD(sprite_identifier);
COMPARE_FIELD(linked_list_index);
COMPARE_FIELD(sprite_index); COMPARE_FIELD(sprite_index);
COMPARE_FIELD(flags); COMPARE_FIELD(flags);
COMPARE_FIELD(x); COMPARE_FIELD(x);