diff --git a/src/cachecheck.cpp b/src/cachecheck.cpp index 8f39f8d5ed..fb0872802b 100644 --- a/src/cachecheck.cpp +++ b/src/cachecheck.cpp @@ -74,9 +74,8 @@ void CheckCaches() for (const RoadStop *rs : RoadStop::Iterate()) { if (IsBayRoadStopTile(rs->xy)) continue; - assert(rs->GetEntry(DIAGDIR_NE) != rs->GetEntry(DIAGDIR_NW)); - rs->GetEntry(DIAGDIR_NE)->CheckIntegrity(rs); - rs->GetEntry(DIAGDIR_NW)->CheckIntegrity(rs); + rs->GetEntry(DIAGDIR_NE).CheckIntegrity(rs); + rs->GetEntry(DIAGDIR_NW).CheckIntegrity(rs); } std::vector grf_cache; diff --git a/src/pathfinder/yapf/yapf_road.cpp b/src/pathfinder/yapf/yapf_road.cpp index cacf74751d..cb240b79ed 100644 --- a/src/pathfinder/yapf/yapf_road.cpp +++ b/src/pathfinder/yapf/yapf_road.cpp @@ -80,8 +80,8 @@ protected: if (!RoadStop::IsDriveThroughRoadStopContinuation(tile, tile - TileOffsByDiagDir(dir))) { /* When we're the first road stop in a 'queue' of them we increase * cost based on the fill percentage of the whole queue. */ - const RoadStop::Entry *entry = rs->GetEntry(dir); - cost += entry->GetOccupied() * Yapf().PfGetSettings().road_stop_occupied_penalty / entry->GetLength(); + const RoadStop::Entry &entry = rs->GetEntry(dir); + cost += entry.GetOccupied() * Yapf().PfGetSettings().road_stop_occupied_penalty / entry.GetLength(); } } else { /* Increase cost for filled road stops */ diff --git a/src/roadstop.cpp b/src/roadstop.cpp index f6879e5187..4f3ece2e41 100644 --- a/src/roadstop.cpp +++ b/src/roadstop.cpp @@ -28,8 +28,7 @@ RoadStop::~RoadStop() { /* When we are the head we need to free the entries */ if (this->status.Test(RoadStopStatusFlag::BaseEntry)) { - delete this->east; - delete this->west; + delete this->entries; } if (CleaningPool()) return; @@ -62,7 +61,7 @@ RoadStop *RoadStop::GetNextRoadStop(const RoadVehicle *v) const */ void RoadStop::MakeDriveThrough() { - assert(this->east == nullptr && this->west == nullptr); + assert(this->entries == nullptr); RoadStopType rst = GetRoadStopType(this->xy); Axis axis = GetDriveThroughStopAxis(this->xy); @@ -79,48 +78,43 @@ void RoadStop::MakeDriveThrough() RoadStop *rs_south = south ? RoadStop::GetByTile(south_tile, rst) : nullptr; /* Amount of road stops that will be added to the 'northern' head */ - int added = 1; - if (north && rs_north->east != nullptr) { // (east != nullptr) == (west != nullptr) + uint16_t added = 1; + if (north && rs_north->entries != nullptr) { /* There is a more northern one, so this can join them */ - this->east = rs_north->east; - this->west = rs_north->west; + this->entries = rs_north->entries; - if (south && rs_south->east != nullptr) { // (east != nullptr) == (west != nullptr) + if (south && rs_south->entries != nullptr) { /* There more southern tiles too, they must 'join' us too */ rs_south->status.Reset(RoadStopStatusFlag::BaseEntry); - this->east->occupied += rs_south->east->occupied; - this->west->occupied += rs_south->west->occupied; + this->entries->east.occupied += rs_south->entries->east.occupied; + this->entries->west.occupied += rs_south->entries->west.occupied; - /* Free the now unneeded entry structs */ - delete rs_south->east; - delete rs_south->west; + /* Free the now unneeded entries struct */ + delete rs_south->entries; /* Make all 'children' of the southern tile take the new master */ for (; IsDriveThroughRoadStopContinuation(this->xy, south_tile); south_tile += offset) { rs_south = RoadStop::GetByTile(south_tile, rst); - if (rs_south->east == nullptr) break; - rs_south->east = rs_north->east; - rs_south->west = rs_north->west; + if (rs_south->entries == nullptr) break; + rs_south->entries = rs_north->entries; added++; } } - } else if (south && rs_south->east != nullptr) { // (east != nullptr) == (west != nullptr) + } else if (south && rs_south->entries != nullptr) { /* There is one to the south, but not to the north... so we become 'parent' */ - this->east = rs_south->east; - this->west = rs_south->west; + this->entries = rs_south->entries; this->status.Set(RoadStopStatusFlag::BaseEntry); rs_south->status.Reset(RoadStopStatusFlag::BaseEntry); } else { /* We are the only... so we are automatically the master */ - this->east = new Entry(); - this->west = new Entry(); + this->entries = new Entries(); this->status.Set(RoadStopStatusFlag::BaseEntry); } /* Now update the lengths */ added *= TILE_SIZE; - this->east->length += added; - this->west->length += added; + this->entries->east.length += added; + this->entries->west.length += added; } /** @@ -129,7 +123,7 @@ void RoadStop::MakeDriveThrough() */ void RoadStop::ClearDriveThrough() { - assert(this->east != nullptr && this->west != nullptr); + assert(this->entries != nullptr); RoadStopType rst = GetRoadStopType(this->xy); Axis axis = GetDriveThroughStopAxis(this->xy); @@ -155,8 +149,7 @@ void RoadStop::ClearDriveThrough() /* There are more southern tiles too, they must be split; * first make the new southern 'base' */ rs_south->status.Set(RoadStopStatusFlag::BaseEntry); - rs_south->east = new Entry(); - rs_south->west = new Entry(); + rs_south->entries = new Entries(); /* Keep track of the base because we need it later on */ RoadStop *rs_south_base = rs_south; @@ -165,8 +158,7 @@ void RoadStop::ClearDriveThrough() /* Make all (even more) southern stops part of the new entry queue */ for (south_tile += offset; IsDriveThroughRoadStopContinuation(base_tile, south_tile); south_tile += offset) { rs_south = RoadStop::GetByTile(south_tile, rst); - rs_south->east = rs_south_base->east; - rs_south->west = rs_south_base->west; + rs_south->entries = rs_south_base->entries; } /* Find the other end; the northern most tile */ @@ -180,32 +172,30 @@ void RoadStop::ClearDriveThrough() * rebuild it from scratch as that removes lots of maintenance code * for the vehicle list and it's faster in real games as long as you * do not keep split and merge road stop every tick by the millions. */ - rs_south_base->east->Rebuild(rs_south_base); - rs_south_base->west->Rebuild(rs_south_base); + rs_south_base->entries->east.Rebuild(rs_south_base); + rs_south_base->entries->west.Rebuild(rs_south_base); assert(rs_north->status.Test(RoadStopStatusFlag::BaseEntry)); - rs_north->east->Rebuild(rs_north); - rs_north->west->Rebuild(rs_north); + rs_north->entries->east.Rebuild(rs_north); + rs_north->entries->west.Rebuild(rs_north); } else { /* Only we left, so simple update the length. */ - rs_north->east->length -= TILE_SIZE; - rs_north->west->length -= TILE_SIZE; + rs_north->entries->east.length -= TILE_SIZE; + rs_north->entries->west.length -= TILE_SIZE; } } else if (south) { /* There is only something to the south. Hand over the base entry */ rs_south->status.Set(RoadStopStatusFlag::BaseEntry); - rs_south->east->length -= TILE_SIZE; - rs_south->west->length -= TILE_SIZE; + rs_south->entries->east.length -= TILE_SIZE; + rs_south->entries->west.length -= TILE_SIZE; } else { /* We were the last */ - delete this->east; - delete this->west; + delete this->entries; } /* Make sure we don't get used for something 'incorrect' */ this->status.Reset(RoadStopStatusFlag::BaseEntry); - this->east = nullptr; - this->west = nullptr; + this->entries = nullptr; } /** @@ -220,7 +210,7 @@ void RoadStop::Leave(RoadVehicle *rv) this->SetEntranceBusy(false); } else { /* Otherwise just leave the drive through's entry cache. */ - this->GetEntry(DirToDiagDir(rv->direction))->Leave(rv); + this->GetEntry(DirToDiagDir(rv->direction)).Leave(rv); } } @@ -248,7 +238,7 @@ bool RoadStop::Enter(RoadVehicle *rv) } /* Vehicles entering a drive-through stop from the 'normal' side use first bay (bay 0). */ - this->GetEntry(DirToDiagDir(rv->direction))->Enter(rv); + this->GetEntry(DirToDiagDir(rv->direction)).Enter(rv); /* Indicate a drive-through stop */ SetBit(rv->state, RVS_IN_DT_ROAD_STOP); @@ -335,7 +325,7 @@ void RoadStop::Entry::Rebuild(const RoadStop *rs, int side) assert(rs->status.Test(RoadStopStatusFlag::BaseEntry)); Axis axis = GetDriveThroughStopAxis(rs->xy); - if (side == -1) side = (rs->east == this); + if (side == -1) side = (&rs->entries->east == this); auto entry_dir = GetEntryDirection(side, axis); std::vector vehicles; @@ -376,6 +366,6 @@ void RoadStop::Entry::CheckIntegrity(const RoadStop *rs) const assert(!IsDriveThroughRoadStopContinuation(rs->xy, rs->xy - TileOffsByAxis(GetDriveThroughStopAxis(rs->xy)))); Entry temp; - temp.Rebuild(rs, rs->east == this); + temp.Rebuild(rs, &rs->entries->east == this); if (temp.length != this->length || temp.occupied != this->occupied) NOT_REACHED(); } diff --git a/src/roadstop_base.h b/src/roadstop_base.h index 1ae6d75729..dc48ae527e 100644 --- a/src/roadstop_base.h +++ b/src/roadstop_base.h @@ -31,15 +31,12 @@ struct RoadStop : RoadStopPool::PoolItem<&_roadstop_pool> { /** Container for each entry point of a drive through road stop */ struct Entry { private: - int length = 0; ///< The length of the stop in tile 'units' - int occupied = 0; ///< The amount of occupied stop in tile 'units' + uint16_t length = 0; ///< The length of the stop in tile 'units' + uint16_t occupied = 0; ///< The amount of occupied stop in tile 'units' public: friend struct RoadStop; ///< Oh yeah, the road stop may play with me. - /** Create an entry */ - Entry() {} - /** * Get the length of this drive through stop. * @return the length in tile units. @@ -64,6 +61,12 @@ struct RoadStop : RoadStopPool::PoolItem<&_roadstop_pool> { void Rebuild(const RoadStop *rs, int side = -1); }; + /** Container for both east and west entry points. */ + struct Entries { + Entry east{}; ///< Information for vehicles that entered from the east + Entry west{}; ///< Information for vehicles that entered from the west + }; + RoadStopStatusFlags status{RoadStopStatusFlag::Bay0Free, RoadStopStatusFlag::Bay1Free}; ///< Current status of the Stop. Access using *Bay and *Busy functions. TileIndex xy = INVALID_TILE; ///< Position on the map RoadStop *next = nullptr; ///< Next stop of the given type at this station @@ -119,9 +122,9 @@ struct RoadStop : RoadStopPool::PoolItem<&_roadstop_pool> { * @param dir The direction to get the entry for. * @return the entry */ - inline const Entry *GetEntry(DiagDirection dir) const + inline const Entry &GetEntry(DiagDirection dir) const { - return HasBit((int)dir, 1) ? this->west : this->east; + return dir >= DIAGDIR_SW ? this->entries->west : this->entries->east; } /** @@ -129,9 +132,9 @@ struct RoadStop : RoadStopPool::PoolItem<&_roadstop_pool> { * @param dir The direction to get the entry for. * @return the entry */ - inline Entry *GetEntry(DiagDirection dir) + inline Entry &GetEntry(DiagDirection dir) { - return HasBit((int)dir, 1) ? this->west : this->east; + return dir >= DIAGDIR_SW ? this->entries->west : this->entries->east; } void MakeDriveThrough(); @@ -147,8 +150,7 @@ struct RoadStop : RoadStopPool::PoolItem<&_roadstop_pool> { static bool IsDriveThroughRoadStopContinuation(TileIndex rs, TileIndex next); private: - Entry *east = nullptr; ///< The vehicles that entered from the east - Entry *west = nullptr; ///< The vehicles that entered from the west + Entries *entries = nullptr; ///< Information about available and allocated bays. /** * Allocates a bay diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index 87091cb6fc..6973ea02e7 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -151,8 +151,8 @@ void AfterLoadRoadStops() for (RoadStop *rs : RoadStop::Iterate()) { if (!rs->status.Test(RoadStop::RoadStopStatusFlag::BaseEntry)) continue; - rs->GetEntry(DIAGDIR_NE)->Rebuild(rs); - rs->GetEntry(DIAGDIR_NW)->Rebuild(rs); + rs->GetEntry(DIAGDIR_NE).Rebuild(rs); + rs->GetEntry(DIAGDIR_NW).Rebuild(rs); } }