mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-11 13:10:45 +00:00
Departures: Use more general order destination detection abstraction
This commit is contained in:
parent
fb37caf785
commit
9d277a5a4c
@ -86,29 +86,31 @@ struct OrderDateQueueItem {
|
||||
};
|
||||
|
||||
template <typename LOAD_FILTER>
|
||||
bool IsArrivalDepartureTest(const DepartureCallingSettings &settings, const Order *order, StationID station, LOAD_FILTER load_filter)
|
||||
bool IsArrivalDepartureTest(const DepartureCallingSettings &settings, const Order *order, LOAD_FILTER load_filter)
|
||||
{
|
||||
if (order->GetType() == OT_GOTO_STATION && (StationID)order->GetDestination() == station) {
|
||||
if (order->GetType() == OT_GOTO_STATION) {
|
||||
if (!settings.departure_no_load_test && !load_filter(order)) return false;
|
||||
return settings.allow_via || ((order->GetWaitTime() != 0 || order->IsWaitTimetabled()) && !(order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION));
|
||||
} else if (order->GetType() == OT_GOTO_WAYPOINT && (StationID)order->GetDestination() == station) {
|
||||
} else if (order->GetType() == OT_GOTO_WAYPOINT) {
|
||||
if (settings.allow_via) return true;
|
||||
return (order->GetWaitTime() != 0 || order->IsWaitTimetabled());
|
||||
} else {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool DepartureCallingSettings::IsDeparture(const Order *order, StationID station)
|
||||
bool DepartureCallingSettings::IsDeparture(const Order *order, const DepartureOrderDestinationDetector &source)
|
||||
{
|
||||
return IsArrivalDepartureTest(*this, order, station, [](const Order *order) {
|
||||
if (!source.OrderMatches(order)) return false;
|
||||
return IsArrivalDepartureTest(*this, order, [](const Order *order) {
|
||||
return order->GetLoadType() != OLFB_NO_LOAD;
|
||||
});
|
||||
}
|
||||
|
||||
bool DepartureCallingSettings::IsArrival(const Order *order, StationID station)
|
||||
bool DepartureCallingSettings::IsArrival(const Order *order, const DepartureOrderDestinationDetector &source)
|
||||
{
|
||||
return IsArrivalDepartureTest(*this, order, station, [](const Order *order) {
|
||||
if (!source.OrderMatches(order)) return false;
|
||||
return IsArrivalDepartureTest(*this, order, [](const Order *order) {
|
||||
return order->GetUnloadType() != OUFB_NO_UNLOAD;
|
||||
});
|
||||
}
|
||||
@ -283,13 +285,13 @@ static void ScheduledDispatchDepartureLocalFix(DepartureList &departure_list)
|
||||
|
||||
/**
|
||||
* Compute an up-to-date list of departures for a station.
|
||||
* @param station the station to compute the departures of
|
||||
* @param source the station/etc to compute the departures of
|
||||
* @param vehicles set of all the vehicles stopping at this station, of all vehicles types that we are interested in
|
||||
* @param type the type of departures to get (departures or arrivals)
|
||||
* @param calling_settings departure calling settings
|
||||
* @return a list of departures, which is empty if an error occurred
|
||||
*/
|
||||
DepartureList MakeDepartureList(StationID station, const std::vector<const Vehicle *> &vehicles, DepartureType type, DepartureCallingSettings calling_settings)
|
||||
DepartureList MakeDepartureList(DepartureOrderDestinationDetector source, const std::vector<const Vehicle *> &vehicles, DepartureType type, DepartureCallingSettings calling_settings)
|
||||
{
|
||||
/* This function is the meat of the departure boards functionality. */
|
||||
/* As an overview, it works by repeatedly considering the best possible next departure to show. */
|
||||
@ -435,8 +437,8 @@ DepartureList MakeDepartureList(StationID station, const std::vector<const Vehic
|
||||
|
||||
/* If the vehicle will be stopping at and loading from this station, and its wait time is not zero, then it is a departure. */
|
||||
/* If the vehicle will be stopping at and unloading at this station, and its wait time is not zero, then it is an arrival. */
|
||||
if ((type == D_DEPARTURE && calling_settings.IsDeparture(order, station)) ||
|
||||
(type == D_ARRIVAL && calling_settings.IsArrival(order, station))) {
|
||||
if ((type == D_DEPARTURE && calling_settings.IsDeparture(order, source)) ||
|
||||
(type == D_ARRIVAL && calling_settings.IsArrival(order, source))) {
|
||||
/* If the departure was scheduled to have already begun and has been cancelled, do not show it. */
|
||||
if (start_ticks < 0 && status == D_CANCELLED) {
|
||||
break;
|
||||
@ -601,15 +603,14 @@ DepartureList MakeDepartureList(StationID station, const std::vector<const Vehic
|
||||
|
||||
/* If we reach the original station again, then use it as the terminus. */
|
||||
if (order->GetType() == OT_GOTO_STATION &&
|
||||
(StationID)order->GetDestination() == station &&
|
||||
source.OrderMatches(order) &&
|
||||
(order->GetUnloadType() != OUFB_NO_UNLOAD ||
|
||||
calling_settings.show_all_stops) &&
|
||||
(((order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0) || ((lod.order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) != 0))) {
|
||||
/* If we're not calling anywhere, then skip this departure. */
|
||||
found_terminus = (d->calling_at.size() > 0);
|
||||
break;
|
||||
} else if (order->GetType() == OT_GOTO_WAYPOINT &&
|
||||
(StationID)order->GetDestination() == station) {
|
||||
} else if (order->GetType() == OT_GOTO_WAYPOINT && source.OrderMatches(order)) {
|
||||
/* If we're not calling anywhere, then skip this departure. */
|
||||
found_terminus = (d->calling_at.size() > 0);
|
||||
break;
|
||||
@ -808,7 +809,7 @@ DepartureList MakeDepartureList(StationID station, const std::vector<const Vehic
|
||||
if ((o->GetType() == OT_GOTO_STATION ||
|
||||
o->GetType() == OT_IMPLICIT) &&
|
||||
(o->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0) {
|
||||
if (o->GetDestination() == station) {
|
||||
if (source.StationMatches(o->GetDestination())) {
|
||||
/* Remove all possible origins */
|
||||
possible_origins.clear();
|
||||
} else {
|
||||
@ -825,7 +826,7 @@ DepartureList MakeDepartureList(StationID station, const std::vector<const Vehic
|
||||
calling_settings.show_all_stops) &&
|
||||
(o->GetType() == OT_GOTO_STATION ||
|
||||
o->GetType() == OT_IMPLICIT) &&
|
||||
o->GetDestination() != station &&
|
||||
!source.StationMatches(o->GetDestination()) &&
|
||||
(o->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0) {
|
||||
possible_origins.push_back({ o->GetDestination(), i });
|
||||
}
|
||||
@ -938,8 +939,8 @@ DepartureList MakeDepartureList(StationID station, const std::vector<const Vehic
|
||||
}
|
||||
|
||||
/* If the order loads from this station (or unloads if we're computing arrivals) and has a wait time set, then it is suitable for being a departure. */
|
||||
if ((type == D_DEPARTURE && calling_settings.IsDeparture(order, station)) ||
|
||||
(type == D_ARRIVAL && calling_settings.IsArrival(order, station))) {
|
||||
if ((type == D_DEPARTURE && calling_settings.IsDeparture(order, source)) ||
|
||||
(type == D_ARRIVAL && calling_settings.IsArrival(order, source))) {
|
||||
lod.order = order;
|
||||
found_next_order = true;
|
||||
break;
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
DepartureList MakeDepartureList(StationID station, const std::vector<const Vehicle *> &vehicles, DepartureType type, DepartureCallingSettings calling_settings);
|
||||
DepartureList MakeDepartureList(DepartureOrderDestinationDetector source, const std::vector<const Vehicle *> &vehicles, DepartureType type, DepartureCallingSettings calling_settings);
|
||||
|
||||
Ticks GetDeparturesMaxTicksAhead();
|
||||
|
||||
|
@ -482,6 +482,15 @@ public:
|
||||
bool show_pax = this->cargo_mode != DCF_FREIGHT_ONLY;
|
||||
bool show_freight = this->cargo_mode != DCF_PAX_ONLY;
|
||||
|
||||
DepartureOrderDestinationDetector source;
|
||||
if (this->is_waypoint) {
|
||||
SetBit(source.order_type_mask, OT_GOTO_WAYPOINT);
|
||||
source.destination = this->station;
|
||||
} else {
|
||||
SetBit(source.order_type_mask, OT_GOTO_STATION);
|
||||
source.destination = this->station;
|
||||
}
|
||||
|
||||
DepartureCallingSettings settings;
|
||||
settings.allow_via = this->is_waypoint || this->show_via;
|
||||
settings.departure_no_load_test = this->is_waypoint || _settings_client.gui.departure_show_all_stops;
|
||||
@ -490,12 +499,12 @@ public:
|
||||
settings.show_freight = show_freight;
|
||||
|
||||
if (this->mode != DM_ARRIVALS) {
|
||||
this->departures = MakeDepartureList(this->station, this->vehicles, D_DEPARTURE, settings);
|
||||
this->departures = MakeDepartureList(source, this->vehicles, D_DEPARTURE, settings);
|
||||
} else {
|
||||
this->departures.clear();
|
||||
}
|
||||
if (this->mode == DM_ARRIVALS || this->mode == DM_SEPARATE) {
|
||||
this->arrivals = MakeDepartureList(this->station, this->vehicles, D_ARRIVAL, settings);
|
||||
this->arrivals = MakeDepartureList(source, this->vehicles, D_ARRIVAL, settings);
|
||||
} else {
|
||||
this->arrivals.clear();
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "station_base.h"
|
||||
#include "order_base.h"
|
||||
#include "vehicle_base.h"
|
||||
#include "core/bitmath_func.hpp"
|
||||
#include <vector>
|
||||
|
||||
/** Whether or not a vehicle has arrived for a departure. */
|
||||
@ -113,6 +114,21 @@ struct Departure {
|
||||
}
|
||||
};
|
||||
|
||||
struct DepartureOrderDestinationDetector {
|
||||
OrderTypeMask order_type_mask = 0;
|
||||
DestinationID destination;
|
||||
|
||||
bool OrderMatches(const Order *order) const
|
||||
{
|
||||
return HasBit(this->order_type_mask, order->GetType()) && order->GetDestination() == this->destination;
|
||||
}
|
||||
|
||||
bool StationMatches(StationID station) const
|
||||
{
|
||||
return HasBit(this->order_type_mask, OT_GOTO_STATION) && station == this->destination;
|
||||
}
|
||||
};
|
||||
|
||||
struct DepartureCallingSettings {
|
||||
bool allow_via = false;
|
||||
bool departure_no_load_test = false;
|
||||
@ -120,8 +136,8 @@ struct DepartureCallingSettings {
|
||||
bool show_pax = false;
|
||||
bool show_freight = false;
|
||||
|
||||
bool IsDeparture(const Order *order, StationID station);
|
||||
bool IsArrival(const Order *order, StationID station);
|
||||
bool IsDeparture(const Order *order, const DepartureOrderDestinationDetector &source);
|
||||
bool IsArrival(const Order *order, const DepartureOrderDestinationDetector &source);
|
||||
};
|
||||
|
||||
typedef std::vector<std::unique_ptr<Departure>> DepartureList;
|
||||
|
@ -45,6 +45,8 @@
|
||||
|
||||
#include "3rdparty/robin_hood/robin_hood.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "safeguards.h"
|
||||
|
||||
/* DestinationID must be at least as large as every these below, because it can
|
||||
@ -53,6 +55,9 @@
|
||||
static_assert(sizeof(DestinationID) >= sizeof(DepotID));
|
||||
static_assert(sizeof(DestinationID) >= sizeof(StationID));
|
||||
|
||||
/* OrderTypeMask must be large enough for all order types */
|
||||
static_assert(std::numeric_limits<OrderTypeMask>::digits >= OT_END);
|
||||
|
||||
OrderPool _order_pool("Order");
|
||||
INSTANTIATE_POOL_METHODS(Order)
|
||||
OrderListPool _orderlist_pool("OrderList");
|
||||
|
@ -55,6 +55,8 @@ enum OrderType : uint8_t {
|
||||
OT_END
|
||||
};
|
||||
|
||||
using OrderTypeMask = uint16_t;
|
||||
|
||||
enum OrderSlotSubType : uint8_t {
|
||||
OSST_RELEASE = 0,
|
||||
OSST_TRY_ACQUIRE = 1,
|
||||
|
Loading…
Reference in New Issue
Block a user