mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Use EnumBitSet for GoodsEntry status. (#13899)
parent
5331389765
commit
325f7f9767
|
@ -1107,9 +1107,7 @@ static Money DeliverGoods(int num_pieces, CargoType cargo_type, StationID dest,
|
|||
|
||||
/* Update station statistics */
|
||||
if (accepted_total > 0) {
|
||||
SetBit(st->goods[cargo_type].status, GoodsEntry::GES_EVER_ACCEPTED);
|
||||
SetBit(st->goods[cargo_type].status, GoodsEntry::GES_CURRENT_MONTH);
|
||||
SetBit(st->goods[cargo_type].status, GoodsEntry::GES_ACCEPTED_BIGTICK);
|
||||
st->goods[cargo_type].status.Set({GoodsEntry::State::EverAccepted, GoodsEntry::State::CurrentMonth, GoodsEntry::State::AcceptedBigtick});
|
||||
}
|
||||
|
||||
/* Update company statistics */
|
||||
|
@ -1285,7 +1283,7 @@ void PrepareUnload(Vehicle *front_v)
|
|||
const GoodsEntry *ge = &st->goods[v->cargo_type];
|
||||
if (v->cargo_cap > 0 && v->cargo.TotalCount() > 0) {
|
||||
v->cargo.Stage(
|
||||
HasBit(ge->status, GoodsEntry::GES_ACCEPTANCE),
|
||||
ge->status.Test(GoodsEntry::State::Acceptance),
|
||||
front_v->last_station_visited, next_station,
|
||||
front_v->current_order.GetUnloadType(), ge,
|
||||
v->cargo_type, front_v->cargo_payment,
|
||||
|
@ -1676,7 +1674,7 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||
uint amount_unloaded = _settings_game.order.gradual_loading ? std::min(cargo_count, GetLoadAmount(v)) : cargo_count;
|
||||
bool remaining = false; // Are there cargo entities in this vehicle that can still be unloaded here?
|
||||
|
||||
if (!HasBit(ge->status, GoodsEntry::GES_ACCEPTANCE) && v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER) > 0) {
|
||||
if (!ge->status.Test(GoodsEntry::State::Acceptance) && v->cargo.ActionCount(VehicleCargoList::MTA_DELIVER) > 0) {
|
||||
/* The station does not accept our goods anymore. */
|
||||
if (front->current_order.GetUnloadType() & (OUFB_TRANSFER | OUFB_UNLOAD)) {
|
||||
/* Transfer instead of delivering. */
|
||||
|
@ -1709,7 +1707,7 @@ static void LoadUnloadVehicle(Vehicle *front)
|
|||
/* Upon transferring cargo, make sure the station has a rating. Fake a pickup for the
|
||||
* first unload to prevent the cargo from quickly decaying after the initial drop. */
|
||||
ge->time_since_pickup = 0;
|
||||
SetBit(ge->status, GoodsEntry::GES_RATING);
|
||||
ge->status.Set(GoodsEntry::State::Rating);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -151,7 +151,7 @@ NodeID LinkGraph::AddNode(const Station *st)
|
|||
const GoodsEntry &good = st->goods[this->cargo];
|
||||
|
||||
NodeID new_node = this->Size();
|
||||
this->nodes.emplace_back(st->xy, st->index, HasBit(good.status, GoodsEntry::GES_ACCEPTANCE));
|
||||
this->nodes.emplace_back(st->xy, st->index, good.status.Test(GoodsEntry::State::Acceptance));
|
||||
|
||||
return new_node;
|
||||
}
|
||||
|
|
|
@ -462,10 +462,7 @@ static uint32_t GetDistanceFromNearbyHouse(uint8_t parameter, TileIndex tile, Ho
|
|||
/* Collect acceptance stats. */
|
||||
uint32_t res = 0;
|
||||
for (Station *st : stations.GetStations()) {
|
||||
if (HasBit(st->goods[cargo_type].status, GoodsEntry::GES_EVER_ACCEPTED)) SetBit(res, 0);
|
||||
if (HasBit(st->goods[cargo_type].status, GoodsEntry::GES_LAST_MONTH)) SetBit(res, 1);
|
||||
if (HasBit(st->goods[cargo_type].status, GoodsEntry::GES_CURRENT_MONTH)) SetBit(res, 2);
|
||||
if (HasBit(st->goods[cargo_type].status, GoodsEntry::GES_ACCEPTED_BIGTICK)) SetBit(res, 3);
|
||||
res |= st->goods[cargo_type].ConvertState();
|
||||
}
|
||||
|
||||
/* Cargo triggered CB 148? */
|
||||
|
|
|
@ -53,6 +53,20 @@ template class NewGRFClass<StationSpec, StationClassID, STAT_CLASS_MAX>;
|
|||
|
||||
static const uint NUM_STATIONSSPECS_PER_STATION = 255; ///< Maximum number of parts per station.
|
||||
|
||||
/**
|
||||
* Convert GoodsEntry status to the form required for NewGRF variables.
|
||||
* @return NewGRF representation of GoodsEntry state.
|
||||
*/
|
||||
uint8_t GoodsEntry::ConvertState() const
|
||||
{
|
||||
uint8_t res = 0;
|
||||
if (this->status.Test(GoodsEntry::State::EverAccepted)) SetBit(res, 0);
|
||||
if (this->status.Test(GoodsEntry::State::LastMonth)) SetBit(res, 1);
|
||||
if (this->status.Test(GoodsEntry::State::CurrentMonth)) SetBit(res, 2);
|
||||
if (this->status.Test(GoodsEntry::State::AcceptedBigtick)) SetBit(res, 3);
|
||||
return res;
|
||||
}
|
||||
|
||||
enum TriggerArea : uint8_t {
|
||||
TA_TILE,
|
||||
TA_PLATFORM,
|
||||
|
@ -447,13 +461,8 @@ uint32_t Station::GetNewGRFVariable(const ResolverObject &object, uint8_t variab
|
|||
case 0x62: return ge->HasRating() ? ge->rating : 0xFFFFFFFF;
|
||||
case 0x63: return ge->HasData() ? ge->GetData().cargo.PeriodsInTransit() : 0;
|
||||
case 0x64: return ge->HasVehicleEverTriedLoading() ? ge->last_speed | (ge->last_age << 8) : 0xFF00;
|
||||
case 0x65: return GB(ge->status, GoodsEntry::GES_ACCEPTANCE, 1) << 3;
|
||||
case 0x69: {
|
||||
static_assert((int)GoodsEntry::GES_EVER_ACCEPTED + 1 == (int)GoodsEntry::GES_LAST_MONTH);
|
||||
static_assert((int)GoodsEntry::GES_EVER_ACCEPTED + 2 == (int)GoodsEntry::GES_CURRENT_MONTH);
|
||||
static_assert((int)GoodsEntry::GES_EVER_ACCEPTED + 3 == (int)GoodsEntry::GES_ACCEPTED_BIGTICK);
|
||||
return GB(ge->status, GoodsEntry::GES_EVER_ACCEPTED, 4);
|
||||
}
|
||||
case 0x65: return ge->status.Test(GoodsEntry::State::Acceptance) ? (1U << 3) : 0;
|
||||
case 0x69: return ge->ConvertState();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,7 +471,7 @@ uint32_t Station::GetNewGRFVariable(const ResolverObject &object, uint8_t variab
|
|||
const GoodsEntry *g = &this->goods[GB(variable - 0x8C, 3, 4)];
|
||||
switch (GB(variable - 0x8C, 0, 3)) {
|
||||
case 0: return g->HasData() ? g->GetData().cargo.TotalCount() : 0;
|
||||
case 1: return GB(g->HasData() ? std::min(g->GetData().cargo.TotalCount(), 4095u) : 0, 0, 4) | (GB(g->status, GoodsEntry::GES_ACCEPTANCE, 1) << 7);
|
||||
case 1: return GB(g->HasData() ? std::min(g->GetData().cargo.TotalCount(), 4095u) : 0, 0, 4) | (g->status.Test(GoodsEntry::State::Acceptance) ? (1U << 7) : 0);
|
||||
case 2: return g->time_since_pickup;
|
||||
case 3: return g->rating;
|
||||
case 4: return (g->HasData() ? g->GetData().cargo.GetFirstStation() : StationID::Invalid()).base();
|
||||
|
|
|
@ -1735,7 +1735,7 @@ bool AfterLoadGame()
|
|||
for (Station *st : Station::Iterate()) {
|
||||
for (GoodsEntry &ge : st->goods) {
|
||||
ge.last_speed = 0;
|
||||
if (ge.HasData() && ge.GetData().cargo.AvailableCount() != 0) SetBit(ge.status, GoodsEntry::GES_RATING);
|
||||
if (ge.HasData() && ge.GetData().cargo.AvailableCount() != 0) ge.status.Set(GoodsEntry::State::Rating);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -724,8 +724,8 @@ static bool LoadOldGood(LoadgameState &ls, int num)
|
|||
|
||||
if (!LoadChunk(ls, ge, goods_chunk)) return false;
|
||||
|
||||
AssignBit(ge->status, GoodsEntry::GES_ACCEPTANCE, HasBit(_waiting_acceptance, 15));
|
||||
AssignBit(ge->status, GoodsEntry::GES_RATING, _cargo_source != 0xFF);
|
||||
ge->status.Set(GoodsEntry::State::Acceptance, HasBit(_waiting_acceptance, 15));
|
||||
ge->status.Set(GoodsEntry::State::Rating, _cargo_source != 0xFF);
|
||||
if (GB(_waiting_acceptance, 0, 12) != 0 && CargoPacket::CanAllocateItem()) {
|
||||
ge->GetOrCreateData().cargo.Append(new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_periods, (_cargo_source == 0xFF) ? StationID::Invalid() : StationID{_cargo_source}, INVALID_TILE, 0),
|
||||
StationID::Invalid());
|
||||
|
|
|
@ -414,7 +414,7 @@ public:
|
|||
SwapPackets(&ge);
|
||||
}
|
||||
if (IsSavegameVersionBefore(SLV_68)) {
|
||||
AssignBit(ge.status, GoodsEntry::GES_ACCEPTANCE, HasBit(_waiting_acceptance, 15));
|
||||
ge.status.Set(GoodsEntry::State::Acceptance, HasBit(_waiting_acceptance, 15));
|
||||
if (GB(_waiting_acceptance, 0, 12) != 0) {
|
||||
/* In old versions, enroute_from used 0xFF as StationID::Invalid() */
|
||||
StationID source = (IsSavegameVersionBefore(SLV_7) && _cargo_source == 0xFF) ? StationID::Invalid() : static_cast<StationID>(_cargo_source);
|
||||
|
@ -428,7 +428,7 @@ public:
|
|||
/* Don't construct the packet with station here, because that'll fail with old savegames */
|
||||
CargoPacket *cp = new CargoPacket(GB(_waiting_acceptance, 0, 12), _cargo_periods, source, TileIndex{_cargo_source_xy}, _cargo_feeder_share);
|
||||
ge.GetOrCreateData().cargo.Append(cp, StationID::Invalid());
|
||||
SetBit(ge.status, GoodsEntry::GES_RATING);
|
||||
ge.status.Set(GoodsEntry::State::Rating);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,6 @@ ScriptCargoList_StationAccepting::ScriptCargoList_StationAccepting(StationID sta
|
|||
|
||||
const Station *st = ::Station::Get(station_id);
|
||||
for (CargoType cargo = 0; cargo < NUM_CARGO; ++cargo) {
|
||||
if (HasBit(st->goods[cargo].status, GoodsEntry::GES_ACCEPTANCE)) this->AddItem(cargo);
|
||||
if (st->goods[cargo].status.Test(GoodsEntry::State::Acceptance)) this->AddItem(cargo);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -165,12 +165,12 @@ public:
|
|||
*/
|
||||
struct GoodsEntry {
|
||||
/** Status of this cargo for the station. */
|
||||
enum GoodsEntryStatus : uint8_t {
|
||||
enum class State : uint8_t {
|
||||
/**
|
||||
* Set when the station accepts the cargo currently for final deliveries.
|
||||
* It is updated every STATION_ACCEPTANCE_TICKS ticks by checking surrounding tiles for acceptance >= 8/8.
|
||||
*/
|
||||
GES_ACCEPTANCE,
|
||||
Acceptance = 0,
|
||||
|
||||
/**
|
||||
* This indicates whether a cargo has a rating at the station.
|
||||
|
@ -180,32 +180,33 @@ struct GoodsEntry {
|
|||
*
|
||||
* This flag is cleared after 255 * STATION_RATING_TICKS of not having seen a pickup.
|
||||
*/
|
||||
GES_RATING,
|
||||
Rating = 1,
|
||||
|
||||
/**
|
||||
* Set when a vehicle ever delivered cargo to the station for final delivery.
|
||||
* This flag is never cleared.
|
||||
*/
|
||||
GES_EVER_ACCEPTED,
|
||||
EverAccepted = 2,
|
||||
|
||||
/**
|
||||
* Set when cargo was delivered for final delivery last month.
|
||||
* This flag is set to the value of GES_CURRENT_MONTH at the start of each month.
|
||||
* This flag is set to the value of State::CurrentMonth at the start of each month.
|
||||
*/
|
||||
GES_LAST_MONTH,
|
||||
LastMonth = 3,
|
||||
|
||||
/**
|
||||
* Set when cargo was delivered for final delivery this month.
|
||||
* This flag is reset on the beginning of every month.
|
||||
*/
|
||||
GES_CURRENT_MONTH,
|
||||
CurrentMonth = 4,
|
||||
|
||||
/**
|
||||
* Set when cargo was delivered for final delivery during the current STATION_ACCEPTANCE_TICKS interval.
|
||||
* This flag is reset every STATION_ACCEPTANCE_TICKS ticks.
|
||||
*/
|
||||
GES_ACCEPTED_BIGTICK,
|
||||
AcceptedBigtick = 5,
|
||||
};
|
||||
using States = EnumBitSet<State, uint8_t>;
|
||||
|
||||
struct GoodsEntryData {
|
||||
StationCargoList cargo{}; ///< The cargo packets of cargo waiting in this station
|
||||
|
@ -221,7 +222,7 @@ struct GoodsEntry {
|
|||
NodeID node = INVALID_NODE; ///< ID of node in link graph referring to this goods entry.
|
||||
LinkGraphID link_graph = LinkGraphID::Invalid(); ///< Link graph this station belongs to.
|
||||
|
||||
uint8_t status = 0; ///< Status of this cargo, see #GoodsEntryStatus.
|
||||
States status{}; ///< Status of this cargo, see #State.
|
||||
|
||||
/**
|
||||
* Number of rating-intervals (up to 255) since the last vehicle tried to load this cargo.
|
||||
|
@ -253,7 +254,7 @@ struct GoodsEntry {
|
|||
|
||||
/**
|
||||
* Reports whether a vehicle has ever tried to load the cargo at this station.
|
||||
* This does not imply that there was cargo available for loading. Refer to GES_RATING for that.
|
||||
* This does not imply that there was cargo available for loading. Refer to GoodsEntry::State::Rating for that.
|
||||
* @return true if vehicle tried to load.
|
||||
*/
|
||||
bool HasVehicleEverTriedLoading() const { return this->last_speed != 0; }
|
||||
|
@ -264,7 +265,7 @@ struct GoodsEntry {
|
|||
*/
|
||||
inline bool HasRating() const
|
||||
{
|
||||
return HasBit(this->status, GES_RATING);
|
||||
return this->status.Test(GoodsEntry::State::Rating);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -339,6 +340,8 @@ struct GoodsEntry {
|
|||
return *this->data;
|
||||
}
|
||||
|
||||
uint8_t ConvertState() const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<GoodsEntryData> data = nullptr; ///< Optional cargo packet and flow data.
|
||||
};
|
||||
|
|
|
@ -501,7 +501,7 @@ CargoTypes GetAcceptanceMask(const Station *st)
|
|||
CargoTypes mask = 0;
|
||||
|
||||
for (auto it = std::begin(st->goods); it != std::end(st->goods); ++it) {
|
||||
if (HasBit(it->status, GoodsEntry::GES_ACCEPTANCE)) SetBit(mask, std::distance(std::begin(st->goods), it));
|
||||
if (it->status.Test(GoodsEntry::State::Acceptance)) SetBit(mask, std::distance(std::begin(st->goods), it));
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
@ -641,7 +641,7 @@ void UpdateStationAcceptance(Station *st, bool show_msg)
|
|||
}
|
||||
|
||||
GoodsEntry &ge = st->goods[cargo];
|
||||
SB(ge.status, GoodsEntry::GES_ACCEPTANCE, 1, amt >= 8);
|
||||
ge.status.Set(GoodsEntry::State::Acceptance, amt >= 8);
|
||||
if (LinkGraph::IsValidID(ge.link_graph)) {
|
||||
(*LinkGraph::Get(ge.link_graph))[ge.node].SetDemand(amt / 8);
|
||||
}
|
||||
|
@ -3753,7 +3753,7 @@ void TriggerWatchedCargoCallbacks(Station *st)
|
|||
/* Collect cargoes accepted since the last big tick. */
|
||||
CargoTypes cargoes = 0;
|
||||
for (CargoType cargo_type = 0; cargo_type < NUM_CARGO; cargo_type++) {
|
||||
if (HasBit(st->goods[cargo_type].status, GoodsEntry::GES_ACCEPTED_BIGTICK)) SetBit(cargoes, cargo_type);
|
||||
if (st->goods[cargo_type].status.Test(GoodsEntry::State::AcceptedBigtick)) SetBit(cargoes, cargo_type);
|
||||
}
|
||||
|
||||
/* Anything to do? */
|
||||
|
@ -3785,7 +3785,7 @@ static bool StationHandleBigTick(BaseStation *st)
|
|||
TriggerWatchedCargoCallbacks(Station::From(st));
|
||||
|
||||
for (GoodsEntry &ge : Station::From(st)->goods) {
|
||||
ClrBit(ge.status, GoodsEntry::GES_ACCEPTED_BIGTICK);
|
||||
ge.status.Reset(GoodsEntry::State::AcceptedBigtick);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3845,7 +3845,7 @@ static void UpdateStationRating(Station *st)
|
|||
if (ge->HasRating()) {
|
||||
byte_inc_sat(&ge->time_since_pickup);
|
||||
if (ge->time_since_pickup == 255 && _settings_game.order.selectgoods) {
|
||||
ClrBit(ge->status, GoodsEntry::GES_RATING);
|
||||
ge->status.Reset(GoodsEntry::State::Rating);
|
||||
ge->last_speed = 0;
|
||||
TruncateCargo(cs, ge);
|
||||
waiting_changed = true;
|
||||
|
@ -4222,8 +4222,8 @@ static IntervalTimer<TimerGameEconomy> _economy_stations_monthly({TimerGameEcono
|
|||
{
|
||||
for (Station *st : Station::Iterate()) {
|
||||
for (GoodsEntry &ge : st->goods) {
|
||||
SB(ge.status, GoodsEntry::GES_LAST_MONTH, 1, GB(ge.status, GoodsEntry::GES_CURRENT_MONTH, 1));
|
||||
ClrBit(ge.status, GoodsEntry::GES_CURRENT_MONTH);
|
||||
ge.status.Set(GoodsEntry::State::LastMonth, ge.status.Test(GoodsEntry::State::CurrentMonth));
|
||||
ge.status.Reset(GoodsEntry::State::CurrentMonth);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -4233,7 +4233,7 @@ void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint rad
|
|||
ForAllStationsRadius(tile, radius, [&](Station *st) {
|
||||
if (st->owner == owner && DistanceManhattan(tile, st->xy) <= radius) {
|
||||
for (GoodsEntry &ge : st->goods) {
|
||||
if (ge.status != 0) {
|
||||
if (ge.status.Any()) {
|
||||
ge.rating = ClampTo<uint8_t>(ge.rating + amount);
|
||||
}
|
||||
}
|
||||
|
@ -4274,7 +4274,7 @@ static uint UpdateStationWaiting(Station *st, CargoType cargo, uint amount, Sour
|
|||
|
||||
if (!ge.HasRating()) {
|
||||
InvalidateWindowData(WC_STATION_LIST, st->owner);
|
||||
SetBit(ge.status, GoodsEntry::GES_RATING);
|
||||
ge.status.Set(GoodsEntry::State::Rating);
|
||||
}
|
||||
|
||||
TriggerStationRandomisation(st, st->xy, SRT_NEW_CARGO, cargo);
|
||||
|
|
Loading…
Reference in New Issue