Merge branch 'cargo_type_order' into jgrpp

# Conflicts:
#	src/order_base.h
#	src/order_gui.cpp
#	src/order_type.h
#	src/saveload/extended_ver_sl.cpp
#	src/saveload/extended_ver_sl.h
#	src/vehicle_base.h
This commit is contained in:
Jonathan G Rennison
2016-09-08 00:12:48 +01:00
19 changed files with 1079 additions and 159 deletions

View File

@@ -24,20 +24,44 @@
* @param v Vehicle to refresh links for.
* @param allow_merge If the refresher is allowed to merge or extend link graphs.
* @param is_full_loading If the vehicle is full loading.
* @param cargo_mask Mask of cargoes to refresh
*/
/* static */ void LinkRefresher::Run(Vehicle *v, bool allow_merge, bool is_full_loading)
/* static */ void LinkRefresher::Run(Vehicle *v, bool allow_merge, bool is_full_loading, uint32 cargo_mask)
{
/* If there are no orders we can't predict anything.*/
if (v->orders.list == NULL) return;
/* Make sure the first order is a useful order. */
const Order *first = v->orders.list->GetNextDecisionNode(v->GetOrder(v->cur_implicit_order_index), 0);
if (first == NULL) return;
uint32 have_cargo_mask = v->GetLastLoadingStationValidCargoMask();
HopSet seen_hops;
LinkRefresher refresher(v, &seen_hops, allow_merge, is_full_loading);
/* Scan orders for cargo-specific load/unload, and run LinkRefresher separately for each set of cargoes where they differ. */
while (cargo_mask != 0) {
uint32 iter_cargo_mask = cargo_mask;
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) {
CargoMaskValueFilter<uint>(iter_cargo_mask, [&](CargoID cargo) -> uint {
return o->GetCargoUnloadType(cargo) & (OUFB_TRANSFER | OUFB_UNLOAD | OUFB_NO_UNLOAD);
});
}
if (o->GetLoadType() == OLFB_CARGO_TYPE_LOAD) {
CargoMaskValueFilter<uint>(iter_cargo_mask, [&](CargoID cargo) -> uint {
return o->GetCargoLoadType(cargo) & (OLFB_NO_LOAD);
});
}
}
}
refresher.RefreshLinks(first, first, v->last_loading_station != INVALID_STATION ? 1 << HAS_CARGO : 0);
/* Make sure the first order is a useful order. */
const Order *first = v->orders.list->GetNextDecisionNode(v->GetOrder(v->cur_implicit_order_index), 0, iter_cargo_mask);
if (first != NULL) {
HopSet seen_hops;
LinkRefresher refresher(v, &seen_hops, allow_merge, is_full_loading, iter_cargo_mask);
refresher.RefreshLinks(first, first, (iter_cargo_mask & have_cargo_mask) ? 1 << HAS_CARGO : 0);
}
cargo_mask &= ~iter_cargo_mask;
}
}
/**
@@ -68,9 +92,9 @@ bool LinkRefresher::Hop::operator<(const Hop &other) const
* @param allow_merge If the refresher is allowed to merge or extend link graphs.
* @param is_full_loading If the vehicle is full loading.
*/
LinkRefresher::LinkRefresher(Vehicle *vehicle, HopSet *seen_hops, bool allow_merge, bool is_full_loading) :
LinkRefresher::LinkRefresher(Vehicle *vehicle, HopSet *seen_hops, bool allow_merge, bool is_full_loading, uint32 cargo_mask) :
vehicle(vehicle), seen_hops(seen_hops), cargo(CT_INVALID), allow_merge(allow_merge),
is_full_loading(is_full_loading)
is_full_loading(is_full_loading), cargo_mask(cargo_mask)
{
memset(this->capacities, 0, sizeof(this->capacities));
@@ -175,8 +199,10 @@ const Order *LinkRefresher::PredictNextOrder(const Order *cur, const Order *next
SetBit(flags, USE_NEXT);
if (next->IsType(OT_CONDITIONAL)) {
uint32 this_cargo_mask = this->cargo_mask;
const Order *skip_to = this->vehicle->orders.list->GetNextDecisionNode(
this->vehicle->orders.list->GetOrderAt(next->GetConditionSkipToOrder()), num_hops);
this->vehicle->orders.list->GetOrderAt(next->GetConditionSkipToOrder()), num_hops, this_cargo_mask);
assert(this_cargo_mask == this->cargo_mask);
if (skip_to != NULL && num_hops < this->vehicle->orders.list->GetNumOrders()) {
/* Make copies of capacity tracking lists. There is potential
* for optimization here: If the vehicle never refits we don't
@@ -189,8 +215,10 @@ const Order *LinkRefresher::PredictNextOrder(const Order *cur, const Order *next
/* Reassign next with the following stop. This can be a station or a
* depot.*/
uint32 this_cargo_mask = this->cargo_mask;
next = this->vehicle->orders.list->GetNextDecisionNode(
this->vehicle->orders.list->GetNext(next), num_hops++);
this->vehicle->orders.list->GetNext(next), num_hops++, this_cargo_mask);
assert(this_cargo_mask == this->cargo_mask);
}
return next;
}
@@ -208,6 +236,8 @@ void LinkRefresher::RefreshStats(const Order *cur, const Order *next)
for (CargoID c = 0; c < NUM_CARGO; c++) {
/* Refresh the link and give it a minimum capacity. */
if (!HasBit(this->cargo_mask, c)) continue;
uint cargo_quantity = this->capacities[c];
if (cargo_quantity == 0) continue;
@@ -218,7 +248,7 @@ void LinkRefresher::RefreshStats(const Order *cur, const Order *next)
}
/* A link is at least partly restricted if a vehicle can't load at its source. */
EdgeUpdateMode restricted_mode = (cur->GetLoadType() & OLFB_NO_LOAD) == 0 ?
EdgeUpdateMode restricted_mode = (cur->GetCargoLoadType(c) & OLFB_NO_LOAD) == 0 ?
EUM_UNRESTRICTED : EUM_RESTRICTED;
/* If the vehicle is currently full loading, increase the capacities at the station
@@ -309,7 +339,7 @@ void LinkRefresher::RefreshLinks(const Order *cur, const Order *next, uint8 flag
}
if (cur->IsType(OT_GOTO_STATION) || cur->IsType(OT_IMPLICIT)) {
if (cur->CanLeaveWithCargo(HasBit(flags, HAS_CARGO))) {
if (cur->CanLeaveWithCargo(HasBit(flags, HAS_CARGO), FindFirstBit(this->cargo_mask))) {
SetBit(flags, HAS_CARGO);
this->RefreshStats(cur, next);
} else {

View File

@@ -23,7 +23,7 @@
*/
class LinkRefresher {
public:
static void Run(Vehicle *v, bool allow_merge = true, bool is_full_loading = false);
static void Run(Vehicle *v, bool allow_merge = true, bool is_full_loading = false, uint32 cargo_mask = ~0);
protected:
/**
@@ -89,8 +89,9 @@ protected:
CargoID cargo; ///< Cargo given in last refit order.
bool allow_merge; ///< If the refresher is allowed to merge or extend link graphs.
bool is_full_loading; ///< If the vehicle is full loading.
uint32 cargo_mask; ///< Bit-mask of cargo IDs to refresh.
LinkRefresher(Vehicle *v, HopSet *seen_hops, bool allow_merge, bool is_full_loading);
LinkRefresher(Vehicle *v, HopSet *seen_hops, bool allow_merge, bool is_full_loading, uint32 cargo_mask);
bool HandleRefit(CargoID refit_cargo);
void ResetRefit();