* Check all next hops of cargo packets in this station for existence of a * a valid link they may use to travel on. Reroute any cargo not having a valid * link and remove timed out links found like this from the linkgraph. We're * not all links here as that is expensive and useless. A link no one is using * doesn't hurt either. * @param from Station to check. */
| 4166 | * @param from Station to check. |
| 4167 | */ |
| 4168 | void DeleteStaleLinks(Station *from) |
| 4169 | { |
| 4170 | for (CargoType cargo = 0; cargo < NUM_CARGO; ++cargo) { |
| 4171 | const bool auto_distributed = (_settings_game.linkgraph.GetDistributionType(cargo) != DT_MANUAL); |
| 4172 | GoodsEntry &ge = from->goods[cargo]; |
| 4173 | LinkGraph *lg = LinkGraph::GetIfValid(ge.link_graph); |
| 4174 | if (lg == nullptr) continue; |
| 4175 | std::vector<NodeID> to_remove{}; |
| 4176 | for (Edge &edge : (*lg)[ge.node].edges) { |
| 4177 | Station *to = Station::Get((*lg)[edge.dest_node].station); |
| 4178 | assert(to->goods[cargo].node == edge.dest_node); |
| 4179 | assert(TimerGameEconomy::date >= edge.LastUpdate()); |
| 4180 | auto timeout = TimerGameEconomy::Date(LinkGraph::MIN_TIMEOUT_DISTANCE + (DistanceManhattan(from->xy, to->xy) >> 3)); |
| 4181 | if (TimerGameEconomy::date - edge.LastUpdate() > timeout) { |
| 4182 | bool updated = false; |
| 4183 | |
| 4184 | if (auto_distributed) { |
| 4185 | /* Have all vehicles refresh their next hops before deciding to |
| 4186 | * remove the node. */ |
| 4187 | std::vector<Vehicle *> vehicles; |
| 4188 | for (const OrderList *l : OrderList::Iterate()) { |
| 4189 | bool found_from = false; |
| 4190 | bool found_to = false; |
| 4191 | for (const Order &order : l->GetOrders()) { |
| 4192 | if (!order.IsType(OT_GOTO_STATION) && !order.IsType(OT_IMPLICIT)) continue; |
| 4193 | if (order.GetDestination() == from->index) { |
| 4194 | found_from = true; |
| 4195 | if (found_to) break; |
| 4196 | } else if (order.GetDestination() == to->index) { |
| 4197 | found_to = true; |
| 4198 | if (found_from) break; |
| 4199 | } |
| 4200 | } |
| 4201 | if (!found_to || !found_from) continue; |
| 4202 | vehicles.push_back(l->GetFirstSharedVehicle()); |
| 4203 | } |
| 4204 | |
| 4205 | auto iter = vehicles.begin(); |
| 4206 | while (iter != vehicles.end()) { |
| 4207 | Vehicle *v = *iter; |
| 4208 | /* Do not refresh links of vehicles that have been stopped in depot for a long time. */ |
| 4209 | if (!v->IsStoppedInDepot() || TimerGameEconomy::date - v->date_of_last_service <= LinkGraph::STALE_LINK_DEPOT_TIMEOUT) { |
| 4210 | LinkRefresher::Run(v, false); // Don't allow merging. Otherwise lg might get deleted. |
| 4211 | } |
| 4212 | if (edge.LastUpdate() == TimerGameEconomy::date) { |
| 4213 | updated = true; |
| 4214 | break; |
| 4215 | } |
| 4216 | |
| 4217 | Vehicle *next_shared = v->NextShared(); |
| 4218 | if (next_shared) { |
| 4219 | *iter = next_shared; |
| 4220 | ++iter; |
| 4221 | } else { |
| 4222 | iter = vehicles.erase(iter); |
| 4223 | } |
| 4224 | |
| 4225 | if (iter == vehicles.end()) iter = vehicles.begin(); |
no test coverage detected