diff options
author | fonsinchen <fonsinchen@openttd.org> | 2013-10-22 16:19:31 +0000 |
---|---|---|
committer | fonsinchen <fonsinchen@openttd.org> | 2013-10-22 16:19:31 +0000 |
commit | 2f9c48b85946d6f03a4a9fc6e9499af7b3e05f2f (patch) | |
tree | 268190cc923571bb17d5ad05fc2e6075c36b0698 | |
parent | bd230f34f415c6c89b40e504c8a56e1bca29ac2e (diff) | |
download | openttd-2f9c48b85946d6f03a4a9fc6e9499af7b3e05f2f.tar.xz |
(svn r25901) -Fix [FS#5675]: Check if any vehicles are still serving a link before deleting it.
-rw-r--r-- | src/linkgraph/linkgraph.h | 2 | ||||
-rw-r--r-- | src/station_cmd.cpp | 41 |
2 files changed, 38 insertions, 5 deletions
diff --git a/src/linkgraph/linkgraph.h b/src/linkgraph/linkgraph.h index cad557e19..811a955e5 100644 --- a/src/linkgraph/linkgraph.h +++ b/src/linkgraph/linkgraph.h @@ -446,7 +446,7 @@ public: typedef SmallMatrix<BaseEdge> EdgeMatrix; /** Minimum effective distance for timeout calculation. */ - static const uint MIN_TIMEOUT_DISTANCE = 48; + static const uint MIN_TIMEOUT_DISTANCE = 32; /** Minimum number of days between subsequent compressions of a LG. */ static const uint COMPRESSION_INTERVAL = 256; diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 477f761b4..9542ea131 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -3419,11 +3419,44 @@ void DeleteStaleLinks(Station *from) assert(to->goods[c].node == it->first); ++it; // Do that before removing the edge. Anything else may crash. assert(_date >= edge.LastUpdate()); - uint timeout = LinkGraph::MIN_TIMEOUT_DISTANCE + (DistanceManhattan(from->xy, to->xy) >> 2); + uint timeout = LinkGraph::MIN_TIMEOUT_DISTANCE + (DistanceManhattan(from->xy, to->xy) >> 3); if ((uint)(_date - edge.LastUpdate()) > timeout) { - node.RemoveEdge(to->goods[c].node); - ge.flows.DeleteFlows(to->index); - RerouteCargo(from, c, to->index, from->index); + /* Have all vehicles refresh their next hops before deciding to + * remove the node. */ + bool updated = false; + OrderList *l; + FOR_ALL_ORDER_LISTS(l) { + bool found_from = false; + bool found_to = false; + for (Order *order = l->GetFirstOrder(); order != NULL; order = order->next) { + if (!order->IsType(OT_GOTO_STATION) && !order->IsType(OT_IMPLICIT)) continue; + if (order->GetDestination() == from->index) { + found_from = true; + if (found_to) break; + } else if (order->GetDestination() == to->index) { + found_to = true; + if (found_from) break; + } + } + if (!found_to || !found_from) continue; + for (Vehicle *v = l->GetFirstSharedVehicle(); !updated && v != NULL; v = v->NextShared()) { + /* There is potential for optimization here: + * - Usually consists of the same order list are the same. It's probably better to + * first check the first of each list, then the second of each list and so on. + * - We could try to figure out if we've seen a consist with the same cargo on the + * same list already and if the consist can actually carry the cargo we're looking + * for. With conditional and refit orders this is not quite trivial, though. */ + v->RefreshNextHopsStats(); + if (edge.LastUpdate() == _date) updated = true; + } + if (updated) break; + } + if (!updated) { + /* If it's still considered dead remove it. */ + node.RemoveEdge(to->goods[c].node); + ge.flows.DeleteFlows(to->index); + RerouteCargo(from, c, to->index, from->index); + } } else if (edge.LastUnrestrictedUpdate() != INVALID_DATE && (uint)(_date - edge.LastUnrestrictedUpdate()) > timeout) { edge.Restrict(); ge.flows.RestrictFlows(to->index); |