Add whether the vehicle is non-front to the vehicle pool pointer tag

Add iteration filters which check this
pull/661/head
Jonathan G Rennison 2 months ago
parent 05e237f8d1
commit 93bf033107

@ -117,12 +117,17 @@ struct Pool : PoolBase {
Pool(const char *name);
void CleanPool() override;
inline PtrType GetRaw(size_t index)
inline PtrType &GetRawRef(size_t index)
{
dbg_assert_msg(index < this->first_unused, "index: " PRINTF_SIZE ", first_unused: " PRINTF_SIZE ", name: %s", index, this->first_unused, this->name);
return this->data[index];
}
inline PtrType GetRaw(size_t index)
{
return this->GetRawRef(index);
}
/**
* Returns Titem with given index
* @param index of item to get

@ -164,7 +164,7 @@ protected:
CompanyMask companies = 0;
int unitnumber_max[4] = { -1, -1, -1, -1 };
for (const Vehicle *v : Vehicle::Iterate()) {
for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->type < 4 && this->show_types[v->type] && v->IsPrimaryVehicle()) {
for(const Order *order : v->Orders()) {
if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT) || order->IsType(OT_IMPLICIT))

@ -368,7 +368,7 @@ static bool DisasterTick_Ufo(DisasterVehicle *v)
}
n = RandomRange(n); // Choose one of them.
for (const RoadVehicle *u : RoadVehicle::Iterate()) {
for (const RoadVehicle *u : RoadVehicle::IterateFrontOnly()) {
/* Find (n+1)-th road vehicle. */
if (u->IsFrontEngine() && (n-- == 0)) {
if (u->crashed_ctr != 0 || !SetDisasterVehicleTargetingVehicle(u->index, v->index)) {

@ -236,7 +236,7 @@ int UpdateCompanyRatingAndValue(Company *c, bool update)
bool min_profit_first = true;
uint num = 0;
for (const Vehicle *v : Vehicle::Iterate()) {
for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->owner != owner) continue;
if (IsCompanyBuildableVehicleType(v->type) && v->IsPrimaryVehicle() && !HasBit(v->subtype, GVSF_VIRTUAL)) {
if (v->profit_last_year > 0) num++; // For the vehicle score only count profitable vehicles

@ -731,7 +731,7 @@ void SettingsDisableElrail(int32_t new_value)
}
/* Fix the total power and acceleration for trains */
for (Train *t : Train::Iterate()) {
for (Train *t : Train::IterateFrontOnly()) {
/* power and acceleration is cached only for front engines */
if (t->IsFrontEngine()) {
t->ConsistChanged(CCF_TRACK);

@ -220,7 +220,7 @@ uint16_t GroupStatistics::GetNumEngines(EngineID engine) const
g->statistics.ClearProfits();
}
for (const Vehicle *v : Vehicle::Iterate()) {
for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->IsPrimaryVehicle() && !HasBit(v->subtype, GVSF_VIRTUAL)) {
GroupStatistics::AddProfitLastYear(v);
if (v->age > VEHICLE_PROFIT_MIN_AGE) GroupStatistics::VehicleReachedMinAge(v);
@ -333,7 +333,7 @@ void IterateDescendantsOfGroup(GroupID id_top, F func)
static void PropagateChildLiveryResetVehicleCache(const Group *g)
{
/* Company colour data is indirectly cached. */
for (Vehicle *v : Vehicle::Iterate()) {
for (Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->IsPrimaryVehicle() && (v->group_id == g->index || IsGroupIDDescendantOfGroupID(v->group_id, g->index, g->owner))) {
for (Vehicle *u = v; u != nullptr; u = u->Next()) {
u->colourmap = PAL_NONE;
@ -823,7 +823,7 @@ CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32
if (flags & DC_EXEC) {
/* Find the first front engine which belong to the group id_g
* then add all shared vehicles of this front engine to the group id_g */
for (const Vehicle *v : Vehicle::IterateType(type)) {
for (const Vehicle *v : Vehicle::IterateTypeFrontOnly(type)) {
if (v->IsPrimaryVehicle()) {
if (v->group_id != id_g) continue;
@ -860,7 +860,7 @@ CommandCost CmdRemoveAllVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint3
if (flags & DC_EXEC) {
/* Find each Vehicle that belongs to the group old_g and add it to the default group */
for (const Vehicle *v : Vehicle::Iterate()) {
for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->IsPrimaryVehicle()) {
if (v->group_id != old_g) continue;

@ -206,7 +206,7 @@ static void FixAllReservations()
{
/* if this function is called, we can safely assume that sharing of rails is being switched off */
assert(!_settings_game.economy.infrastructure_sharing[VEH_TRAIN]);
for (Train *v : Train::Iterate()) {
for (Train *v : Train::IterateFrontOnly()) {
if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL)) continue;
/* It might happen that the train reserved additional tracks,
* but FollowTrainReservation can't detect those because they are no longer reachable.
@ -254,9 +254,8 @@ bool CheckSharingChangePossible(VehicleType type, bool new_value)
});
StringID error_message = STR_NULL;
for (Vehicle *v : Vehicle::IterateType(type)) {
for (Vehicle *v : Vehicle::IterateTypeFrontOnly(type)) {
if (HasBit(v->subtype, GVSF_VIRTUAL)) continue;
if (v->Previous() != nullptr) continue;
/* Check vehicle positiion */
if (!VehiclePositionIsAllowed(v)) {
@ -280,7 +279,7 @@ bool CheckSharingChangePossible(VehicleType type, bool new_value)
}
if (type == VEH_TRAIN && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) {
for (Train *v : Train::Iterate()) {
for (Train *v : Train::IterateFrontOnly()) {
if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL)) continue;
/* It might happen that the train reserved additional tracks,
* but FollowTrainReservation can't detect those because they are no longer reachable.
@ -329,9 +328,9 @@ void HandleSharingCompanyDeletion(Owner owner)
Vehicle *si_v = nullptr;
SCOPE_INFO_FMT([&si_v], "HandleSharingCompanyDeletion: veh: %s", scope_dumper().VehicleInfo(si_v));
for (Vehicle *v : Vehicle::Iterate()) {
for (Vehicle *v : Vehicle::IterateFrontOnly()) {
si_v = v;
if (!IsCompanyBuildableVehicleType(v) || v->Previous() != nullptr) continue;
if (!IsCompanyBuildableVehicleType(v)) continue;
/* vehicle position */
if (v->owner == owner || !VehiclePositionIsAllowed(v, owner)) {
RemoveAndSellVehicle(v, v->owner != owner);

@ -1759,7 +1759,7 @@ void NetworkPopulateCompanyStats(NetworkCompanyStats *stats)
memset(stats, 0, sizeof(*stats) * MAX_COMPANIES);
/* Go through all vehicles and count the type of vehicles */
for (const Vehicle *v : Vehicle::Iterate()) {
for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (!Company::IsValidID(v->owner) || !v->IsPrimaryVehicle() || HasBit(v->subtype, GVSF_VIRTUAL)) continue;
byte type = 0;
switch (v->type) {

@ -66,9 +66,9 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s
void IntialiseOrderDestinationRefcountMap()
{
ClearOrderDestinationRefcountMap();
for (const Vehicle *v : Vehicle::Iterate()) {
for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v != v->FirstShared()) continue;
for(const Order *order : v->Orders()) {
for (const Order *order : v->Orders()) {
if (order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT) || order->IsType(OT_IMPLICIT)) {
_order_destination_refcount_map[OrderDestinationRefcountMapKey(order->GetDestination(), v->owner, order->GetType(), v->type)]++;
}
@ -2933,7 +2933,7 @@ void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool
*/
/* Go through all vehicles */
for (Vehicle *v : Vehicle::Iterate()) {
for (Vehicle *v : Vehicle::IterateFrontOnly()) {
Order *order = &v->current_order;
if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) && !hangar ? OT_GOTO_STATION : order->GetType()) == type &&
(!hangar || v->type == VEH_AIRCRAFT) && order->GetDestination() == destination) {
@ -3786,7 +3786,7 @@ CommandCost CmdMassChangeOrder(TileIndex tile, DoCommandFlag flags, uint32_t p1,
DestinationID to_dest = GB(p2, 0, 16);
if (flags & DC_EXEC) {
for (Vehicle *v : Vehicle::IterateType(vehtype)) {
for (Vehicle *v : Vehicle::IterateTypeFrontOnly(vehtype)) {
if (v->IsPrimaryVehicle() && CheckOwnership(v->owner).Succeeded() && VehicleCargoFilter(v, cargo_filter)) {
int index = 0;
bool changed = false;

@ -203,7 +203,7 @@ bool RoadVehiclesAreBuilt()
*/
bool RoadVehiclesExistOutsideDepots()
{
for (const RoadVehicle *rv : RoadVehicle::Iterate()) {
for (const RoadVehicle *rv : RoadVehicle::IterateFrontOnly()) {
if (rv->IsFrontEngine() && !rv->IsChainInDepot()) return true;
}
return false;

@ -308,10 +308,8 @@ static void InitializeWindowsAndCaches()
it->tile = t->xy;
}
}
for (RoadVehicle *rv : RoadVehicle::Iterate()) {
if (rv->IsFrontEngine()) {
rv->CargoChanged();
}
for (RoadVehicle *rv : RoadVehicle::IterateFrontOnly()) {
rv->CargoChanged();
}
RecomputePrices();
@ -1735,7 +1733,7 @@ bool AfterLoadGame()
}
}
for (Train *v : Train::Iterate()) {
for (Train *v : Train::IterateFrontOnly()) {
if (v->IsFrontEngine() || v->IsFreeWagon()) v->ConsistChanged(CCF_TRACK);
}
@ -2370,8 +2368,8 @@ bool AfterLoadGame()
GroupStatistics::UpdateAfterLoad(); // Ensure statistics pool is initialised before trying to delete vehicles
/* Remove all trams from savegames without tram support.
* There would be trams without tram track under causing crashes sooner or later. */
for (RoadVehicle *v : RoadVehicle::Iterate()) {
if (v->First() == v && HasBit(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM)) {
for (RoadVehicle *v : RoadVehicle::IterateFrontOnly()) {
if (HasBit(EngInfo(v->engine_type)->misc_flags, EF_ROAD_TRAM)) {
ShowErrorMessage(STR_WARNING_LOADGAME_REMOVED_TRAMS, INVALID_STRING_ID, WL_CRITICAL);
delete v;
}
@ -2466,8 +2464,8 @@ bool AfterLoadGame()
/* Reserve all tracks trains are currently on. */
if (IsSavegameVersionBefore(SLV_101)) {
for (const Train *t : Train::Iterate()) {
if (t->First() == t) t->ReserveTrackUnderConsist();
for (const Train *t : Train::IterateFrontOnly()) {
t->ReserveTrackUnderConsist();
}
}
@ -3196,7 +3194,7 @@ bool AfterLoadGame()
}
/* Fill Vehicle::cur_real_order_index */
for (Vehicle *v : Vehicle::Iterate()) {
for (Vehicle *v : Vehicle::IterateFrontOnly()) {
if (!v->IsPrimaryVehicle()) continue;
/* Older versions are less strict with indices being in range and fix them on the fly */
@ -3501,7 +3499,7 @@ bool AfterLoadGame()
* So, make articulated parts catch up. */
bool roadside = _settings_game.vehicle.road_side == 1;
std::vector<uint> skip_frames;
for (RoadVehicle *v : RoadVehicle::Iterate()) {
for (RoadVehicle *v : RoadVehicle::IterateFrontOnly()) {
if (!v->IsFrontEngine()) continue;
skip_frames.clear();
TileIndex prev_tile = v->tile;
@ -3706,7 +3704,7 @@ bool AfterLoadGame()
}
if (!IsSavegameVersionBefore(SLV_DEPOT_UNBUNCHING)) {
for (Vehicle *v : Vehicle::Iterate()) {
for (Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->unbunch_state != nullptr) {
if (v->unbunch_state->depot_unbunching_last_departure > 0) {
v->unbunch_state->depot_unbunching_last_departure += _state_ticks.base() - _tick_counter;
@ -4217,7 +4215,7 @@ bool AfterLoadGame()
}
if (!SlXvIsFeaturePresent(XSLFI_REALISTIC_TRAIN_BRAKING, 5) && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) {
for (Train *t : Train::Iterate()) {
for (Train *t : Train::IterateFrontOnly()) {
if (t->lookahead != nullptr) {
t->lookahead->SetNextExtendPosition();
}
@ -4225,7 +4223,7 @@ bool AfterLoadGame()
}
if (!SlXvIsFeaturePresent(XSLFI_REALISTIC_TRAIN_BRAKING, 6) && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) {
for (Train *t : Train::Iterate()) {
for (Train *t : Train::IterateFrontOnly()) {
if (t->lookahead != nullptr) {
t->lookahead->cached_zpos = t->CalculateOverallZPos();
t->lookahead->zpos_refresh_remaining = t->GetZPosCacheUpdateInterval();
@ -4366,7 +4364,7 @@ bool AfterLoadGame()
}
if (!SlXvIsFeaturePresent(XSLFI_REALISTIC_TRAIN_BRAKING, 9) && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) {
for (Train *t : Train::Iterate()) {
for (Train *t : Train::IterateFrontOnly()) {
if (t->lookahead != nullptr) {
t->lookahead->lookahead_end_position = t->lookahead->reservation_end_position + 1;
}

@ -180,7 +180,7 @@
Money profit = 0;
for (const Vehicle *v : Vehicle::Iterate()) {
for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->group_id != group_id) continue;
if (!v->IsPrimaryVehicle()) continue;
@ -204,7 +204,7 @@
uint32_t occupancy = 0;
uint32_t vehicle_count = 0;
for (const Vehicle *v : Vehicle::Iterate()) {
for (const Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->group_id != group_id) continue;
if (!v->IsPrimaryVehicle()) continue;

@ -1141,7 +1141,7 @@ static void StationSpreadChanged(int32_t new_value)
static void UpdateConsists(int32_t new_value)
{
for (Train *t : Train::Iterate()) {
for (Train *t : Train::IterateFrontOnly()) {
/* Update the consist of all trains so the maximum speed is set correctly. */
if (t->IsFrontEngine() || t->IsFreeWagon()) {
t->ConsistChanged(CCF_TRACK);
@ -1196,7 +1196,7 @@ static void UpdateAllServiceInterval(int32_t new_value)
if (update_vehicles) {
const Company *c = Company::Get(_current_company);
for (Vehicle *v : Vehicle::Iterate()) {
for (Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->owner == _current_company && v->IsPrimaryVehicle() && !v->ServiceIntervalIsCustom()) {
v->SetServiceInterval(CompanyServiceInterval(c, v->type));
v->SetServiceIntervalIsPercent(new_value != 0);
@ -1224,7 +1224,7 @@ static bool CanUpdateServiceInterval(VehicleType type, int32_t &new_value)
static void UpdateServiceInterval(VehicleType type, int32_t new_value)
{
if (_game_mode != GM_MENU && Company::IsValidID(_current_company)) {
for (Vehicle *v : Vehicle::IterateType(type)) {
for (Vehicle *v : Vehicle::IterateTypeFrontOnly(type)) {
if (v->owner == _current_company && v->IsPrimaryVehicle() && !v->ServiceIntervalIsCustom()) {
v->SetServiceInterval(new_value);
}
@ -1330,7 +1330,7 @@ static void ChangeMinutesPerYear(int32_t new_value)
static void TrainAccelerationModelChanged(int32_t new_value)
{
for (Train *t : Train::Iterate()) {
for (Train *t : Train::IterateFrontOnly()) {
if (t->IsFrontEngine()) {
t->tcache.cached_max_curve_speed = t->GetCurveSpeedLimit();
t->UpdateAcceleration();
@ -1406,13 +1406,13 @@ static void TrainBrakingModelChanged(int32_t new_value)
SCOPE_INFO_FMT([&v_cur], "TrainBrakingModelChanged: %s", scope_dumper().VehicleInfo(v_cur));
extern bool _long_reserve_disabled;
_long_reserve_disabled = true;
for (Train *v : Train::Iterate()) {
for (Train *v : Train::IterateFrontOnly()) {
v_cur = v;
if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL) || v->track == TRACK_BIT_DEPOT) continue;
TryPathReserve(v, true, HasStationTileRail(v->tile));
}
_long_reserve_disabled = false;
for (Train *v : Train::Iterate()) {
for (Train *v : Train::IterateFrontOnly()) {
v_cur = v;
if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL) || v->track == TRACK_BIT_DEPOT) continue;
TryPathReserve(v, true, HasStationTileRail(v->tile));
@ -1421,7 +1421,7 @@ static void TrainBrakingModelChanged(int32_t new_value)
} else if (new_value == TBM_ORIGINAL && (_game_mode == GM_NORMAL || _game_mode == GM_EDITOR)) {
Train *v_cur = nullptr;
SCOPE_INFO_FMT([&v_cur], "TrainBrakingModelChanged: %s", scope_dumper().VehicleInfo(v_cur));
for (Train *v : Train::Iterate()) {
for (Train *v : Train::IterateFrontOnly()) {
v_cur = v;
if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL) || v->track == TRACK_BIT_DEPOT) {
v->lookahead.reset();
@ -1451,7 +1451,7 @@ static void TrainBrakingModelChanged(int32_t new_value)
*/
static void TrainSlopeSteepnessChanged(int32_t new_value)
{
for (Train *t : Train::Iterate()) {
for (Train *t : Train::IterateFrontOnly()) {
if (t->IsFrontEngine()) {
t->CargoChanged();
if (t->lookahead != nullptr) SetBit(t->lookahead->flags, TRLF_APPLY_ADVISORY);
@ -1466,17 +1466,13 @@ static void TrainSlopeSteepnessChanged(int32_t new_value)
static void RoadVehAccelerationModelChanged(int32_t new_value)
{
if (_settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL) {
for (RoadVehicle *rv : RoadVehicle::Iterate()) {
if (rv->IsFrontEngine()) {
rv->CargoChanged();
}
for (RoadVehicle *rv : RoadVehicle::IterateFrontOnly()) {
rv->CargoChanged();
}
}
if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL || !_settings_game.vehicle.improved_breakdowns) {
for (RoadVehicle *rv : RoadVehicle::Iterate()) {
if (rv->IsFrontEngine()) {
rv->breakdown_chance_factor = 128;
}
for (RoadVehicle *rv : RoadVehicle::IterateFrontOnly()) {
rv->breakdown_chance_factor = 128;
}
}
@ -1493,8 +1489,8 @@ static void RoadVehAccelerationModelChanged(int32_t new_value)
*/
static void RoadVehSlopeSteepnessChanged(int32_t new_value)
{
for (RoadVehicle *rv : RoadVehicle::Iterate()) {
if (rv->IsFrontEngine()) rv->CargoChanged();
for (RoadVehicle *rv : RoadVehicle::IterateFrontOnly()) {
rv->CargoChanged();
}
}
@ -2022,8 +2018,8 @@ static void ImprovedBreakdownsSettingChanged(int32_t new_value)
{
if (!_settings_game.vehicle.improved_breakdowns) return;
for (Vehicle *v : Vehicle::Iterate()) {
switch(v->type) {
for (Vehicle *v : Vehicle::IterateFrontOnly()) {
switch (v->type) {
case VEH_TRAIN:
if (v->IsFrontEngine()) {
v->breakdown_chance_factor = 128;

@ -273,6 +273,9 @@ void AfterLoadVehicles(bool part_of_load)
/* Reinstate the previous pointer */
if (v->Next() != nullptr) {
v->Next()->previous = v;
#if OTTD_UPPER_TAGGED_PTR
VehiclePoolOps::SetIsNonFrontVehiclePtr(_vehicle_pool.GetRawRef(v->Next()->index), true);
#endif
if (v->type == VEH_TRAIN && (HasBit(v->subtype, GVSF_VIRTUAL) != HasBit(v->Next()->subtype, GVSF_VIRTUAL))) {
SlErrorCorrupt("Mixed virtual/non-virtual train consist");
}
@ -387,7 +390,7 @@ void AfterLoadVehicles(bool part_of_load)
if (IsSavegameVersionBefore(SLV_180)) {
/* Set service interval flags */
for (Vehicle *v : Vehicle::Iterate()) {
for (Vehicle *v : Vehicle::IterateFrontOnly()) {
si_v = v;
if (!v->IsPrimaryVehicle()) continue;
@ -429,7 +432,7 @@ void AfterLoadVehicles(bool part_of_load)
CheckValidVehicles();
for (Vehicle *v : Vehicle::Iterate()) {
for (Vehicle *v : Vehicle::IterateFrontOnly()) {
si_v = v;
assert(v->first != nullptr);
@ -595,7 +598,7 @@ void FixupTrainLengths()
{
/* Vehicle center was moved from 4 units behind the front to half the length
* behind the front. Move vehicles so they end up on the same spot. */
for (Train *v : Train::Iterate()) {
for (Train *v : Train::IterateFrontOnly()) {
if (v->IsPrimaryVehicle()) {
/* The vehicle center is now more to the front depending on vehicle length,
* so we need to move all vehicles forward to cover the difference to the
@ -1622,7 +1625,7 @@ const SaveLoadTable GetVehicleUnbunchStateDescription()
void Save_VUBS()
{
for (Vehicle *v : Vehicle::Iterate()) {
for (Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->unbunch_state != nullptr) {
SlSetArrayIndex(v->index);
SlObject(v->unbunch_state.get(), GetVehicleUnbunchStateDescription());

@ -2456,9 +2456,8 @@ CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags, int replacement_
delete cur_stop;
/* Make sure no vehicle is going to the old roadstop */
for (RoadVehicle *v : RoadVehicle::Iterate()) {
if (v->First() == v && v->current_order.IsType(OT_GOTO_STATION) &&
v->dest_tile == tile) {
for (RoadVehicle *v : RoadVehicle::IterateFrontOnly()) {
if (v->current_order.IsType(OT_GOTO_STATION) && v->dest_tile == tile) {
v->SetDestTile(v->GetOrderStationLocation(st->index));
}
}
@ -3236,9 +3235,7 @@ static CommandCost RemoveDock(TileIndex tile, DoCommandFlag flags)
ClearDockingTilesCheckingNeighbours(tile1);
ClearDockingTilesCheckingNeighbours(tile2);
for (Ship *s : Ship::Iterate()) {
if (!s->IsPrimaryVehicle()) continue;
for (Ship *s : Ship::IterateFrontOnly()) {
/* Find all ships going to our dock. */
if (s->current_order.GetDestination() != st->index) {
continue;

@ -204,7 +204,7 @@ static void MarkTrainsInGroupAsPendingTemplateReplacement(GroupID gid, const Tem
std::sort(groups.begin(), groups.end());
for (Train *t : Train::Iterate()) {
for (Train *t : Train::IterateFrontOnly()) {
if (!t->IsFrontEngine() || t->owner != owner || t->group_id >= NEW_GROUP) continue;
if (std::binary_search(groups.begin(), groups.end(), t->group_id)) {
@ -217,7 +217,7 @@ void MarkTrainsUsingTemplateAsPendingTemplateReplacement(const TemplateVehicle *
{
Owner owner = tv->owner;
for (Train *t : Train::Iterate()) {
for (Train *t : Train::IterateFrontOnly()) {
if (!t->IsFrontEngine() || t->owner != owner || t->group_id >= NEW_GROUP) continue;
if (GetTemplateIDByGroupIDRecursive(t->group_id) == tv->index) {

@ -327,7 +327,7 @@ uint CountsTrainsNeedingTemplateReplacement(GroupID g_id, const TemplateVehicle
uint count = 0;
if (!tv) return count;
for (Train *t : Train::Iterate()) {
for (Train *t : Train::IterateFrontOnly()) {
if (t->IsPrimaryVehicle() && t->group_id == g_id && TrainTemplateDifference(t, tv) != TBTRDF_NONE) {
count++;
}

@ -170,8 +170,8 @@ void CheckTrainsLengths()
{
bool first = true;
for (const Train *v : Train::Iterate()) {
if (v->First() == v && !(v->vehstatus & VS_CRASHED) && !v->IsVirtual()) {
for (const Train *v : Train::IterateFrontOnly()) {
if (!(v->vehstatus & VS_CRASHED) && !v->IsVirtual()) {
for (const Train *u = v, *w = v->Next(); w != nullptr; u = w, w = w->Next()) {
if (u->track != TRACK_BIT_DEPOT) {
if ((w->track != TRACK_BIT_DEPOT &&
@ -1503,7 +1503,7 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const
CheckConsistencyOfArticulatedVehicle(v);
/* Try to connect the vehicle to one of free chains of wagons. */
for (Train *w : Train::Iterate()) {
for (Train *w : Train::IterateFrontOnly()) {
if (w->tile == tile && ///< Same depot
w->IsFreeWagon() && ///< A free wagon chain
w->engine_type == e->index && ///< Same type
@ -1527,7 +1527,7 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const
void NormalizeTrainVehInDepot(const Train *u)
{
assert(u->IsEngine());
for (const Train *v : Train::Iterate()) {
for (const Train *v : Train::IterateFrontOnly()) {
if (v->IsFreeWagon() && v->tile == u->tile &&
v->track == TRACK_BIT_DEPOT &&
v->owner == u->owner &&
@ -1674,7 +1674,7 @@ static Train *FindGoodVehiclePos(const Train *src)
EngineID eng = src->engine_type;
TileIndex tile = src->tile;
for (Train *dst : Train::Iterate()) {
for (Train *dst : Train::IterateFrontOnly()) {
if (dst->IsFreeWagon() && dst->tile == tile && !(dst->vehstatus & VS_CRASHED) && dst->owner == src->owner && !dst->IsVirtual()) {
/* check so all vehicles in the line have the same engine. */
Train *t = dst;

@ -36,7 +36,7 @@ void CcBuildWagon(const CommandCost &result, TileIndex tile, uint32_t p1, uint32
/* find a locomotive in the depot. */
const Vehicle *found = nullptr;
for (const Train *t : Train::Iterate()) {
for (const Train *t : Train::IterateFrontOnly()) {
if (t->IsFrontEngine() && t->tile == tile && t->IsStoppedInDepot() && !t->IsVirtual()) {
if (found != nullptr) return; // must be exactly one.
found = t;

@ -2861,7 +2861,7 @@ static bool ClickTile_TunnelBridge(TileIndex tile)
if (IsTunnelTile(tile)) {
int count = 0;
TileIndex tile_end = GetOtherTunnelBridgeEnd(tile);
for (const Train *t : Train::Iterate()) {
for (const Train *t : Train::IterateFrontOnly()) {
if (!t->IsFrontEngine()) continue;
if (tile == t->tile || tile_end == t->tile) {
ShowVehicleViewWindow(t);

@ -4317,6 +4317,9 @@ void Vehicle::SetNext(Vehicle *next)
v->first = this->next;
}
this->next->previous = nullptr;
#if OTTD_UPPER_TAGGED_PTR
VehiclePoolOps::SetIsNonFrontVehiclePtr(_vehicle_pool.GetRawRef(this->next->index), false);
#endif
}
this->next = next;
@ -4325,6 +4328,9 @@ void Vehicle::SetNext(Vehicle *next)
/* A new next vehicle. Update the first and previous pointers */
if (this->next->previous != nullptr) this->next->previous->next = nullptr;
this->next->previous = this;
#if OTTD_UPPER_TAGGED_PTR
VehiclePoolOps::SetIsNonFrontVehiclePtr(_vehicle_pool.GetRawRef(this->next->index), true);
#endif
for (Vehicle *v = this->next; v != nullptr; v = v->Next()) {
v->first = this->first;
}
@ -4549,7 +4555,7 @@ char *Vehicle::DumpVehicleFlagsMultiline(char *b, const char *last, const char *
void VehiclesYearlyLoop()
{
for (Vehicle *v : Vehicle::Iterate()) {
for (Vehicle *v : Vehicle::IterateFrontOnly()) {
if (v->IsPrimaryVehicle()) {
/* show warning if vehicle is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
Money profit = v->GetDisplayProfitThisYear();

@ -255,6 +255,9 @@ struct VehiclePoolOps {
static constexpr VehicleType DefaultItemParam() { return VEH_INVALID; }
static constexpr VehicleType GetVehicleType(uintptr_t ptr) { return static_cast<VehicleType>(GB(ptr, 60, 3)); }
static constexpr bool IsNonFrontVehiclePtr(uintptr_t ptr) { return HasBit(ptr, 63); }
static constexpr void SetIsNonFrontVehiclePtr(uintptr_t &ptr, bool non_front) { SB(ptr, 63, 1, non_front ? 1 : 0); }
};
typedef Pool<Vehicle, VehicleID, 512, 0xFF000, PT_NORMAL, false, true, VehiclePoolOps> VehiclePool;
@ -1303,6 +1306,32 @@ public:
}
};
struct VehicleFrontOnlyFilter {
bool operator() (size_t index)
{
#if OTTD_UPPER_TAGGED_PTR
return !VehiclePoolOps::IsNonFrontVehiclePtr(_vehicle_pool.GetRaw(index));
#else
return Vehicle::Get(index)->Previous() == nullptr;
#endif
}
};
struct VehicleFrontOnlyTypeFilter {
VehicleType vt;
bool operator() (size_t index)
{
#if OTTD_UPPER_TAGGED_PTR
uintptr_t vptr = _vehicle_pool.GetRaw(index);
return !VehiclePoolOps::IsNonFrontVehiclePtr(vptr) && VehiclePoolOps::GetVehicleType(vptr) == this->vt;
#else
const Vehicle *v = Vehicle::Get(index);
return v->type == this->vt && v->Previous() == nullptr;
#endif
}
};
/**
* Returns an iterable ensemble of all valid vehicles of the given type
* @param vt the VehicleType to filter
@ -1313,6 +1342,27 @@ public:
{
return Pool::IterateWrapperFiltered<Vehicle, VehicleTypeFilter>(from, VehicleTypeFilter{ vt });
}
/**
* Returns an iterable ensemble of all valid front vehicles (i.e. Previous() == nullptr)
* @param from index of the first vehicle to consider
* @return an iterable ensemble of all valid front vehicles
*/
static Pool::IterateWrapperFiltered<Vehicle, VehicleFrontOnlyFilter> IterateFrontOnly(size_t from = 0)
{
return Pool::IterateWrapperFiltered<Vehicle, VehicleFrontOnlyFilter>(from, VehicleFrontOnlyFilter{});
}
/**
* Returns an iterable ensemble of all valid front vehicles of the given type
* @param vt the VehicleType to filter
* @param from index of the first vehicle to consider
* @return an iterable ensemble of all valid front vehicles of the given type
*/
static Pool::IterateWrapperFiltered<Vehicle, VehicleFrontOnlyTypeFilter> IterateTypeFrontOnly(VehicleType vt, size_t from = 0)
{
return Pool::IterateWrapperFiltered<Vehicle, VehicleFrontOnlyTypeFilter>(from, VehicleFrontOnlyTypeFilter{ vt });
}
};
inline bool IsPointInViewportVehicleRedrawArea(const std::vector<Rect> &viewport_redraw_rects, const Point &pt)
@ -1608,6 +1658,16 @@ public:
* @return an iterable ensemble of all valid vehicles of type T
*/
static Pool::IterateWrapper<T> Iterate(size_t from = 0) { return Pool::IterateWrapper<T>(from); }
/**
* Returns an iterable ensemble of all valid front vehicles (i.e. Previous() == nullptr) of type T
* @param from index of the first vehicle to consider
* @return an iterable ensemble of all valid front vehicles of type T
*/
static Pool::IterateWrapperFiltered<T, VehicleFrontOnlyFilter> IterateFrontOnly(size_t from = 0)
{
return Pool::IterateWrapperFiltered<T, VehicleFrontOnlyFilter>(from, VehicleFrontOnlyFilter{});
}
};
/** Generates sequence of free UnitID numbers */

@ -155,7 +155,7 @@ bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli
};
auto fill_all_vehicles = [&]() {
for (const Vehicle *v : Vehicle::IterateType(vli.vtype)) {
for (const Vehicle *v : Vehicle::IterateTypeFrontOnly(vli.vtype)) {
if (!HasBit(v->subtype, GVSF_VIRTUAL) && v->owner == vli.company && v->IsPrimaryVehicle()) {
add_veh(v);
}
@ -184,7 +184,7 @@ bool GenerateVehicleSortList(VehicleList *list, const VehicleListIdentifier &vli
case VL_GROUP_LIST:
if (vli.index != ALL_GROUP) {
for (const Vehicle *v : Vehicle::IterateType(vli.vtype)) {
for (const Vehicle *v : Vehicle::IterateTypeFrontOnly(vli.vtype)) {
if (!HasBit(v->subtype, GVSF_VIRTUAL) && v->IsPrimaryVehicle() &&
v->owner == vli.company && GroupIsInGroup(v->group_id, vli.index)) {
add_veh(v);

Loading…
Cancel
Save