From c4931c3a6e66a522c7e8afc126b3e2598806fd2c Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Mon, 17 Apr 2023 08:14:51 +0100 Subject: [PATCH] Add: NewGRF persistent storage for vehicles. --- src/newgrf_engine.cpp | 20 ++++++++++++++++++++ src/newgrf_engine.h | 1 + src/saveload/afterload.cpp | 6 ++++++ src/saveload/saveload.h | 2 ++ src/saveload/vehicle_sl.cpp | 1 + src/table/newgrf_debug_data.h | 7 +++++++ src/vehicle.cpp | 2 ++ src/vehicle_base.h | 2 ++ 8 files changed, 41 insertions(+) diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index 82ab0b70fb..708d5c5b61 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -24,6 +24,7 @@ #include "newgrf_railtype.h" #include "newgrf_roadtype.h" #include "ship.h" +#include "newgrf_debug.h" #include "safeguards.h" @@ -315,6 +316,23 @@ static uint8_t MapAircraftMovementAction(const Aircraft *v) return this->v == nullptr ? 0 : this->v->waiting_triggers; } +/* virtual */ void VehicleScopeResolver::StorePSA(uint pos, int32_t value) +{ + if (this->v == nullptr) return; + + /* const_cast because we're in too deep to change Vehicle to be non-const. */ + Vehicle *v = const_cast(this->v); + if (v->psa == nullptr) { + /* There is no need to create a storage if the value is zero. */ + if (value == 0) return; + + uint32_t grfid = (this->ro.grffile != nullptr) ? this->ro.grffile->grfid : 0; + assert(PersistentStorage::CanAllocateItem()); + v->psa = new PersistentStorage(grfid, GetGrfSpecFeature(this->v->type), INVALID_TILE); + } + v->psa->StoreValue(pos, value); +} + /* virtual */ ScopeResolver *VehicleResolverObject::GetScope(VarSpriteGroupScope scope, uint8_t relative) { @@ -693,6 +711,8 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec default: return 0x00; } + case 0x7C: return (v->psa != nullptr) ? v->psa->GetValue(parameter) : 0; + case 0xFE: case 0xFF: { uint16_t modflags = 0; diff --git a/src/newgrf_engine.h b/src/newgrf_engine.h index 339be33d8a..0ff19a916b 100644 --- a/src/newgrf_engine.h +++ b/src/newgrf_engine.h @@ -41,6 +41,7 @@ struct VehicleScopeResolver : public ScopeResolver { uint32_t GetRandomBits() const override; uint32_t GetVariable(uint8_t variable, [[maybe_unused]] uint32_t parameter, bool &available) const override; uint32_t GetTriggers() const override; + void StorePSA(uint pos, int32_t value) override; }; /** Resolver for a vehicle (chain) */ diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 40da48d437..98263f9250 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -48,6 +48,7 @@ #include "../subsidy_base.h" #include "../subsidy_func.h" #include "../newgrf.h" +#include "../newgrf_debug.h" #include "../newgrf_station.h" #include "../engine_func.h" #include "../rail_gui.h" @@ -290,6 +291,11 @@ static void InitializeWindowsAndCaches() it->tile = t->xy; } } + for (Vehicle *v : Vehicle::Iterate()) { + if (v->psa != nullptr) { + v->psa->feature = GetGrfSpecFeature(v->type); + } + } for (RoadVehicle *rv : RoadVehicle::Iterate()) { if (rv->IsFrontEngine()) { rv->CargoChanged(); diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index ff4aff172f..81f376eb0a 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -397,6 +397,8 @@ enum SaveLoadVersion : uint16_t { SLV_INCREASE_HOUSE_LIMIT, ///< 348 PR#12288 Increase house limit to 4096. SLV_VARIABLE_PERSISTENT_STORAGE, ///< 349 PR#10670 NewGRF persistent storage moved from fixed array to dynamic. + SLV_VEHICLE_STORAGE, ///< 350 PR#10670 Addition of persistent storage for vehicles. + SL_MAX_VERSION, ///< Highest possible saveload version }; diff --git a/src/saveload/vehicle_sl.cpp b/src/saveload/vehicle_sl.cpp index 504494391b..f959e54e94 100644 --- a/src/saveload/vehicle_sl.cpp +++ b/src/saveload/vehicle_sl.cpp @@ -767,6 +767,7 @@ public: SLE_CONDVAR(Vehicle, depot_unbunching_last_departure, SLE_UINT64, SLV_DEPOT_UNBUNCHING, SL_MAX_VERSION), SLE_CONDVAR(Vehicle, depot_unbunching_next_departure, SLE_UINT64, SLV_DEPOT_UNBUNCHING, SL_MAX_VERSION), SLE_CONDVAR(Vehicle, round_trip_time, SLE_INT32, SLV_DEPOT_UNBUNCHING, SL_MAX_VERSION), + SLE_CONDREF(Vehicle, psa, REF_STORAGE, SLV_VEHICLE_STORAGE, SL_MAX_VERSION), }; inline const static SaveLoadCompatTable compat_description = _vehicle_common_sl_compat; diff --git a/src/table/newgrf_debug_data.h b/src/table/newgrf_debug_data.h index 91b66c8f11..a604183e60 100644 --- a/src/table/newgrf_debug_data.h +++ b/src/table/newgrf_debug_data.h @@ -84,6 +84,13 @@ class NIHVehicle : public NIHelper { VehicleResolverObject ro(v->engine_type, v, VehicleResolverObject::WO_CACHED); return ro.GetScope(VSG_SCOPE_SELF)->GetVariable(var, param, avail); } + + std::span GetPSA(uint index, uint32_t) const override + { + const Vehicle *v = Vehicle::Get(index); + if (v->psa == nullptr) return {}; + return v->psa->storage; + } }; static const NIFeature _nif_vehicle = { diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 18c04eb7ba..af088c3817 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -901,6 +901,8 @@ Vehicle::~Vehicle() * it may happen that vehicle chain is deleted when visible */ if (!(this->vehstatus & VS_HIDDEN)) this->MarkAllViewportsDirty(); + delete this->psa; + Vehicle *v = this->Next(); this->SetNext(nullptr); diff --git a/src/vehicle_base.h b/src/vehicle_base.h index 8243fdbd59..cddf2d6981 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -367,6 +367,8 @@ public: mutable MutableSpriteCache sprite_cache; ///< Cache of sprites and values related to recalculating them, see #MutableSpriteCache + struct PersistentStorage *psa; ///< Persistent storage + /** * Calculates the weight value that this vehicle will have when fully loaded with its current cargo. * @return Weight value in tonnes.