(svn r26327) -Fix [FS#5901]: Take care of next_station when reassigning from MTA_DELIVER to MTA_TRANSFER.

This commit is contained in:
fonsinchen 2014-02-09 21:10:25 +00:00
parent a4941e759c
commit 88787412b6
3 changed files with 55 additions and 15 deletions

View File

@ -544,17 +544,54 @@ void VehicleCargoList::InvalidateCache()
/** /**
* Moves some cargo from one designation to another. You can only move * Moves some cargo from one designation to another. You can only move
* between adjacent designations. E.g. you can keep cargo that was * between adjacent designations. E.g. you can keep cargo that was previously
* previously reserved (MTA_LOAD) or you can mark cargo to be transferred * reserved (MTA_LOAD), but you can't reserve cargo that's marked as to be
* that was previously marked as to be delivered, but you can't reserve * delivered. Furthermore, as this method doesn't change the actual packets,
* cargo that's marked as to be delivered. * you cannot move cargo from or to MTA_TRANSFER. You need a specialized
* template method for that.
* @tparam from Previous designation of cargo.
* @tparam to New designation of cargo.
* @param max_move Maximum amount of cargo to reassign.
* @return Amount of cargo actually reassigned.
*/ */
uint VehicleCargoList::Reassign(uint max_move, MoveToAction from, MoveToAction to) template<VehicleCargoList::MoveToAction Tfrom, VehicleCargoList::MoveToAction Tto>
uint VehicleCargoList::Reassign(uint max_move, TileOrStationID)
{ {
max_move = min(this->action_counts[from], max_move); assert_compile(Tfrom != MTA_TRANSFER && Tto != MTA_TRANSFER);
assert(Delta((int)from, (int)to) == 1); assert_compile(Tfrom - Tto == 1 || Tto - Tfrom == 1);
this->action_counts[from] -= max_move; max_move = min(this->action_counts[Tfrom], max_move);
this->action_counts[to] += max_move; this->action_counts[Tfrom] -= max_move;
this->action_counts[Tto] += max_move;
return max_move;
}
/**
* Reassign cargo from MTA_DELIVER to MTA_TRANSFER and take care of the next
* station the cargo wants to visit.
* @param max_move Maximum amount of cargo to reassign.
* @param next_station Station to record as next hop in the reassigned packets.
* @return Amount of cargo actually reassigned.
*/
template<>
uint VehicleCargoList::Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_TRANSFER>(uint max_move, TileOrStationID next_station)
{
max_move = min(this->action_counts[MTA_DELIVER], max_move);
uint sum = 0;
for (Iterator it(this->packets.begin()); sum < this->action_counts[MTA_TRANSFER] + max_move;) {
CargoPacket *cp = *it++;
sum += cp->Count();
if (sum <= this->action_counts[MTA_TRANSFER]) continue;
if (sum > this->action_counts[MTA_TRANSFER] + max_move) {
CargoPacket *cp_split = cp->Split(sum - this->action_counts[MTA_TRANSFER] + max_move);
sum -= cp_split->Count();
this->packets.insert(it, cp_split);
}
cp->next_station = next_station;
}
this->action_counts[MTA_DELIVER] -= max_move;
this->action_counts[MTA_TRANSFER] += max_move;
return max_move; return max_move;
} }
@ -806,7 +843,7 @@ uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, TileIndex loa
uint move = min(dest->ActionCount(VehicleCargoList::MTA_LOAD), max_move); uint move = min(dest->ActionCount(VehicleCargoList::MTA_LOAD), max_move);
if (move > 0) { if (move > 0) {
this->reserved_count -= move; this->reserved_count -= move;
dest->Reassign(move, VehicleCargoList::MTA_LOAD, VehicleCargoList::MTA_KEEP); dest->Reassign<VehicleCargoList::MTA_LOAD, VehicleCargoList::MTA_KEEP>(move);
return move; return move;
} else { } else {
return this->ShiftCargo(CargoLoad(this, dest, max_move, load_place), next_station, true); return this->ShiftCargo(CargoLoad(this, dest, max_move, load_place), next_station, true);
@ -831,3 +868,5 @@ uint StationCargoList::Reroute(uint max_move, StationCargoList *dest, StationID
*/ */
template class CargoList<VehicleCargoList, CargoPacketList>; template class CargoList<VehicleCargoList, CargoPacketList>;
template class CargoList<StationCargoList, StationCargoPacketMap>; template class CargoList<StationCargoList, StationCargoPacketMap>;
template uint VehicleCargoList::Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_KEEP>(uint max_move, TileOrStationID);
template uint VehicleCargoList::Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_TRANSFER>(uint max_move, TileOrStationID next_station);

View File

@ -429,7 +429,8 @@ public:
* amount of cargo to be moved. Second parameter is destination (if * amount of cargo to be moved. Second parameter is destination (if
* applicable), return value is amount of cargo actually moved. */ * applicable), return value is amount of cargo actually moved. */
uint Reassign(uint max_move, MoveToAction from, MoveToAction to); template<MoveToAction Tfrom, MoveToAction Tto>
uint Reassign(uint max_move, TileOrStationID update = INVALID_TILE);
uint Return(uint max_move, StationCargoList *dest, StationID next_station); uint Return(uint max_move, StationCargoList *dest, StationID next_station);
uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment); uint Unload(uint max_move, StationCargoList *dest, CargoPayment *payment);
uint Shift(uint max_move, VehicleCargoList *dest); uint Shift(uint max_move, VehicleCargoList *dest);

View File

@ -1509,8 +1509,8 @@ static void LoadUnloadVehicle(Vehicle *front)
/* The station does not accept our goods anymore. */ /* The station does not accept our goods anymore. */
if (front->current_order.GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) { if (front->current_order.GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) {
/* Transfer instead of delivering. */ /* Transfer instead of delivering. */
v->cargo.Reassign(v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER), v->cargo.Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_TRANSFER>(
VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_TRANSFER); v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER), INVALID_STATION);
} else { } else {
uint new_remaining = v->cargo.RemainingCount() + v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER); uint new_remaining = v->cargo.RemainingCount() + v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER);
if (v->cargo_cap < new_remaining) { if (v->cargo_cap < new_remaining) {
@ -1519,8 +1519,8 @@ static void LoadUnloadVehicle(Vehicle *front)
} }
/* Keep instead of delivering. This may lead to no cargo being unloaded, so ...*/ /* Keep instead of delivering. This may lead to no cargo being unloaded, so ...*/
v->cargo.Reassign(v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER), v->cargo.Reassign<VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_KEEP>(
VehicleCargoList::MTA_DELIVER, VehicleCargoList::MTA_KEEP); v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER));
/* ... say we unloaded something, otherwise we'll think we didn't unload /* ... say we unloaded something, otherwise we'll think we didn't unload
* something and we didn't load something, so we must be finished * something and we didn't load something, so we must be finished