diff --git a/src/linkgraph/refresh.cpp b/src/linkgraph/refresh.cpp index ae2c5fa6e7..f872fc1bfd 100644 --- a/src/linkgraph/refresh.cpp +++ b/src/linkgraph/refresh.cpp @@ -38,22 +38,14 @@ for (const Order *o = v->orders.list->GetFirstOrder(); o != NULL; o = o->next) { if (o->IsType(OT_GOTO_STATION) || o->IsType(OT_IMPLICIT)) { if (o->GetUnloadType() == OUFB_CARGO_TYPE_UNLOAD) { - OrderUnloadFlags ouf = o->GetCargoUnloadType(first_cargo_id); - uint32 other_cargo_mask = cargo_mask; - ClrBit(other_cargo_mask, first_cargo_id); - CargoID cargo; - FOR_EACH_SET_BIT(cargo, other_cargo_mask) { - if (((ouf ^ o->GetCargoUnloadType(cargo)) & (OUFB_TRANSFER | OUFB_UNLOAD | OUFB_NO_UNLOAD)) != 0) ClrBit(cargo_mask, cargo); - } + CargoMaskValueFilter(cargo_mask, [&](CargoID cargo) -> uint { + return o->GetCargoUnloadType(cargo) & (OUFB_TRANSFER | OUFB_UNLOAD | OUFB_NO_UNLOAD); + }); } if (o->GetLoadType() == OLFB_CARGO_TYPE_LOAD) { - OrderLoadFlags olf = o->GetCargoLoadType(first_cargo_id); - uint32 other_cargo_mask = cargo_mask; - ClrBit(other_cargo_mask, first_cargo_id); - CargoID cargo; - FOR_EACH_SET_BIT(cargo, other_cargo_mask) { - if (((olf ^ o->GetCargoLoadType(cargo)) & (OLFB_NO_LOAD)) != 0) ClrBit(cargo_mask, cargo); - } + CargoMaskValueFilter(cargo_mask, [&](CargoID cargo) -> uint { + return o->GetCargoLoadType(cargo) & (OLFB_NO_LOAD); + }); } } } diff --git a/src/order_base.h b/src/order_base.h index 73582d926e..d739044012 100644 --- a/src/order_base.h +++ b/src/order_base.h @@ -388,6 +388,19 @@ public: void FillNextStoppingStation(const Vehicle *v, const OrderList *o, const Order *first = NULL, uint hops = 0); }; +template T CargoMaskValueFilter(uint32 &cargo_mask, F filter_func) +{ + CargoID first_cargo_id = FindFirstBit(cargo_mask); + T value = filter_func(first_cargo_id); + uint32 other_cargo_mask = cargo_mask; + ClrBit(other_cargo_mask, first_cargo_id); + CargoID cargo; + FOR_EACH_SET_BIT(cargo, other_cargo_mask) { + if (value != filter_func(cargo)) ClrBit(cargo_mask, cargo); + } + return value; +} + /** * Shared order list linking together the linked list of orders and the list * of vehicles sharing this order list. diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 55815c3e47..66b467a4ec 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -439,16 +439,9 @@ const Order *OrderList::GetNextDecisionNode(const Order *next, uint hops, uint32 /* This is a cargo-specific load/unload order. * If the first cargo is both a no-load and no-unload order, skip it. * Drop cargoes which don't match the first one. */ - CargoID first_cargo_id = FindFirstBit(cargo_mask); - can_load_or_unload = ((next->GetCargoLoadType(first_cargo_id) & OLFB_NO_LOAD) == 0 || (next->GetCargoUnloadType(first_cargo_id) & OUFB_NO_UNLOAD) == 0); - uint32 other_cargo_mask = cargo_mask; - ClrBit(other_cargo_mask, first_cargo_id); - CargoID cargo; - FOR_EACH_SET_BIT(cargo, other_cargo_mask) { - if (can_load_or_unload != ((next->GetCargoLoadType(cargo) & OLFB_NO_LOAD) == 0 || (next->GetCargoUnloadType(cargo) & OUFB_NO_UNLOAD) == 0)) { - ClrBit(cargo_mask, cargo); - } - } + can_load_or_unload = CargoMaskValueFilter(cargo_mask, [&](CargoID cargo) { + return ((next->GetCargoLoadType(cargo) & OLFB_NO_LOAD) == 0 || (next->GetCargoUnloadType(cargo) & OUFB_NO_UNLOAD) == 0); + }); } else if ((next->GetLoadType() & OLFB_NO_LOAD) == 0 || (next->GetUnloadType() & OUFB_NO_UNLOAD) == 0) { can_load_or_unload = true; } @@ -520,21 +513,12 @@ CargoMaskedStationIDStack OrderList::GetNextStoppingStation(const Vehicle *v, ui /* Don't return a next stop if the vehicle has to unload everything. */ if ((next->IsType(OT_GOTO_STATION) || next->IsType(OT_IMPLICIT)) && next->GetDestination() == v->last_station_visited) { - CargoID first_cargo_id = FindFirstBit(cargo_mask); - bool invalid = ((next->GetCargoUnloadType(first_cargo_id) & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0); - if (next->GetUnloadType() == OUFB_CARGO_TYPE_UNLOAD) { - /* This is a cargo-specific load/unload order. - * Don't return a next stop if first cargo has transfer or unload set. - * Drop cargoes which don't match the first one. */ - uint32 other_cargo_mask = cargo_mask; - ClrBit(other_cargo_mask, first_cargo_id); - CargoID cargo; - FOR_EACH_SET_BIT(cargo, other_cargo_mask) { - if (invalid != ((next->GetCargoUnloadType(cargo) & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0)) { - ClrBit(cargo_mask, cargo); - } - } - } + /* This is a cargo-specific load/unload order. + * Don't return a next stop if first cargo has transfer or unload set. + * Drop cargoes which don't match the first one. */ + bool invalid = CargoMaskValueFilter(cargo_mask, [&](CargoID cargo) { + return ((next->GetCargoUnloadType(cargo) & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0); + }); if (invalid) return CargoMaskedStationIDStack(cargo_mask, INVALID_STATION); } } while (next->IsType(OT_GOTO_DEPOT) || next->GetDestination() == v->last_station_visited);