From 6ce6fd05d818b11be00a023b81e9fea8433c30ac Mon Sep 17 00:00:00 2001 From: fonsinchen Date: Sun, 23 Jun 2013 08:28:53 +0000 Subject: [PATCH] (svn r25434) -Fix: reroute cargo staged for unloading if a link breaks --- src/cargoaction.cpp | 25 ++++++++++++++++++++++++- src/cargoaction.h | 27 +++++++++++++++++++++++---- src/cargopacket.cpp | 17 ++++++++++++++++- src/cargopacket.h | 10 +++++++++- src/station_cmd.cpp | 10 ++++++++++ 5 files changed, 82 insertions(+), 7 deletions(-) diff --git a/src/cargoaction.cpp b/src/cargoaction.cpp index 9a13e53298..929017506a 100644 --- a/src/cargoaction.cpp +++ b/src/cargoaction.cpp @@ -192,7 +192,7 @@ bool CargoShift::operator()(CargoPacket *cp) * @param cp Packet to be rerouted. * @return True if the packet was completely rerouted, false if part of it was. */ -bool CargoReroute::operator()(CargoPacket *cp) +bool StationCargoReroute::operator()(CargoPacket *cp) { CargoPacket *cp_new = this->Preprocess(cp); if (cp_new == NULL) cp_new = cp; @@ -210,6 +210,29 @@ bool CargoReroute::operator()(CargoPacket *cp) return cp_new == cp; } +/** + * Reroutes some cargo in a VehicleCargoList. + * @param cp Packet to be rerouted. + * @return True if the packet was completely rerouted, false if part of it was. + */ +bool VehicleCargoReroute::operator()(CargoPacket *cp) +{ + CargoPacket *cp_new = this->Preprocess(cp); + if (cp_new == NULL) cp_new = cp; + if (cp_new->NextStation() == this->avoid || cp_new->NextStation() == this->avoid2) { + cp->SetNextStation(this->ge->GetVia(cp_new->SourceStation(), this->avoid, this->avoid2)); + } + if (this->source != this->destination) { + this->source->RemoveFromMeta(cp_new, VehicleCargoList::MTA_TRANSFER, cp_new->Count()); + this->source->AddToMeta(cp_new, VehicleCargoList::MTA_TRANSFER); + this->destination->action_counts[VehicleCargoList::MTA_TRANSFER] += cp_new->Count(); + } + + /* Legal, as front pushing doesn't invalidate iterators in std::list. */ + this->destination->packets.push_front(cp_new); + return cp_new == cp; +} + template uint CargoRemoval::Preprocess(CargoPacket *cp); template uint CargoRemoval::Preprocess(CargoPacket *cp); template bool CargoRemoval::Postprocess(CargoPacket *cp, uint remove); diff --git a/src/cargoaction.h b/src/cargoaction.h index b6879fb767..c305fcb29f 100644 --- a/src/cargoaction.h +++ b/src/cargoaction.h @@ -112,15 +112,34 @@ public: bool operator()(CargoPacket *cp); }; -/** Action of rerouting cargo between different station cargo lists and/or next hops. */ -class CargoReroute : public CargoMovement { +/** Action of rerouting cargo between different cargo lists and/or next hops. */ +template +class CargoReroute : public CargoMovement { protected: StationID avoid; StationID avoid2; const GoodsEntry *ge; public: - CargoReroute(StationCargoList *source, StationCargoList *dest, uint max_move, StationID avoid, StationID avoid2, const GoodsEntry *ge) : - CargoMovement(source, dest, max_move), avoid(avoid), avoid2(avoid2), ge(ge) {} + CargoReroute(Tlist *source, Tlist *dest, uint max_move, StationID avoid, StationID avoid2, const GoodsEntry *ge) : + CargoMovement(source, dest, max_move), avoid(avoid), avoid2(avoid2), ge(ge) {} +}; + +/** Action of rerouting cargo in a station. */ +class StationCargoReroute : public CargoReroute { +public: + StationCargoReroute(StationCargoList *source, StationCargoList *dest, uint max_move, StationID avoid, StationID avoid2, const GoodsEntry *ge) : + CargoReroute(source, dest, max_move, avoid, avoid2, ge) {} + bool operator()(CargoPacket *cp); +}; + +/** Action of rerouting cargo staged for transfer in a vehicle. */ +class VehicleCargoReroute : public CargoReroute { +public: + VehicleCargoReroute(VehicleCargoList *source, VehicleCargoList *dest, uint max_move, StationID avoid, StationID avoid2, const GoodsEntry *ge) : + CargoReroute(source, dest, max_move, avoid, avoid2, ge) + { + assert(this->max_move <= source->ActionCount(VehicleCargoList::MTA_TRANSFER)); + } bool operator()(CargoPacket *cp); }; diff --git a/src/cargopacket.cpp b/src/cargopacket.cpp index e2e7e4e4da..22be361e3d 100644 --- a/src/cargopacket.cpp +++ b/src/cargopacket.cpp @@ -580,6 +580,21 @@ uint VehicleCargoList::Truncate(uint max_move) return max_move; } +/** + * Routes packets with station "avoid" as next hop to a different place. + * @param max_move Maximum amount of cargo to move. + * @param dest List to prepend the cargo to. + * @param avoid Station to exclude from routing and current next hop of packets to reroute. + * @param avoid2 Additional station to exclude from routing. + * @oaram ge GoodsEntry to get the routing info from. + */ +uint VehicleCargoList::Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge) +{ + max_move = min(this->action_counts[MTA_TRANSFER], max_move); + this->ShiftCargo(VehicleCargoReroute(this, dest, max_move, avoid, avoid2, ge)); + return max_move; +} + /* * * Station cargo list implementation. @@ -759,7 +774,7 @@ uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, TileIndex loa */ uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge) { - return this->ShiftCargo(CargoReroute(this, dest, max_move, avoid, avoid2, ge), avoid, false); + return this->ShiftCargo(StationCargoReroute(this, dest, max_move, avoid, avoid2, ge), avoid, false); } /* diff --git a/src/cargopacket.h b/src/cargopacket.h index dc1e66ba2e..c4ea9e144b 100644 --- a/src/cargopacket.h +++ b/src/cargopacket.h @@ -82,6 +82,12 @@ public: */ void SetLoadPlace(TileIndex load_place) { this->loaded_at_xy = load_place; } + /** + * Sets the station where the packet is supposed to go next. + * @param next_station Next station the packet should go to. + */ + void SetNextStation(StationID next_station) { this->next_station = next_station; } + /** * Adds some feeder share to the packet. * @param new_share Feeder share to be added. @@ -319,6 +325,7 @@ public: template friend class CargoRemoval; friend class CargoReturn; + friend class VehicleCargoReroute; /** * Returns source of the first cargo packet in this list. @@ -424,6 +431,7 @@ public: uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment); uint Shift(uint max_move, VehicleCargoList *dest); uint Truncate(uint max_move = UINT_MAX); + uint Reroute(uint max_move, VehicleCargoList *dest, StationID avoid, StationID avoid2, const GoodsEntry *ge); /** * Are two the two CargoPackets mergeable in the context of @@ -467,7 +475,7 @@ public: friend class CargoRemoval; friend class CargoReservation; friend class CargoReturn; - friend class CargoReroute; + friend class StationCargoReroute; static void InvalidateAllFrom(SourceType src_type, SourceID src); diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 0ac50d2eb6..2335d8151b 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -3402,7 +3402,17 @@ void DeleteStaleLinks(Station *from) (DistanceManhattan(from->xy, to->xy) >> 2)) { node.RemoveEdge(to->goods[c].node); ge.flows.DeleteFlows(to->index); + + /* Reroute cargo in station. */ ge.cargo.Reroute(UINT_MAX, &ge.cargo, to->index, from->index, &ge); + + /* Reroute cargo staged to be transfered. */ + for (std::list::iterator it(from->loading_vehicles.begin()); it != from->loading_vehicles.end(); ++it) { + for (Vehicle *v = *it; v != NULL; v = v->Next()) { + if (v->cargo_type != c) continue; + v->cargo.Reroute(UINT_MAX, &v->cargo, to->index, from->index, &ge); + } + } } } assert(_date >= lg->LastCompression());