(svn r25361) -Feature: distribute cargo according to plan given by linkgraph
This commit is contained in:
@@ -10,7 +10,9 @@
|
||||
/** @file cargopacket.cpp Implementation of the cargo packets. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "station_base.h"
|
||||
#include "core/pool_func.hpp"
|
||||
#include "core/random_func.hpp"
|
||||
#include "economy_base.h"
|
||||
#include "cargoaction.h"
|
||||
#include "order_type.h"
|
||||
@@ -151,8 +153,8 @@ void CargoPacket::Reduce(uint count)
|
||||
/**
|
||||
* Destroy the cargolist ("frees" all cargo packets).
|
||||
*/
|
||||
template <class Tinst>
|
||||
CargoList<Tinst>::~CargoList()
|
||||
template <class Tinst, class Tcont>
|
||||
CargoList<Tinst, Tcont>::~CargoList()
|
||||
{
|
||||
for (Iterator it(this->packets.begin()); it != this->packets.end(); ++it) {
|
||||
delete *it;
|
||||
@@ -163,8 +165,8 @@ CargoList<Tinst>::~CargoList()
|
||||
* Empty the cargo list, but don't free the cargo packets;
|
||||
* the cargo packets are cleaned by CargoPacket's CleanPool.
|
||||
*/
|
||||
template <class Tinst>
|
||||
void CargoList<Tinst>::OnCleanPool()
|
||||
template <class Tinst, class Tcont>
|
||||
void CargoList<Tinst, Tcont>::OnCleanPool()
|
||||
{
|
||||
this->packets.clear();
|
||||
}
|
||||
@@ -175,8 +177,8 @@ void CargoList<Tinst>::OnCleanPool()
|
||||
* @param cp Packet to be removed from cache.
|
||||
* @param count Amount of cargo from the given packet to be removed.
|
||||
*/
|
||||
template <class Tinst>
|
||||
void CargoList<Tinst>::RemoveFromCache(const CargoPacket *cp, uint count)
|
||||
template <class Tinst, class Tcont>
|
||||
void CargoList<Tinst, Tcont>::RemoveFromCache(const CargoPacket *cp, uint count)
|
||||
{
|
||||
assert(count <= cp->count);
|
||||
this->count -= count;
|
||||
@@ -188,83 +190,16 @@ void CargoList<Tinst>::RemoveFromCache(const CargoPacket *cp, uint count)
|
||||
* Increases count and days_in_transit.
|
||||
* @param cp New packet to be inserted.
|
||||
*/
|
||||
template <class Tinst>
|
||||
void CargoList<Tinst>::AddToCache(const CargoPacket *cp)
|
||||
template <class Tinst, class Tcont>
|
||||
void CargoList<Tinst, Tcont>::AddToCache(const CargoPacket *cp)
|
||||
{
|
||||
this->count += cp->count;
|
||||
this->cargo_days_in_transit += cp->days_in_transit * cp->count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates the cargo in this list to the given amount. It leaves the
|
||||
* first cargo entities and removes max_move from the back of the list.
|
||||
* @param max_move Maximum amount of entities to be removed from the list.
|
||||
* @return Amount of entities actually moved.
|
||||
*/
|
||||
template <class Tinst>
|
||||
uint CargoList<Tinst>::Truncate(uint max_move)
|
||||
{
|
||||
max_move = min(this->count, max_move);
|
||||
this->PopCargo(CargoRemoval<Tinst>(static_cast<Tinst *>(this), max_move));
|
||||
return max_move;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts cargo from the front of the packet list and applies some action to it.
|
||||
* @tparam Taction Action class or function to be used. It should define
|
||||
* "bool operator()(CargoPacket *)". If true is returned the
|
||||
* cargo packet will be removed from the list. Otherwise it
|
||||
* will be kept and the loop will be aborted.
|
||||
* @param action Action instance to be applied.
|
||||
*/
|
||||
template <class Tinst>
|
||||
template <class Taction>
|
||||
void CargoList<Tinst>::ShiftCargo(Taction action)
|
||||
{
|
||||
Iterator it(this->packets.begin());
|
||||
while (it != this->packets.end() && action.MaxMove() > 0) {
|
||||
CargoPacket *cp = *it;
|
||||
if (action(cp)) {
|
||||
it = this->packets.erase(it);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops cargo from the back of the packet list and applies some action to it.
|
||||
* @tparam Taction Action class or function to be used. It should define
|
||||
* "bool operator()(CargoPacket *)". If true is returned the
|
||||
* cargo packet will be removed from the list. Otherwise it
|
||||
* will be kept and the loop will be aborted.
|
||||
* @param action Action instance to be applied.
|
||||
*/
|
||||
template <class Tinst>
|
||||
template <class Taction>
|
||||
void CargoList<Tinst>::PopCargo(Taction action)
|
||||
{
|
||||
if (this->packets.empty()) return;
|
||||
Iterator it(--(this->packets.end()));
|
||||
Iterator begin(this->packets.begin());
|
||||
while (action.MaxMove() > 0) {
|
||||
CargoPacket *cp = *it;
|
||||
if (action(cp)) {
|
||||
if (it != begin) {
|
||||
this->packets.erase(it--);
|
||||
} else {
|
||||
this->packets.erase(it);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Invalidates the cached data and rebuilds it. */
|
||||
template <class Tinst>
|
||||
void CargoList<Tinst>::InvalidateCache()
|
||||
template <class Tinst, class Tcont>
|
||||
void CargoList<Tinst, Tcont>::InvalidateCache()
|
||||
{
|
||||
this->count = 0;
|
||||
this->cargo_days_in_transit = 0;
|
||||
@@ -281,11 +216,11 @@ void CargoList<Tinst>::InvalidateCache()
|
||||
* @param cp Packet to be eliminated.
|
||||
* @return If the packets could be merged.
|
||||
*/
|
||||
template <class Tinst>
|
||||
/* static */ bool CargoList<Tinst>::TryMerge(CargoPacket *icp, CargoPacket *cp)
|
||||
template <class Tinst, class Tcont>
|
||||
/* static */ bool CargoList<Tinst, Tcont>::TryMerge(CargoPacket *icp, CargoPacket *cp)
|
||||
{
|
||||
if (Tinst::AreMergable(icp, cp) &&
|
||||
icp->count + cp->count <= CargoPacket::MAX_COUNT) {
|
||||
icp->count + cp->count <= CargoPacket::MAX_COUNT) {
|
||||
icp->Merge(cp);
|
||||
return true;
|
||||
} else {
|
||||
@@ -340,6 +275,57 @@ void VehicleCargoList::Append(CargoPacket *cp, MoveToAction action)
|
||||
NOT_REACHED();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts cargo from the front of the packet list and applies some action to it.
|
||||
* @tparam Taction Action class or function to be used. It should define
|
||||
* "bool operator()(CargoPacket *)". If true is returned the
|
||||
* cargo packet will be removed from the list. Otherwise it
|
||||
* will be kept and the loop will be aborted.
|
||||
* @param action Action instance to be applied.
|
||||
*/
|
||||
template<class Taction>
|
||||
void VehicleCargoList::ShiftCargo(Taction action)
|
||||
{
|
||||
Iterator it(this->packets.begin());
|
||||
while (it != this->packets.end() && action.MaxMove() > 0) {
|
||||
CargoPacket *cp = *it;
|
||||
if (action(cp)) {
|
||||
it = this->packets.erase(it);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops cargo from the back of the packet list and applies some action to it.
|
||||
* @tparam Taction Action class or function to be used. It should define
|
||||
* "bool operator()(CargoPacket *)". If true is returned the
|
||||
* cargo packet will be removed from the list. Otherwise it
|
||||
* will be kept and the loop will be aborted.
|
||||
* @param action Action instance to be applied.
|
||||
*/
|
||||
template<class Taction>
|
||||
void VehicleCargoList::PopCargo(Taction action)
|
||||
{
|
||||
if (this->packets.empty()) return;
|
||||
Iterator it(--(this->packets.end()));
|
||||
Iterator begin(this->packets.begin());
|
||||
while (action.MaxMove() > 0) {
|
||||
CargoPacket *cp = *it;
|
||||
if (action(cp)) {
|
||||
if (it != begin) {
|
||||
this->packets.erase(it--);
|
||||
} else {
|
||||
this->packets.erase(it);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the cached values to reflect the removal of this packet or part of it.
|
||||
* Decreases count, feeder share and days_in_transit.
|
||||
@@ -405,6 +391,23 @@ void VehicleCargoList::AgeCargo()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets loaded_at_xy to the current station for all cargo to be transfered.
|
||||
* This is done when stopping or skipping while the vehicle is unloading. In
|
||||
* that case the vehicle will get part of its transfer credits early and it may
|
||||
* get more transfer credits than it's entitled to.
|
||||
* @param xy New loaded_at_xy for the cargo.
|
||||
*/
|
||||
void VehicleCargoList::SetTransferLoadPlace(TileIndex xy)
|
||||
{
|
||||
uint sum = 0;
|
||||
for (Iterator it = this->packets.begin(); sum < this->action_counts[MTA_TRANSFER]; ++it) {
|
||||
CargoPacket *cp = *it;
|
||||
cp->loaded_at_xy = xy;
|
||||
sum += cp->count;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stages cargo for unloading. The cargo is sorted so that packets to be
|
||||
* transferred, delivered or kept are in consecutive chunks in the list. At the
|
||||
@@ -412,10 +415,13 @@ void VehicleCargoList::AgeCargo()
|
||||
* chunks.
|
||||
* @param accepted If the cargo will be accepted at the station.
|
||||
* @param current_station ID of the station.
|
||||
* @param next_station ID of the station the vehicle will go to next.
|
||||
* @param order_flags OrderUnloadFlags that will apply to the unload operation.
|
||||
* @param ge GoodsEntry for getting the flows.
|
||||
* @param payment Payment object for registering transfers.
|
||||
* return If any cargo will be unloaded.
|
||||
*/
|
||||
bool VehicleCargoList::Stage(bool accepted, StationID current_station, uint8 order_flags)
|
||||
bool VehicleCargoList::Stage(bool accepted, StationID current_station, StationID next_station, uint8 order_flags, const GoodsEntry *ge, CargoPayment *payment)
|
||||
{
|
||||
this->AssertCountConsistency();
|
||||
assert(this->action_counts[MTA_LOAD] == 0);
|
||||
@@ -423,20 +429,59 @@ bool VehicleCargoList::Stage(bool accepted, StationID current_station, uint8 ord
|
||||
Iterator deliver = this->packets.end();
|
||||
Iterator it = this->packets.begin();
|
||||
uint sum = 0;
|
||||
|
||||
bool force_keep = (order_flags & OUFB_NO_UNLOAD) != 0;
|
||||
bool force_unload = (order_flags & OUFB_UNLOAD) != 0;
|
||||
bool force_transfer = (order_flags & (OUFB_TRANSFER | OUFB_UNLOAD)) != 0;
|
||||
assert(this->count > 0 || it == this->packets.end());
|
||||
while (sum < this->count) {
|
||||
CargoPacket *cp = *it;
|
||||
|
||||
this->packets.erase(it++);
|
||||
if ((order_flags & OUFB_TRANSFER) != 0 || (!accepted && (order_flags & OUFB_UNLOAD) != 0)) {
|
||||
this->packets.push_front(cp);
|
||||
this->action_counts[MTA_TRANSFER] += cp->count;
|
||||
} else if (accepted && current_station != cp->source && (order_flags & OUFB_NO_UNLOAD) == 0) {
|
||||
this->packets.insert(deliver, cp);
|
||||
this->action_counts[MTA_DELIVER] += cp->count;
|
||||
StationID cargo_next = INVALID_STATION;
|
||||
MoveToAction action = MTA_LOAD;
|
||||
if (force_keep) {
|
||||
action = MTA_KEEP;
|
||||
} else if (force_unload && accepted && cp->source != current_station) {
|
||||
action = MTA_DELIVER;
|
||||
} else if (force_transfer) {
|
||||
action = MTA_TRANSFER;
|
||||
cargo_next = ge->GetVia(cp->source, current_station, next_station);
|
||||
assert((cargo_next != next_station || cargo_next == INVALID_STATION) &&
|
||||
cargo_next != current_station);
|
||||
} else {
|
||||
this->packets.push_back(cp);
|
||||
if (deliver == this->packets.end()) --deliver;
|
||||
this->action_counts[MTA_KEEP] += cp->count;
|
||||
cargo_next = ge->GetVia(cp->source);
|
||||
if (cargo_next == INVALID_STATION) {
|
||||
action = (accepted && cp->source != current_station) ? MTA_DELIVER : MTA_KEEP;
|
||||
} else if (cargo_next == current_station) {
|
||||
action = MTA_DELIVER;
|
||||
} else if (cargo_next == next_station) {
|
||||
action = MTA_KEEP;
|
||||
} else {
|
||||
action = MTA_TRANSFER;
|
||||
}
|
||||
}
|
||||
Money share;
|
||||
switch (action) {
|
||||
case MTA_KEEP:
|
||||
this->packets.push_back(cp);
|
||||
if (deliver == this->packets.end()) --deliver;
|
||||
break;
|
||||
case MTA_DELIVER:
|
||||
this->packets.insert(deliver, cp);
|
||||
break;
|
||||
case MTA_TRANSFER:
|
||||
this->packets.push_front(cp);
|
||||
/* Add feeder share here to allow reusing field for next station. */
|
||||
share = payment->PayTransfer(cp, cp->count);
|
||||
cp->AddFeederShare(share);
|
||||
this->feeder_share += share;
|
||||
cp->next_station = cargo_next;
|
||||
break;
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
this->action_counts[action] += cp->count;
|
||||
sum += cp->count;
|
||||
}
|
||||
this->AssertCountConsistency();
|
||||
@@ -468,14 +513,15 @@ uint VehicleCargoList::Reassign(uint max_move, MoveToAction from, MoveToAction t
|
||||
|
||||
/**
|
||||
* Returns reserved cargo to the station and removes it from the cache.
|
||||
* @param dest Station the cargo is returned to.
|
||||
* @param max_move Maximum amount of cargo to move.
|
||||
* @param dest Station the cargo is returned to.
|
||||
* @param ID of next the station the cargo wants to go next.
|
||||
* @return Amount of cargo actually returned.
|
||||
*/
|
||||
uint VehicleCargoList::Return(uint max_move, StationCargoList *dest)
|
||||
uint VehicleCargoList::Return(uint max_move, StationCargoList *dest, StationID next)
|
||||
{
|
||||
max_move = min(this->action_counts[MTA_LOAD], max_move);
|
||||
this->PopCargo(CargoReturn(this, dest, max_move));
|
||||
this->PopCargo(CargoReturn(this, dest, max_move, next));
|
||||
return max_move;
|
||||
}
|
||||
|
||||
@@ -505,7 +551,7 @@ uint VehicleCargoList::Unload(uint max_move, StationCargoList *dest, CargoPaymen
|
||||
uint moved = 0;
|
||||
if (this->action_counts[MTA_TRANSFER] > 0) {
|
||||
uint move = min(this->action_counts[MTA_TRANSFER], max_move);
|
||||
this->ShiftCargo(CargoTransfer(this, dest, move, payment));
|
||||
this->ShiftCargo(CargoTransfer(this, dest, move));
|
||||
moved += move;
|
||||
}
|
||||
if (this->action_counts[MTA_TRANSFER] == 0 && this->action_counts[MTA_DELIVER] > 0 && moved < max_move) {
|
||||
@@ -516,6 +562,19 @@ uint VehicleCargoList::Unload(uint max_move, StationCargoList *dest, CargoPaymen
|
||||
return moved;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates the cargo in this list to the given amount. It leaves the
|
||||
* first cargo entities and removes max_move from the back of the list.
|
||||
* @param max_move Maximum amount of entities to be removed from the list.
|
||||
* @return Amount of entities actually moved.
|
||||
*/
|
||||
uint VehicleCargoList::Truncate(uint max_move)
|
||||
{
|
||||
max_move = min(this->count, max_move);
|
||||
this->PopCargo(CargoRemoval<VehicleCargoList>(this, max_move));
|
||||
return max_move;
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Station cargo list implementation.
|
||||
@@ -523,24 +582,112 @@ uint VehicleCargoList::Unload(uint max_move, StationCargoList *dest, CargoPaymen
|
||||
*/
|
||||
|
||||
/**
|
||||
* Appends the given cargo packet. Tries to merge it with another one in the
|
||||
* packets list. If no fitting packet is found, appends it.
|
||||
* Appends the given cargo packet to the range of packets with the same next station
|
||||
* @warning After appending this packet may not exist anymore!
|
||||
* @note Do not use the cargo packet anymore after it has been appended to this CargoList!
|
||||
* @param cp Cargo packet to add.
|
||||
* @param next the next hop
|
||||
* @param cp the cargo packet to add
|
||||
* @pre cp != NULL
|
||||
*/
|
||||
void StationCargoList::Append(CargoPacket *cp)
|
||||
void StationCargoList::Append(CargoPacket *cp, StationID next)
|
||||
{
|
||||
assert(cp != NULL);
|
||||
this->AddToCache(cp);
|
||||
|
||||
for (List::reverse_iterator it(this->packets.rbegin()); it != this->packets.rend(); it++) {
|
||||
StationCargoPacketMap::List &list = this->packets[next];
|
||||
for (StationCargoPacketMap::List::reverse_iterator it(list.rbegin());
|
||||
it != list.rend(); it++) {
|
||||
if (StationCargoList::TryMerge(*it, cp)) return;
|
||||
}
|
||||
|
||||
/* The packet could not be merged with another one */
|
||||
this->packets.push_back(cp);
|
||||
list.push_back(cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts cargo from the front of the packet list for a specific station and
|
||||
* applies some action to it.
|
||||
* @tparam Taction Action class or function to be used. It should define
|
||||
* "bool operator()(CargoPacket *)". If true is returned the
|
||||
* cargo packet will be removed from the list. Otherwise it
|
||||
* will be kept and the loop will be aborted.
|
||||
* @param action Action instance to be applied.
|
||||
* @param next Next hop the cargo wants to visit.
|
||||
* @return True if all packets with the given next hop have been removed,
|
||||
* False otherwise.
|
||||
*/
|
||||
template <class Taction>
|
||||
bool StationCargoList::ShiftCargo(Taction &action, StationID next)
|
||||
{
|
||||
std::pair<Iterator, Iterator> range(this->packets.equal_range(next));
|
||||
for (Iterator it(range.first); it != range.second && it.GetKey() == next;) {
|
||||
if (action.MaxMove() == 0) return false;
|
||||
CargoPacket *cp = *it;
|
||||
if (action(cp)) {
|
||||
it = this->packets.erase(it);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shifts cargo from the front of the packet list for a specific station and
|
||||
* and optional also from the list for "any station", then applies some action
|
||||
* to it.
|
||||
* @tparam Taction Action class or function to be used. It should define
|
||||
* "bool operator()(CargoPacket *)". If true is returned the
|
||||
* cargo packet will be removed from the list. Otherwise it
|
||||
* will be kept and the loop will be aborted.
|
||||
* @param action Action instance to be applied.
|
||||
* @param next Next hop the cargo wants to visit.
|
||||
* @param include_invalid If cargo from the INVALID_STATION list should be
|
||||
* used if necessary.
|
||||
* @return Amount of cargo actually moved.
|
||||
*/
|
||||
template <class Taction>
|
||||
uint StationCargoList::ShiftCargo(Taction action, StationID next, bool include_invalid)
|
||||
{
|
||||
uint max_move = action.MaxMove();
|
||||
if (this->ShiftCargo(action, next) && include_invalid && action.MaxMove() > 0) {
|
||||
this->ShiftCargo(action, INVALID_STATION);
|
||||
}
|
||||
return max_move - action.MaxMove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates where each destination loses roughly the same percentage of its
|
||||
* cargo. This is done by randomizing the selection of packets to be removed.
|
||||
* @param max_move Maximum amount of cargo to remove.
|
||||
* @return Amount of cargo actually moved.
|
||||
*/
|
||||
uint StationCargoList::Truncate(uint max_move)
|
||||
{
|
||||
max_move = min(max_move, this->count);
|
||||
uint prev_count = this->count;
|
||||
uint moved = 0;
|
||||
while (max_move > moved) {
|
||||
for (Iterator it(this->packets.begin()); it != this->packets.end();) {
|
||||
if (prev_count > max_move && RandomRange(prev_count) < prev_count - max_move) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
CargoPacket *cp = *it;
|
||||
uint diff = max_move - moved;
|
||||
if (cp->count > diff) {
|
||||
this->RemoveFromCache(cp, diff);
|
||||
cp->Reduce(diff);
|
||||
return moved + diff;
|
||||
} else {
|
||||
it = this->packets.erase(it);
|
||||
moved += cp->count;
|
||||
this->RemoveFromCache(cp, cp->count);
|
||||
delete cp;
|
||||
}
|
||||
}
|
||||
}
|
||||
return moved;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -550,10 +697,10 @@ void StationCargoList::Append(CargoPacket *cp)
|
||||
* @param load_place Tile index of the current station.
|
||||
* @return Amount of cargo actually reserved.
|
||||
*/
|
||||
uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place)
|
||||
uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next)
|
||||
{
|
||||
max_move = min(this->count, max_move);
|
||||
this->ShiftCargo(CargoReservation(this, dest, max_move, load_place));
|
||||
this->ShiftCargo(CargoReservation(this, dest, max_move, load_place), next, true);
|
||||
return max_move;
|
||||
}
|
||||
|
||||
@@ -564,21 +711,34 @@ uint StationCargoList::Reserve(uint max_move, VehicleCargoList *dest, TileIndex
|
||||
* @param max_move Amount of cargo to load.
|
||||
* @return Amount of cargo actually loaded.
|
||||
*/
|
||||
uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, TileIndex load_place)
|
||||
uint StationCargoList::Load(uint max_move, VehicleCargoList *dest, TileIndex load_place, StationID next_station)
|
||||
{
|
||||
uint move = min(dest->ActionCount(VehicleCargoList::MTA_LOAD), max_move);
|
||||
if (move > 0) {
|
||||
this->reserved_count -= move;
|
||||
dest->Reassign(move, VehicleCargoList::MTA_LOAD, VehicleCargoList::MTA_KEEP);
|
||||
return move;
|
||||
} else {
|
||||
move = min(this->count, max_move);
|
||||
this->ShiftCargo(CargoLoad(this, dest, move, load_place));
|
||||
return this->ShiftCargo(CargoLoad(this, dest, move, load_place), next_station, true);
|
||||
}
|
||||
return 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 append 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 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);
|
||||
}
|
||||
|
||||
/*
|
||||
* We have to instantiate everything we want to be usable.
|
||||
*/
|
||||
template class CargoList<VehicleCargoList>;
|
||||
template class CargoList<StationCargoList>;
|
||||
template class CargoList<VehicleCargoList, CargoPacketList>;
|
||||
template class CargoList<StationCargoList, StationCargoPacketMap>;
|
||||
|
Reference in New Issue
Block a user