From f3b10599300fb57dd177f79d9ce3aac3687a156d Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Wed, 22 Feb 2017 20:51:45 +0000 Subject: [PATCH] Fix order removal due to shared-infra company deletion. Order totals were not updated correctly, implicit orders not handled properly, etc. Create generic function for vehicle order filtering. Use for station deletion and infra sharing company deletion. --- projects/openttd_vs100.vcxproj | 1 + projects/openttd_vs100.vcxproj.filters | 3 ++ projects/openttd_vs140.vcxproj | 3 ++ projects/openttd_vs140.vcxproj.filters | 9 ++++ projects/openttd_vs80.vcproj | 4 ++ projects/openttd_vs90.vcproj | 4 ++ source.list | 1 + src/infrastructure.cpp | 19 +++----- src/order_cmd.cpp | 50 ++++--------------- src/order_cmd.h | 66 ++++++++++++++++++++++++++ 10 files changed, 106 insertions(+), 54 deletions(-) create mode 100644 src/order_cmd.h diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj index 9b0f22affc..95b30d6c9a 100644 --- a/projects/openttd_vs100.vcxproj +++ b/projects/openttd_vs100.vcxproj @@ -556,6 +556,7 @@ + diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters index e4d15702e0..91ddf44efb 100644 --- a/projects/openttd_vs100.vcxproj.filters +++ b/projects/openttd_vs100.vcxproj.filters @@ -897,6 +897,9 @@ Header Files + + Header Files + Header Files diff --git a/projects/openttd_vs140.vcxproj b/projects/openttd_vs140.vcxproj index b82aba741c..85455f0df1 100644 --- a/projects/openttd_vs140.vcxproj +++ b/projects/openttd_vs140.vcxproj @@ -348,6 +348,7 @@ + @@ -498,6 +499,7 @@ + @@ -571,6 +573,7 @@ + diff --git a/projects/openttd_vs140.vcxproj.filters b/projects/openttd_vs140.vcxproj.filters index 0b6dc573b4..91ddf44efb 100644 --- a/projects/openttd_vs140.vcxproj.filters +++ b/projects/openttd_vs140.vcxproj.filters @@ -222,6 +222,9 @@ Source Files + + Source Files + Source Files @@ -672,6 +675,9 @@ Header Files + + Header Files + Header Files @@ -891,6 +897,9 @@ Header Files + + Header Files + Header Files diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index a30084b662..d5907cc86c 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -1498,6 +1498,10 @@ RelativePath=".\..\src\order_base.h" > + + diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index 2d8013d163..c84169052d 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -1495,6 +1495,10 @@ RelativePath=".\..\src\order_base.h" > + + diff --git a/source.list b/source.list index 5b696b7388..34a665ec19 100644 --- a/source.list +++ b/source.list @@ -295,6 +295,7 @@ object_type.h openttd.h order_backup.h order_base.h +order_cmd.h order_func.h order_type.h pbs.h diff --git a/src/infrastructure.cpp b/src/infrastructure.cpp index 6e6a34cf19..34c21dd27d 100644 --- a/src/infrastructure.cpp +++ b/src/infrastructure.cpp @@ -23,6 +23,7 @@ #include "gui.h" #include "pathfinder/yapf/yapf_cache.h" #include "company_base.h" +#include "order_cmd.h" #include "table/strings.h" @@ -138,6 +139,7 @@ static bool OrderDestinationIsAllowed(const Order *order, const Vehicle *v, Owne { Owner dest_owner; switch (order->GetType()) { + case OT_IMPLICIT: case OT_GOTO_STATION: case OT_GOTO_WAYPOINT: dest_owner = BaseStation::Get(order->GetDestination())->owner; break; case OT_GOTO_DEPOT: dest_owner = (v->type == VEH_AIRCRAFT) ? Station::Get(order->GetDestination())->owner : GetTileOwner(Depot::Get(order->GetDestination())->xy); break; @@ -294,19 +296,10 @@ void HandleSharingCompanyDeletion(Owner owner) /* order list */ if (v->FirstShared() != v) continue; - Order *o; - int id = -1; - FOR_VEHICLE_ORDERS(v, o) { - id++; - if (OrderDestinationIsAllowed(o, v, owner)) continue; - - o->MakeDummy(); - for (const Vehicle *w = v; w != NULL; w = w->NextShared()) { - /* In GUI, simulate by removing the order and adding it back */ - InvalidateVehicleOrder(w, id | (INVALID_VEH_ORDER_ID << 8)); - InvalidateVehicleOrder(w, (id << 8) | INVALID_VEH_ORDER_ID); - } - } + RemoveVehicleOrdersIf(v, [&](const Order *o) { + if (o->GetType() == OT_GOTO_DEPOT && (o->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) return false; + return !OrderDestinationIsAllowed(o, v, owner); + }); } } diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 65a1deae3d..807b09d41b 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -29,6 +29,7 @@ #include "infrastructure_func.h" #include "order_backup.h" #include "cheat_type.h" +#include "order_cmd.h" #include "table/strings.h" @@ -1842,55 +1843,22 @@ void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination) /* Go through all vehicles */ FOR_ALL_VEHICLES(v) { - Order *order; - - order = &v->current_order; + Order *order = &v->current_order; if ((v->type == VEH_AIRCRAFT && order->IsType(OT_GOTO_DEPOT) ? OT_GOTO_STATION : order->GetType()) == type && v->current_order.GetDestination() == destination) { order->MakeDummy(); SetWindowDirty(WC_VEHICLE_VIEW, v->index); } - /* Clear the order from the order-list */ - int id = -1; - FOR_VEHICLE_ORDERS(v, order) { - id++; -restart: + /* order list */ + if (v->FirstShared() != v) continue; - OrderType ot = order->GetType(); - if (ot == OT_GOTO_DEPOT && (order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) continue; + RemoveVehicleOrdersIf(v, [&](const Order *o) { + OrderType ot = o->GetType(); + if (ot == OT_GOTO_DEPOT && (o->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0) return false; if (ot == OT_IMPLICIT || (v->type == VEH_AIRCRAFT && ot == OT_GOTO_DEPOT)) ot = OT_GOTO_STATION; - if (ot == type && order->GetDestination() == destination) { - /* We want to clear implicit orders, but we don't want to make them - * dummy orders. They should just vanish. Also check the actual order - * type as ot is currently OT_GOTO_STATION. */ - if (order->IsType(OT_IMPLICIT)) { - order = order->next; // DeleteOrder() invalidates current order - DeleteOrder(v, id); - if (order != NULL) goto restart; - break; - } - - /* Clear wait time */ - v->orders.list->UpdateTotalDuration(-order->GetWaitTime()); - if (order->IsWaitTimetabled()) { - v->orders.list->UpdateTimetableDuration(-order->GetTimetabledWait()); - order->SetWaitTimetabled(false); - } - order->SetWaitTime(0); - - /* Clear order, preserving travel time */ - bool travel_timetabled = order->IsTravelTimetabled(); - order->MakeDummy(); - order->SetTravelTimetabled(travel_timetabled); - - for (const Vehicle *w = v->FirstShared(); w != NULL; w = w->NextShared()) { - /* In GUI, simulate by removing the order and adding it back */ - InvalidateVehicleOrder(w, id | (INVALID_VEH_ORDER_ID << 8)); - InvalidateVehicleOrder(w, (INVALID_VEH_ORDER_ID << 8) | id); - } - } - } + return (ot == type && o->GetDestination() == destination); + }); } OrderBackup::RemoveOrder(type, destination); diff --git a/src/order_cmd.h b/src/order_cmd.h new file mode 100644 index 0000000000..bbb6c1dc59 --- /dev/null +++ b/src/order_cmd.h @@ -0,0 +1,66 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file order_cmd.h Functions related to order commands. */ + +#ifndef ORDER_CMD_H +#define ORDER_CMD_H + +#include "order_base.h" +#include "order_func.h" +#include "vehicle_base.h" + +/** + * Removes all orders from a vehicle for which order_predicate returns true. + * Handles timetable updating, removing implicit orders correctly, etc. + * @param v The vehicle. + * @param order_predicate Functor with signature: bool (const Order *) + */ +template void RemoveVehicleOrdersIf(Vehicle * const v, F order_predicate) { + /* Clear the order from the order-list */ + Order *order; + int id = -1; + FOR_VEHICLE_ORDERS(v, order) { + id++; +restart: + + if (order_predicate(const_cast(order))) { + /* We want to clear implicit orders, but we don't want to make them + * dummy orders. They should just vanish. Also check the actual order + * type as ot is currently OT_GOTO_STATION. */ + if (order->IsType(OT_IMPLICIT)) { + order = order->next; // DeleteOrder() invalidates current order + DeleteOrder(v, id); + if (order != NULL) goto restart; + break; + } + + /* Clear wait time */ + v->orders.list->UpdateTotalDuration(-order->GetWaitTime()); + if (order->IsWaitTimetabled()) { + v->orders.list->UpdateTimetableDuration(-order->GetTimetabledWait()); + order->SetWaitTimetabled(false); + } + order->SetWaitTime(0); + + /* Clear order, preserving travel time */ + bool travel_timetabled = order->IsTravelTimetabled(); + order->MakeDummy(); + order->SetTravelTimetabled(travel_timetabled); + + for (const Vehicle *w = v->FirstShared(); w != NULL; w = w->NextShared()) { + /* In GUI, simulate by removing the order and adding it back */ + InvalidateVehicleOrder(w, id | (INVALID_VEH_ORDER_ID << 8)); + InvalidateVehicleOrder(w, (INVALID_VEH_ORDER_ID << 8) | id); + } + } + } +} + +#endif /* ORDER_CMD_H */