diff --git a/src/pathfinder/yapf/yapf_ship.cpp b/src/pathfinder/yapf/yapf_ship.cpp index 544c33fddf..a47df5abb3 100644 --- a/src/pathfinder/yapf/yapf_ship.cpp +++ b/src/pathfinder/yapf/yapf_ship.cpp @@ -355,15 +355,6 @@ public: return 0; } - static Vehicle *CountShipProc(Vehicle *v, void *data) - { - uint *count = (uint*)data; - /* Ignore other vehicles (aircraft) and ships inside depot. */ - if (v->type == VEH_SHIP && !v->vehstatus.Test(VehState::Hidden)) (*count)++; - - return nullptr; - } - /** * Called by YAPF to calculate the cost from the origin to the given node. * Calculates only the cost of given node, adds it to the parent node cost @@ -378,8 +369,10 @@ public: if (IsDockingTile(n.GetTile())) { /* Check docking tile for occupancy. */ - uint count = 0; - FindVehicleOnPos(n.GetTile(), &count, &CountShipProc); + uint count = std::ranges::count_if(VehiclesOnTile(n.GetTile()), [](const Vehicle *v) { + /* Ignore other vehicles (aircraft) and ships inside depot. */ + return v->type == VEH_SHIP && !v->vehstatus.Test(VehState::Hidden); + }); c += count * 3 * YAPF_TILE_LENGTH; } diff --git a/src/pbs.cpp b/src/pbs.cpp index ecf570a5d3..e567574609 100644 --- a/src/pbs.cpp +++ b/src/pbs.cpp @@ -259,23 +259,20 @@ struct FindTrainOnTrackInfo { FindTrainOnTrackInfo() : best(nullptr) {} }; -/** Callback for Has/FindVehicleOnPos to find a train on a specific track. */ -static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data) +/** Find the best matching vehicle on a tile. */ +static void CheckTrainsOnTrack(FindTrainOnTrackInfo &info, TileIndex tile) { - FindTrainOnTrackInfo *info = (FindTrainOnTrackInfo *)data; + for (Vehicle *v : VehiclesOnTile(tile)) { + if (v->type != VEH_TRAIN || v->vehstatus.Test(VehState::Crashed)) continue; - if (v->type != VEH_TRAIN || v->vehstatus.Test(VehState::Crashed)) return nullptr; + Train *t = Train::From(v); + if (t->track == TRACK_BIT_WORMHOLE || HasBit(static_cast(t->track), TrackdirToTrack(info.res.trackdir))) { + t = t->First(); - Train *t = Train::From(v); - if (t->track == TRACK_BIT_WORMHOLE || HasBit((TrackBits)t->track, TrackdirToTrack(info->res.trackdir))) { - t = t->First(); - - /* ALWAYS return the lowest ID (anti-desync!) */ - if (info->best == nullptr || t->index < info->best->index) info->best = t; - return t; + /* ALWAYS return the lowest ID (anti-desync!) */ + if (info.best == nullptr || t->index < info.best->index) info.best = t; + } } - - return nullptr; } /** @@ -298,7 +295,7 @@ PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res) ftoti.res = FollowReservation(v->owner, GetRailTypeInfo(v->railtype)->compatible_railtypes, tile, trackdir); ftoti.res.okay = IsSafeWaitingPosition(v, ftoti.res.tile, ftoti.res.trackdir, true, _settings_game.pf.forbid_90_deg); if (train_on_res != nullptr) { - FindVehicleOnPos(ftoti.res.tile, &ftoti, FindTrainOnTrackEnum); + CheckTrainsOnTrack(ftoti, ftoti.res.tile); if (ftoti.best != nullptr) *train_on_res = ftoti.best->First(); if (*train_on_res == nullptr && IsRailStationTile(ftoti.res.tile)) { /* The target tile is a rail station. The track follower @@ -307,13 +304,13 @@ PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res) * for a possible train. */ TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(ftoti.res.trackdir))); for (TileIndex st_tile = ftoti.res.tile + diff; *train_on_res == nullptr && IsCompatibleTrainStationTile(st_tile, ftoti.res.tile); st_tile += diff) { - FindVehicleOnPos(st_tile, &ftoti, FindTrainOnTrackEnum); + CheckTrainsOnTrack(ftoti, st_tile); if (ftoti.best != nullptr) *train_on_res = ftoti.best->First(); } } if (*train_on_res == nullptr && IsTileType(ftoti.res.tile, MP_TUNNELBRIDGE)) { /* The target tile is a bridge/tunnel, also check the other end tile. */ - FindVehicleOnPos(GetOtherTunnelBridgeEnd(ftoti.res.tile), &ftoti, FindTrainOnTrackEnum); + CheckTrainsOnTrack(ftoti, GetOtherTunnelBridgeEnd(ftoti.res.tile)); if (ftoti.best != nullptr) *train_on_res = ftoti.best->First(); } } @@ -345,21 +342,21 @@ Train *GetTrainForReservation(TileIndex tile, Track track) FindTrainOnTrackInfo ftoti; ftoti.res = FollowReservation(GetTileOwner(tile), rts, tile, trackdir, true); - FindVehicleOnPos(ftoti.res.tile, &ftoti, FindTrainOnTrackEnum); + CheckTrainsOnTrack(ftoti, ftoti.res.tile); if (ftoti.best != nullptr) return ftoti.best; /* Special case for stations: check the whole platform for a vehicle. */ if (IsRailStationTile(ftoti.res.tile)) { TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(ftoti.res.trackdir))); for (TileIndex st_tile = ftoti.res.tile + diff; IsCompatibleTrainStationTile(st_tile, ftoti.res.tile); st_tile += diff) { - FindVehicleOnPos(st_tile, &ftoti, FindTrainOnTrackEnum); + CheckTrainsOnTrack(ftoti, st_tile); if (ftoti.best != nullptr) return ftoti.best; } } /* Special case for bridges/tunnels: check the other end as well. */ if (IsTileType(ftoti.res.tile, MP_TUNNELBRIDGE)) { - FindVehicleOnPos(GetOtherTunnelBridgeEnd(ftoti.res.tile), &ftoti, FindTrainOnTrackEnum); + CheckTrainsOnTrack(ftoti, GetOtherTunnelBridgeEnd(ftoti.res.tile)); if (ftoti.best != nullptr) return ftoti.best; } } diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index e9ea6bf292..f792b22bde 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1528,17 +1528,6 @@ CommandCost CmdRemoveSignalTrack(DoCommandFlags flags, TileIndex tile, TileIndex return CmdSignalTrackHelper(flags, tile, end_tile, track, SIGTYPE_BLOCK, SIG_ELECTRIC, false, true, autofill, false, 1); // bit 5 is remove bit } -/** Update power of train under which is the railtype being converted */ -static Vehicle *UpdateTrainPowerProc(Vehicle *v, void *data) -{ - if (v->type != VEH_TRAIN) return nullptr; - - TrainList *affected_trains = static_cast(data); - include(*affected_trains, Train::From(v)->First()); - - return nullptr; -} - /** * Convert one rail type to the other. You can convert normal rail to * monorail/maglev easily or vice-versa. @@ -1640,7 +1629,9 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_ SetRailType(tile, totype); MarkTileDirtyByTile(tile); /* update power of train on this tile */ - FindVehicleOnPos(tile, &affected_trains, &UpdateTrainPowerProc); + for (Vehicle *v : VehiclesOnTile(tile)) { + if (v->type == VEH_TRAIN) include(affected_trains, Train::From(v)->First()); + } } } @@ -1717,8 +1708,12 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_ SetRailType(tile, totype); SetRailType(endtile, totype); - FindVehicleOnPos(tile, &affected_trains, &UpdateTrainPowerProc); - FindVehicleOnPos(endtile, &affected_trains, &UpdateTrainPowerProc); + for (Vehicle *v : VehiclesOnTile(tile)) { + if (v->type == VEH_TRAIN) include(affected_trains, Train::From(v)->First()); + } + for (Vehicle *v : VehiclesOnTile(endtile)) { + if (v->type == VEH_TRAIN) include(affected_trains, Train::From(v)->First()); + } YapfNotifyTrackLayoutChange(tile, track); YapfNotifyTrackLayoutChange(endtile, track); diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index f04a948d09..584730a101 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -2370,17 +2370,6 @@ static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlags flags, int return Command::Do(flags, tile); } -/** Update power of road vehicle under which is the roadtype being converted */ -static Vehicle *UpdateRoadVehPowerProc(Vehicle *v, void *data) -{ - if (v->type != VEH_ROAD) return nullptr; - - RoadVehicleList *affected_rvs = static_cast(data); - include(*affected_rvs, RoadVehicle::From(v)->First()); - - return nullptr; -} - /** * Checks the tile and returns whether the current player is allowed to convert the roadtype to another roadtype without taking ownership * @param owner the tile owner. @@ -2538,7 +2527,9 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_ MarkTileDirtyByTile(tile); /* update power of train on this tile */ - FindVehicleOnPos(tile, &affected_rvs, &UpdateRoadVehPowerProc); + for (Vehicle *v : VehiclesOnTile(tile)) { + if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First()); + } if (IsRoadDepotTile(tile)) { /* Update build vehicle window related to this depot */ @@ -2595,8 +2586,12 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_ SetRoadType(tile, rtt, to_type); SetRoadType(endtile, rtt, to_type); - FindVehicleOnPos(tile, &affected_rvs, &UpdateRoadVehPowerProc); - FindVehicleOnPos(endtile, &affected_rvs, &UpdateRoadVehPowerProc); + for (Vehicle *v : VehiclesOnTile(tile)) { + if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First()); + } + for (Vehicle *v : VehiclesOnTile(endtile)) { + if (v->type == VEH_ROAD) include(affected_rvs, RoadVehicle::From(v)->First()); + } if (IsBridge(tile)) { MarkBridgeDirty(tile); diff --git a/src/roadstop.cpp b/src/roadstop.cpp index 4dcc2c5c53..f6879e5187 100644 --- a/src/roadstop.cpp +++ b/src/roadstop.cpp @@ -10,6 +10,7 @@ #include "stdafx.h" #include "roadveh.h" #include "core/pool_func.hpp" +#include "core/container_func.hpp" #include "roadstop_base.h" #include "station_base.h" #include "vehicle_func.h" @@ -309,39 +310,6 @@ void RoadStop::Entry::Enter(const RoadVehicle *rv) GetDriveThroughStopAxis(next) == GetDriveThroughStopAxis(rs); } -typedef std::list RVList; ///< A list of road vehicles - -/** Helper for finding RVs in a road stop. */ -struct RoadStopEntryRebuilderHelper { - RVList vehicles; ///< The list of vehicles to possibly add to. - DiagDirection dir; ///< The direction the vehicle has to face to be added. -}; - -/** - * Add road vehicles to the station's list if needed. - * @param v the found vehicle - * @param data the extra data used to make our decision - * @return always nullptr - */ -Vehicle *FindVehiclesInRoadStop(Vehicle *v, void *data) -{ - RoadStopEntryRebuilderHelper *rserh = (RoadStopEntryRebuilderHelper*)data; - /* Not a RV or not in the right direction or crashed :( */ - if (v->type != VEH_ROAD || DirToDiagDir(v->direction) != rserh->dir || !v->IsPrimaryVehicle() || v->vehstatus.Test(VehState::Crashed)) return nullptr; - - RoadVehicle *rv = RoadVehicle::From(v); - /* Don't add ones not in a road stop */ - if (rv->state < RVSB_IN_ROAD_STOP) return nullptr; - - /* Do not add duplicates! */ - for (const auto &it : rserh->vehicles) { - if (rv == it) return nullptr; - } - - rserh->vehicles.push_back(rv); - return nullptr; -} - /** * Get the DiagDirection for entering the drive through stop from the given 'side' (east or west) on the given axis. * @param east Enter from the east when true or from the west when false. @@ -369,18 +337,27 @@ void RoadStop::Entry::Rebuild(const RoadStop *rs, int side) Axis axis = GetDriveThroughStopAxis(rs->xy); if (side == -1) side = (rs->east == this); - RoadStopEntryRebuilderHelper rserh; - rserh.dir = GetEntryDirection(side, axis); + auto entry_dir = GetEntryDirection(side, axis); + std::vector vehicles; this->length = 0; TileIndexDiff offset = TileOffsByAxis(axis); for (TileIndex tile = rs->xy; IsDriveThroughRoadStopContinuation(rs->xy, tile); tile += offset) { this->length += TILE_SIZE; - FindVehicleOnPos(tile, &rserh, FindVehiclesInRoadStop); + for (const Vehicle *v : VehiclesOnTile(tile)) { + /* Not a RV or not in the right direction or crashed :( */ + if (v->type != VEH_ROAD || DirToDiagDir(v->direction) != entry_dir || !v->IsPrimaryVehicle() || v->vehstatus.Test(VehState::Crashed)) continue; + + const RoadVehicle *rv = RoadVehicle::From(v); + /* Don't add ones not in a road stop */ + if (rv->state < RVSB_IN_ROAD_STOP) continue; + + include(vehicles, rv); + } } this->occupied = 0; - for (const auto &it : rserh.vehicles) { + for (const auto &it : vehicles) { this->occupied += it->gcache.cached_total_length; } } diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 750b42b567..8e9b750c8c 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -659,8 +659,12 @@ static RoadVehicle *RoadVehFindCloseTo(RoadVehicle *v, int x, int y, Direction d rvf.best_diff = UINT_MAX; if (front->state == RVSB_WORMHOLE) { - FindVehicleOnPos(v->tile, &rvf, EnumCheckRoadVehClose); - FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &rvf, EnumCheckRoadVehClose); + for (Vehicle *u : VehiclesOnTile(v->tile)) { + EnumCheckRoadVehClose(u, &rvf); + } + for (Vehicle *u : VehiclesOnTile(GetOtherTunnelBridgeEnd(v->tile))) { + EnumCheckRoadVehClose(u, &rvf); + } } else { FindVehicleOnPosXY(x, y, &rvf, EnumCheckRoadVehClose); } diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 5ac2898844..67569dc76d 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2108,24 +2108,6 @@ CommandCost CmdBuildRoadStop(DoCommandFlags flags, TileIndex tile, uint8_t width return cost; } - -static Vehicle *ClearRoadStopStatusEnum(Vehicle *v, void *) -{ - if (v->type == VEH_ROAD) { - /* Okay... we are a road vehicle on a drive through road stop. - * But that road stop has just been removed, so we need to make - * sure we are in a valid state... however, vehicles can also - * turn on road stop tiles, so only clear the 'road stop' state - * bits and only when the state was 'in road stop', otherwise - * we'll end up clearing the turn around bits. */ - RoadVehicle *rv = RoadVehicle::From(v); - if (HasBit(rv->state, RVS_IN_DT_ROAD_STOP)) rv->state &= RVSB_ROAD_STOP_TRACKDIR_MASK; - } - - return nullptr; -} - - /** * Remove a bus station/truck stop * @param tile TileIndex been queried @@ -2159,7 +2141,19 @@ static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlags flags, int repl /* don't do the check for drive-through road stops when company bankrupts */ if (IsDriveThroughStopTile(tile) && flags.Test(DoCommandFlag::Bankrupt)) { /* remove the 'going through road stop' status from all vehicles on that tile */ - if (flags.Test(DoCommandFlag::Execute)) FindVehicleOnPos(tile, nullptr, &ClearRoadStopStatusEnum); + if (flags.Test(DoCommandFlag::Execute)) { + for (Vehicle *v : VehiclesOnTile(tile)) { + if (v->type != VEH_ROAD) continue; + /* Okay... we are a road vehicle on a drive through road stop. + * But that road stop has just been removed, so we need to make + * sure we are in a valid state... however, vehicles can also + * turn on road stop tiles, so only clear the 'road stop' state + * bits and only when the state was 'in road stop', otherwise + * we'll end up clearing the turn around bits. */ + RoadVehicle *rv = RoadVehicle::From(v); + if (HasBit(rv->state, RVS_IN_DT_ROAD_STOP)) rv->state &= RVSB_ROAD_STOP_TRACKDIR_MASK; + } + } } else { CommandCost ret = EnsureNoVehicleOnGround(tile); if (ret.Failed()) return ret; diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 54b2106ed1..2332656dd7 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -3234,8 +3234,12 @@ static bool CheckTrainCollision(Train *v) /* find colliding vehicles */ if (v->track == TRACK_BIT_WORMHOLE) { - FindVehicleOnPos(v->tile, &tcc, FindTrainCollideEnum); - FindVehicleOnPos(GetOtherTunnelBridgeEnd(v->tile), &tcc, FindTrainCollideEnum); + for (Vehicle *u : VehiclesOnTile(v->tile)) { + FindTrainCollideEnum(u, &tcc); + } + for (Vehicle *u : VehiclesOnTile(GetOtherTunnelBridgeEnd(v->tile))) { + FindTrainCollideEnum(u, &tcc); + } } else { FindVehicleOnPosXY(v->x_pos, v->y_pos, &tcc, FindTrainCollideEnum); } @@ -3582,29 +3586,6 @@ reverse_train_direction: return false; } -/** - * Collect trackbits of all crashed train vehicles on a tile - * @param v Vehicle passed from Find/HasVehicleOnPos() - * @param data trackdirbits for the result - * @return nullptr to iterate over all vehicles on the tile. - */ -static Vehicle *CollectTrackbitsFromCrashedVehiclesEnum(Vehicle *v, void *data) -{ - TrackBits *trackbits = (TrackBits *)data; - - if (v->type == VEH_TRAIN && v->vehstatus.Test(VehState::Crashed)) { - TrackBits train_tbits = Train::From(v)->track; - if (train_tbits == TRACK_BIT_WORMHOLE) { - /* Vehicle is inside a wormhole, v->track contains no useful value then. */ - *trackbits |= DiagDirToDiagTrackBits(GetTunnelBridgeDirection(v->tile)); - } else if (train_tbits != TRACK_BIT_DEPOT) { - *trackbits |= train_tbits; - } - } - - return nullptr; -} - static bool IsRailStationPlatformOccupied(TileIndex tile) { TileIndexDiff delta = TileOffsByAxis(GetRailStationAxis(tile)); @@ -3631,11 +3612,11 @@ static void DeleteLastWagon(Train *v) Train *first = v->First(); /* Go to the last wagon and delete the link pointing there - * *u is then the one-before-last wagon, and *v the last + * new_last is then the one-before-last wagon, and v the last * one which will physically be removed */ - Train *u = v; - for (; v->Next() != nullptr; v = v->Next()) u = v; - u->SetNext(nullptr); + Train *new_last = v; + for (; v->Next() != nullptr; v = v->Next()) new_last = v; + new_last->SetNext(nullptr); if (first != v) { /* Recalculate cached train properties */ @@ -3667,7 +3648,16 @@ static void DeleteLastWagon(Train *v) /* If there are still crashed vehicles on the tile, give the track reservation to them */ TrackBits remaining_trackbits = TRACK_BIT_NONE; - FindVehicleOnPos(tile, &remaining_trackbits, CollectTrackbitsFromCrashedVehiclesEnum); + for (const Vehicle *u : VehiclesOnTile(tile)) { + if (u->type != VEH_TRAIN || !u->vehstatus.Test(VehState::Crashed)) continue; + TrackBits train_tbits = Train::From(u)->track; + if (train_tbits == TRACK_BIT_WORMHOLE) { + /* Vehicle is inside a wormhole, u->track contains no useful value then. */ + remaining_trackbits |= DiagDirToDiagTrackBits(GetTunnelBridgeDirection(u->tile)); + } else if (train_tbits != TRACK_BIT_DEPOT) { + remaining_trackbits |= train_tbits; + } + } /* It is important that these two are the first in the loop, as reservation cannot deal with every trackbit combination */ assert(TRACK_BEGIN == TRACK_X && TRACK_Y == TRACK_BEGIN + 1); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 9ad6eb775f..9b0cb657a3 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -500,66 +500,6 @@ void VehiclesOnTile::Iterator::SkipFalseMatches() while (this->current != nullptr && this->current->tile != this->tile) this->Increment(); } -/** - * Helper function for FindVehicleOnPos/HasVehicleOnPos. - * @note Do not call this function directly! - * @param tile The location on the map - * @param data Arbitrary data passed to \a proc. - * @param proc The proc that determines whether a vehicle will be "found". - * @param find_first Whether to return on the first found or iterate over - * all vehicles - * @return the best matching or first vehicle (depending on find_first). - */ -static Vehicle *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc, bool find_first) -{ - int x = GB(TileX(tile), HASH_RES, HASH_BITS); - int y = GB(TileY(tile), HASH_RES, HASH_BITS) << HASH_BITS; - - Vehicle *v = _vehicle_tile_hash[(x + y) & TOTAL_HASH_MASK]; - for (; v != nullptr; v = v->hash_tile_next) { - if (v->tile != tile) continue; - - Vehicle *a = proc(v, data); - if (find_first && a != nullptr) return a; - } - - return nullptr; -} - -/** - * Find a vehicle from a specific location. It will call \a proc for ALL vehicles - * on the tile and YOU must make SURE that the "best one" is stored in the - * data value and is ALWAYS the same regardless of the order of the vehicles - * where proc was called on! - * When you fail to do this properly you create an almost untraceable DESYNC! - * @note The return value of \a proc will be ignored. - * @note Use this function when you have the intention that all vehicles - * should be iterated over. - * @param tile The location on the map - * @param data Arbitrary data passed to \a proc. - * @param proc The proc that determines whether a vehicle will be "found". - */ -void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc) -{ - VehicleFromPos(tile, data, proc, false); -} - -/** - * Callback that returns 'real' vehicles lower or at height \c *(int*)data . - * @param v Vehicle to examine. - * @param data Pointer to height data. - * @return \a v if conditions are met, else \c nullptr. - */ -static Vehicle *EnsureNoVehicleProcZ(Vehicle *v, void *data) -{ - int z = *(int*)data; - - if (v->type == VEH_DISASTER || (v->type == VEH_AIRCRAFT && v->subtype == AIR_SHADOW)) return nullptr; - if (v->z_pos > z) return nullptr; - - return v; -} - /** * Ensure there is no vehicle at the ground at the given position. * @param tile Position to examine. @@ -573,20 +513,15 @@ CommandCost EnsureNoVehicleOnGround(TileIndex tile) * error message only (which may be different for different machines). * Such a message does not affect MP synchronisation. */ - Vehicle *v = VehicleFromPos(tile, &z, &EnsureNoVehicleProcZ, true); - if (v != nullptr) return CommandCost(STR_ERROR_TRAIN_IN_THE_WAY + v->type); + for (const Vehicle *v : VehiclesOnTile(tile)) { + if (v->type == VEH_DISASTER || (v->type == VEH_AIRCRAFT && v->subtype == AIR_SHADOW)) continue; + if (v->z_pos > z) continue; + + return CommandCost(STR_ERROR_TRAIN_IN_THE_WAY + v->type); + } return CommandCost(); } -/** Procedure called for every vehicle found in tunnel/bridge in the hash map */ -static Vehicle *GetVehicleTunnelBridgeProc(Vehicle *v, void *data) -{ - if (v->type != VEH_TRAIN && v->type != VEH_ROAD && v->type != VEH_SHIP) return nullptr; - if (v == (const Vehicle *)data) return nullptr; - - return v; -} - /** * Finds vehicle in tunnel / bridge * @param tile first end @@ -596,29 +531,20 @@ static Vehicle *GetVehicleTunnelBridgeProc(Vehicle *v, void *data) */ CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore) { - /* Value v is not safe in MP games, however, it is used to generate a local - * error message only (which may be different for different machines). - * Such a message does not affect MP synchronisation. - */ - Vehicle *v = VehicleFromPos(tile, const_cast(ignore), &GetVehicleTunnelBridgeProc, true); - if (v == nullptr) v = VehicleFromPos(endtile, const_cast(ignore), &GetVehicleTunnelBridgeProc, true); - - if (v != nullptr) return CommandCost(STR_ERROR_TRAIN_IN_THE_WAY + v->type); + for (TileIndex t : {tile, endtile}) { + /* Value v is not safe in MP games, however, it is used to generate a local + * error message only (which may be different for different machines). + * Such a message does not affect MP synchronisation. + */ + for (const Vehicle *v : VehiclesOnTile(t)) { + if (v->type != VEH_TRAIN && v->type != VEH_ROAD && v->type != VEH_SHIP) continue; + if (v == ignore) continue; + return CommandCost(STR_ERROR_TRAIN_IN_THE_WAY + v->type); + } + } return CommandCost(); } -static Vehicle *EnsureNoTrainOnTrackProc(Vehicle *v, void *data) -{ - TrackBits rail_bits = *(TrackBits *)data; - - if (v->type != VEH_TRAIN) return nullptr; - - Train *t = Train::From(v); - if ((t->track != rail_bits) && !TracksOverlap(t->track | rail_bits)) return nullptr; - - return v; -} - /** * Tests if a vehicle interacts with the specified track bits. * All track bits interact except parallel #TRACK_BIT_HORZ or #TRACK_BIT_VERT. @@ -633,8 +559,14 @@ CommandCost EnsureNoTrainOnTrackBits(TileIndex tile, TrackBits track_bits) * error message only (which may be different for different machines). * Such a message does not affect MP synchronisation. */ - Vehicle *v = VehicleFromPos(tile, &track_bits, &EnsureNoTrainOnTrackProc, true); - if (v != nullptr) return CommandCost(STR_ERROR_TRAIN_IN_THE_WAY + v->type); + for (const Vehicle *v : VehiclesOnTile(tile)) { + if (v->type != VEH_TRAIN) continue; + + const Train *t = Train::From(v); + if ((t->track != track_bits) && !TracksOverlap(t->track | track_bits)) continue; + + return CommandCost(STR_ERROR_TRAIN_IN_THE_WAY + v->type); + } return CommandCost(); } diff --git a/src/vehicle_func.h b/src/vehicle_func.h index f91d76851d..7a3ae6147b 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -115,7 +115,6 @@ typedef Vehicle *VehicleFromPosProc(Vehicle *v, void *data); void VehicleServiceInDepot(Vehicle *v); uint CountVehiclesInChain(const Vehicle *v); -void FindVehicleOnPos(TileIndex tile, void *data, VehicleFromPosProc *proc); void FindVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc); bool HasVehicleOnPosXY(int x, int y, void *data, VehicleFromPosProc *proc); void CallVehicleTicks(); diff --git a/src/vehiclelist.cpp b/src/vehiclelist.cpp index 1bfebabf54..bf5ac560b8 100644 --- a/src/vehiclelist.cpp +++ b/src/vehiclelist.cpp @@ -32,39 +32,6 @@ WindowNumber VehicleListIdentifier::ToWindowNumber() const return c << 28 | this->type << 23 | this->vtype << 26 | this->index; } -/** Data for building a depot vehicle list. */ -struct BuildDepotVehicleListData -{ - VehicleList *engines; ///< Pointer to list to add vehicles to. - VehicleList *wagons; ///< Pointer to list to add wagons to (can be nullptr). - VehicleType type; ///< Type of vehicle. - bool individual_wagons; ///< If true add every wagon to \a wagons which is not attached to an engine. If false only add the first wagon of every row. -}; - -/** - * Add vehicles to a depot vehicle list. - * @param v The found vehicle. - * @param data The depot vehicle list data. - * @return Always nullptr. - */ -static Vehicle *BuildDepotVehicleListProc(Vehicle *v, void *data) -{ - auto bdvld = static_cast(data); - if (v->type != bdvld->type || !v->IsInDepot()) return nullptr; - - if (bdvld->type == VEH_TRAIN) { - const Train *t = Train::From(v); - if (t->IsArticulatedPart() || t->IsRearDualheaded()) return nullptr; - if (bdvld->wagons != nullptr && t->First()->IsFreeWagon()) { - if (bdvld->individual_wagons || t->IsFreeWagon()) bdvld->wagons->push_back(t); - return nullptr; - } - } - - if (v->IsPrimaryVehicle()) bdvld->engines->push_back(v); - return nullptr; -}; - /** * Generate a list of vehicles inside a depot. * @param type Type of vehicle @@ -78,8 +45,20 @@ void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engine engines->clear(); if (wagons != nullptr && wagons != engines) wagons->clear(); - BuildDepotVehicleListData bdvld{engines, wagons, type, individual_wagons}; - FindVehicleOnPos(tile, &bdvld, BuildDepotVehicleListProc); + for (Vehicle *v : VehiclesOnTile(tile)) { + if (v->type != type || !v->IsInDepot()) continue; + + if (type == VEH_TRAIN) { + const Train *t = Train::From(v); + if (t->IsArticulatedPart() || t->IsRearDualheaded()) continue; + if (wagons != nullptr && t->First()->IsFreeWagon()) { + if (individual_wagons || t->IsFreeWagon()) wagons->push_back(t); + continue; + } + } + + if (v->IsPrimaryVehicle()) engines->push_back(v); + } } /** diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 2eb45af852..45ef9d58ee 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -1012,12 +1012,11 @@ static void FloodVehicle(Vehicle *v) /** * Flood a vehicle if we are allowed to flood it, i.e. when it is on the ground. * @param v The vehicle to test for flooding. - * @param data The z of level to flood. - * @return nullptr as we always want to remove everything. + * @param z The z of level to flood. */ -static Vehicle *FloodVehicleProc(Vehicle *v, void *data) +static void FloodVehicleProc(Vehicle *v, int z) { - if (v->vehstatus.Test(VehState::Crashed)) return nullptr; + if (v->vehstatus.Test(VehState::Crashed)) return; switch (v->type) { default: break; @@ -1038,14 +1037,18 @@ static Vehicle *FloodVehicleProc(Vehicle *v, void *data) case VEH_TRAIN: case VEH_ROAD: { - int z = *(int*)data; if (v->z_pos > z) break; FloodVehicle(v->First()); break; } } +} - return nullptr; +static void FloodVehiclesOnTile(TileIndex tile, int z) +{ + for (Vehicle *v : VehiclesOnTile(tile)) { + FloodVehicleProc(v, z); + } } /** @@ -1055,12 +1058,10 @@ static Vehicle *FloodVehicleProc(Vehicle *v, void *data) */ static void FloodVehicles(TileIndex tile) { - int z = 0; - if (IsAirportTile(tile)) { const Station *st = Station::GetByTile(tile); for (TileIndex airport_tile : st->airport) { - if (st->TileBelongsToAirport(airport_tile)) FindVehicleOnPos(airport_tile, &z, &FloodVehicleProc); + if (st->TileBelongsToAirport(airport_tile)) FloodVehiclesOnTile(airport_tile, 0); } /* No vehicle could be flooded on this airport anymore */ @@ -1068,15 +1069,15 @@ static void FloodVehicles(TileIndex tile) } if (!IsBridgeTile(tile)) { - FindVehicleOnPos(tile, &z, &FloodVehicleProc); + FloodVehiclesOnTile(tile, 0); return; } TileIndex end = GetOtherBridgeEnd(tile); - z = GetBridgePixelHeight(tile); + int z = GetBridgePixelHeight(tile); - FindVehicleOnPos(tile, &z, &FloodVehicleProc); - FindVehicleOnPos(end, &z, &FloodVehicleProc); + FloodVehiclesOnTile(tile, z); + FloodVehiclesOnTile(end, z); } /**