mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Replace FindVehicleOnPos with 'for' loop.
parent
06c399b79e
commit
2bee313642
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
35
src/pbs.cpp
35
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<TrackBits>(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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<TrainList*>(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);
|
||||
|
|
|
@ -2370,17 +2370,6 @@ static CommandCost TerraformTile_Road(TileIndex tile, DoCommandFlags flags, int
|
|||
return Command<CMD_LANDSCAPE_CLEAR>::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<RoadVehicleList*>(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);
|
||||
|
|
|
@ -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<const RoadVehicle *> 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<const RoadVehicle *> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
118
src/vehicle.cpp
118
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<Vehicle *>(ignore), &GetVehicleTunnelBridgeProc, true);
|
||||
if (v == nullptr) v = VehicleFromPos(endtile, const_cast<Vehicle *>(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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<BuildDepotVehicleListData *>(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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue