src/pbs.cpp
changeset 10083 eee4e42aa15b
parent 9954 a9ea85501b3b
child 10210 a542a6d595fc
equal deleted inserted replaced
10082:44931aeaa000 10083:eee4e42aa15b
   204 	}
   204 	}
   205 
   205 
   206 	return PBSTileInfo(tile, trackdir, false);
   206 	return PBSTileInfo(tile, trackdir, false);
   207 }
   207 }
   208 
   208 
   209 /** Callback for VehicleFromPos to find a train on a specific track. */
   209 /**
       
   210  * Helper struct for finding the best matching vehicle on a specific track.
       
   211  */
       
   212 struct FindTrainOnTrackInfo {
       
   213 	PBSTileInfo res; ///< Information about the track.
       
   214 	Vehicle *best;   ///< The currently "best" vehicle we have found.
       
   215 
       
   216 	/** Init the best location to NULL always! */
       
   217 	FindTrainOnTrackInfo() : best(NULL) {}
       
   218 };
       
   219 
       
   220 /** Callback for Has/FindVehicleOnPos to find a train on a specific track. */
   210 static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data)
   221 static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data)
   211 {
   222 {
   212 	PBSTileInfo info = *(PBSTileInfo *)data;
   223 	FindTrainOnTrackInfo *info = (FindTrainOnTrackInfo *)data;
   213 
   224 
   214 	if (v->type == VEH_TRAIN && !(v->vehstatus & VS_CRASHED) && HasBit((TrackBits)v->u.rail.track, TrackdirToTrack(info.trackdir))) return v;
   225 	if (v->type == VEH_TRAIN && !(v->vehstatus & VS_CRASHED) && HasBit((TrackBits)v->u.rail.track, TrackdirToTrack(info->res.trackdir))) {
       
   226 		v = v->First();
       
   227 
       
   228 		/* ALWAYS return the lowest ID (anti-desync!) */
       
   229 		if (info->best == NULL || v->index < info->best->index) info->best = v;
       
   230 		return v;
       
   231 	}
   215 
   232 
   216 	return NULL;
   233 	return NULL;
   217 }
   234 }
   218 
   235 
   219 /**
   236 /**
   221  *
   238  *
   222  * @param v the vehicle
   239  * @param v the vehicle
   223  * @param train_on_res Is set to a train we might encounter
   240  * @param train_on_res Is set to a train we might encounter
   224  * @returns The last tile of the reservation or the current train tile if no reservation present.
   241  * @returns The last tile of the reservation or the current train tile if no reservation present.
   225  */
   242  */
   226 PBSTileInfo FollowTrainReservation(const Vehicle *v, Vehicle **train_on_res)
   243 PBSTileInfo FollowTrainReservation(const Vehicle *v, bool *train_on_res)
   227 {
   244 {
   228 	assert(v->type == VEH_TRAIN);
   245 	assert(v->type == VEH_TRAIN);
   229 
   246 
   230 	TileIndex tile = v->tile;
   247 	TileIndex tile = v->tile;
   231 	Trackdir  trackdir = GetVehicleTrackdir(v);
   248 	Trackdir  trackdir = GetVehicleTrackdir(v);
   232 
   249 
   233 	if (IsRailDepotTile(tile) && !GetRailDepotReservation(tile)) return PBSTileInfo(tile, trackdir, false);
   250 	if (IsRailDepotTile(tile) && !GetRailDepotReservation(tile)) return PBSTileInfo(tile, trackdir, false);
   234 
   251 
   235 	PBSTileInfo res = FollowReservation(v->owner, GetRailTypeInfo(v->u.rail.railtype)->compatible_railtypes, tile, trackdir);
   252 	FindTrainOnTrackInfo ftoti;
   236 	res.okay = IsSafeWaitingPosition(v, res.tile, res.trackdir, true, _settings_game.pf.forbid_90_deg);
   253 	ftoti.res = FollowReservation(v->owner, GetRailTypeInfo(v->u.rail.railtype)->compatible_railtypes, tile, trackdir);
   237 	if (train_on_res != NULL) *train_on_res = VehicleFromPos(res.tile, &res, FindTrainOnTrackEnum);
   254 	ftoti.res.okay = IsSafeWaitingPosition(v, ftoti.res.tile, ftoti.res.trackdir, true, _settings_game.pf.forbid_90_deg);
   238 	return res;
   255 	if (train_on_res != NULL) *train_on_res = HasVehicleOnPos(ftoti.res.tile, &ftoti, FindTrainOnTrackEnum);
       
   256 	return ftoti.res;
   239 }
   257 }
   240 
   258 
   241 /**
   259 /**
   242  * Find the train which has reserved a specific path.
   260  * Find the train which has reserved a specific path.
   243  *
   261  *
   254 
   272 
   255 	/* Follow the path from tile to both ends, one of the end tiles should
   273 	/* Follow the path from tile to both ends, one of the end tiles should
   256 	 * have a train on it. We need FollowReservation to ignore one-way signals
   274 	 * have a train on it. We need FollowReservation to ignore one-way signals
   257 	 * here, as one of the two search directions will be the "wrong" way. */
   275 	 * here, as one of the two search directions will be the "wrong" way. */
   258 	for (int i = 0; i < 2; ++i, trackdir = ReverseTrackdir(trackdir)) {
   276 	for (int i = 0; i < 2; ++i, trackdir = ReverseTrackdir(trackdir)) {
   259 		PBSTileInfo dest = FollowReservation(GetTileOwner(tile), rts, tile, trackdir, true);
   277 		FindTrainOnTrackInfo ftoti;
   260 
   278 		ftoti.res = FollowReservation(GetTileOwner(tile), rts, tile, trackdir, true);
   261 		Vehicle *v = VehicleFromPos(dest.tile, &dest, FindTrainOnTrackEnum);
   279 
   262 		if (v != NULL) return v->First();
   280 		FindVehicleOnPos(ftoti.res.tile, &ftoti, FindTrainOnTrackEnum);
       
   281 		if (ftoti.best != NULL) return ftoti.best;
   263 
   282 
   264 		/* Special case for stations: check the whole platform for a vehicle. */
   283 		/* Special case for stations: check the whole platform for a vehicle. */
   265 		if (IsRailwayStationTile(dest.tile)) {
   284 		if (IsRailwayStationTile(ftoti.res.tile)) {
   266 			TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(dest.trackdir)));
   285 			TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(ftoti.res.trackdir)));
   267 			for (TileIndex st_tile = dest.tile + diff; IsCompatibleTrainStationTile(st_tile, dest.tile); st_tile += diff) {
   286 			for (TileIndex st_tile = ftoti.res.tile + diff; IsCompatibleTrainStationTile(st_tile, ftoti.res.tile); st_tile += diff) {
   268 				v = VehicleFromPos(st_tile, &dest, FindTrainOnTrackEnum);
   287 				FindVehicleOnPos(st_tile, &ftoti, FindTrainOnTrackEnum);
   269 				if (v != NULL) return v->First();
   288 				if (ftoti.best != NULL) return ftoti.best;
   270 			}
   289 			}
   271 		}
   290 		}
   272 
   291 
   273 		/* Special case for bridges/tunnels: check the other end as well. */
   292 		/* Special case for bridges/tunnels: check the other end as well. */
   274 		if (IsTileType(dest.tile, MP_TUNNELBRIDGE)) {
   293 		if (IsTileType(ftoti.res.tile, MP_TUNNELBRIDGE)) {
   275 			v = VehicleFromPos(GetOtherTunnelBridgeEnd(dest.tile), &dest, FindTrainOnTrackEnum);
   294 			FindVehicleOnPos(GetOtherTunnelBridgeEnd(ftoti.res.tile), &ftoti, FindTrainOnTrackEnum);
   276 			if (v != NULL) return v->First();
   295 			if (ftoti.best != NULL) return ftoti.best;
   277 		}
   296 		}
   278 	}
   297 	}
   279 
   298 
   280 	return NULL;
   299 	return NULL;
   281 }
   300 }