mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Do not use a mutable global to return calculated VarAction2 results.
parent
e90b68d504
commit
d030d17bd6
|
@ -998,14 +998,14 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* virtual */ const SpriteGroup *VehicleResolverObject::ResolveReal(const RealSpriteGroup &group) const
|
/* virtual */ ResolverResult VehicleResolverObject::ResolveReal(const RealSpriteGroup &group) const
|
||||||
{
|
{
|
||||||
const Vehicle *v = this->self_scope.v;
|
const Vehicle *v = this->self_scope.v;
|
||||||
|
|
||||||
if (v == nullptr) {
|
if (v == nullptr) {
|
||||||
if (!group.loading.empty()) return group.loading[0];
|
if (!group.loading.empty()) return group.loading[0];
|
||||||
if (!group.loaded.empty()) return group.loaded[0];
|
if (!group.loaded.empty()) return group.loaded[0];
|
||||||
return nullptr;
|
return std::monostate{};
|
||||||
}
|
}
|
||||||
|
|
||||||
const Order &order = v->First()->current_order;
|
const Order &order = v->First()->current_order;
|
||||||
|
@ -1014,7 +1014,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
|
||||||
|
|
||||||
uint totalsets = static_cast<uint>(in_motion ? group.loaded.size() : group.loading.size());
|
uint totalsets = static_cast<uint>(in_motion ? group.loaded.size() : group.loading.size());
|
||||||
|
|
||||||
if (totalsets == 0) return nullptr;
|
if (totalsets == 0) return std::monostate{};
|
||||||
|
|
||||||
uint set = (v->cargo.StoredCount() * totalsets) / std::max<uint16_t>(1u, v->cargo_cap);
|
uint set = (v->cargo.StoredCount() * totalsets) / std::max<uint16_t>(1u, v->cargo_cap);
|
||||||
set = std::min(set, totalsets - 1);
|
set = std::min(set, totalsets - 1);
|
||||||
|
|
|
@ -64,7 +64,7 @@ struct VehicleResolverObject : public SpecializedResolverObject<VehicleRandomTri
|
||||||
|
|
||||||
ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, uint8_t relative = 0) override;
|
ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, uint8_t relative = 0) override;
|
||||||
|
|
||||||
const SpriteGroup *ResolveReal(const RealSpriteGroup &group) const override;
|
ResolverResult ResolveReal(const RealSpriteGroup &group) const override;
|
||||||
|
|
||||||
GrfSpecFeature GetFeature() const override;
|
GrfSpecFeature GetFeature() const override;
|
||||||
uint32_t GetDebugID() const override;
|
uint32_t GetDebugID() const override;
|
||||||
|
|
|
@ -60,20 +60,28 @@ void NewGRFProfiler::BeginResolve(const ResolverObject &resolver)
|
||||||
/**
|
/**
|
||||||
* Capture the completion of a sprite group resolution.
|
* Capture the completion of a sprite group resolution.
|
||||||
*/
|
*/
|
||||||
void NewGRFProfiler::EndResolve(const SpriteGroup *result)
|
void NewGRFProfiler::EndResolve(const ResolverResult &result)
|
||||||
{
|
{
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
this->cur_call.time = (uint32_t)time_point_cast<microseconds>(high_resolution_clock::now()).time_since_epoch().count() - this->cur_call.time;
|
this->cur_call.time = (uint32_t)time_point_cast<microseconds>(high_resolution_clock::now()).time_since_epoch().count() - this->cur_call.time;
|
||||||
|
|
||||||
if (result == nullptr) {
|
struct visitor {
|
||||||
this->cur_call.result = 0;
|
uint32_t operator()(std::monostate)
|
||||||
} else if (result->type == SGT_CALLBACK) {
|
{
|
||||||
this->cur_call.result = static_cast<const CallbackResultSpriteGroup *>(result)->result;
|
return 0;
|
||||||
} else if (result->type == SGT_RESULT) {
|
|
||||||
this->cur_call.result = GetSpriteLocalID(static_cast<const ResultSpriteGroup *>(result)->sprite);
|
|
||||||
} else {
|
|
||||||
this->cur_call.result = result->nfo_line;
|
|
||||||
}
|
}
|
||||||
|
uint32_t operator()(CallbackResult cb_result)
|
||||||
|
{
|
||||||
|
return cb_result;
|
||||||
|
}
|
||||||
|
uint32_t operator()(const SpriteGroup *group)
|
||||||
|
{
|
||||||
|
if (group == nullptr) return 0;
|
||||||
|
if (group->type != SGT_RESULT) return group->nfo_line;
|
||||||
|
return GetSpriteLocalID(static_cast<const ResultSpriteGroup *>(group)->sprite);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this->cur_call.result = std::visit(visitor{}, result);
|
||||||
|
|
||||||
this->calls.push_back(this->cur_call);
|
this->calls.push_back(this->cur_call);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ struct NewGRFProfiler {
|
||||||
~NewGRFProfiler();
|
~NewGRFProfiler();
|
||||||
|
|
||||||
void BeginResolve(const ResolverObject &resolver);
|
void BeginResolve(const ResolverObject &resolver);
|
||||||
void EndResolve(const SpriteGroup *result);
|
void EndResolve(const ResolverResult &result);
|
||||||
void RecursiveResolve();
|
void RecursiveResolve();
|
||||||
|
|
||||||
void Start();
|
void Start();
|
||||||
|
|
|
@ -31,9 +31,9 @@ TemporaryStorageArray<int32_t, 0x110> _temp_store;
|
||||||
* @param top_level true if this is a top-level SpriteGroup, false if used nested in another SpriteGroup.
|
* @param top_level true if this is a top-level SpriteGroup, false if used nested in another SpriteGroup.
|
||||||
* @return the resolved group
|
* @return the resolved group
|
||||||
*/
|
*/
|
||||||
/* static */ const SpriteGroup *SpriteGroup::Resolve(const SpriteGroup *group, ResolverObject &object, bool top_level)
|
/* static */ ResolverResult SpriteGroup::Resolve(const SpriteGroup *group, ResolverObject &object, bool top_level)
|
||||||
{
|
{
|
||||||
if (group == nullptr) return nullptr;
|
if (group == nullptr) return std::monostate{};
|
||||||
|
|
||||||
const GRFFile *grf = object.grffile;
|
const GRFFile *grf = object.grffile;
|
||||||
auto profiler = std::ranges::find(_newgrf_profilers, grf, &NewGRFProfiler::grffile);
|
auto profiler = std::ranges::find(_newgrf_profilers, grf, &NewGRFProfiler::grffile);
|
||||||
|
@ -44,7 +44,7 @@ TemporaryStorageArray<int32_t, 0x110> _temp_store;
|
||||||
} else if (top_level) {
|
} else if (top_level) {
|
||||||
profiler->BeginResolve(object);
|
profiler->BeginResolve(object);
|
||||||
_temp_store.ClearChanges();
|
_temp_store.ClearChanges();
|
||||||
const SpriteGroup *result = group->Resolve(object);
|
auto result = group->Resolve(object);
|
||||||
profiler->EndResolve(result);
|
profiler->EndResolve(result);
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
|
@ -120,12 +120,12 @@ static inline uint32_t GetVariable(const ResolverObject &object, ScopeResolver *
|
||||||
* @param group Group to get.
|
* @param group Group to get.
|
||||||
* @return The available sprite group.
|
* @return The available sprite group.
|
||||||
*/
|
*/
|
||||||
/* virtual */ const SpriteGroup *ResolverObject::ResolveReal(const RealSpriteGroup &group) const
|
/* virtual */ ResolverResult ResolverObject::ResolveReal(const RealSpriteGroup &group) const
|
||||||
{
|
{
|
||||||
if (!group.loaded.empty()) return group.loaded[0];
|
if (!group.loaded.empty()) return group.loaded[0];
|
||||||
if (!group.loading.empty()) return group.loading[0];
|
if (!group.loading.empty()) return group.loading[0];
|
||||||
|
|
||||||
return nullptr;
|
return std::monostate{};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -185,7 +185,7 @@ static bool RangeHighComparator(const DeterministicSpriteGroupRange &range, uint
|
||||||
return range.high < value;
|
return range.high < value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) const
|
/* virtual */ ResolverResult DeterministicSpriteGroup::Resolve(ResolverObject &object) const
|
||||||
{
|
{
|
||||||
uint32_t last_value = 0;
|
uint32_t last_value = 0;
|
||||||
uint32_t value = 0;
|
uint32_t value = 0;
|
||||||
|
@ -196,13 +196,9 @@ const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) con
|
||||||
/* Try to get the variable. We shall assume it is available, unless told otherwise. */
|
/* Try to get the variable. We shall assume it is available, unless told otherwise. */
|
||||||
bool available = true;
|
bool available = true;
|
||||||
if (adjust.variable == 0x7E) {
|
if (adjust.variable == 0x7E) {
|
||||||
const SpriteGroup *subgroup = SpriteGroup::Resolve(adjust.subroutine, object, false);
|
auto subgroup = SpriteGroup::Resolve(adjust.subroutine, object, false);
|
||||||
if (subgroup == nullptr) {
|
auto *subvalue = std::get_if<CallbackResult>(&subgroup);
|
||||||
value = UINT16_MAX;
|
value = subvalue != nullptr ? *subvalue : UINT16_MAX;
|
||||||
} else {
|
|
||||||
value = subgroup->GetCallbackResult();
|
|
||||||
if (value == CALLBACK_FAILED) value = UINT16_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Note: 'last_value' and 'reseed' are shared between the main chain and the procedure */
|
/* Note: 'last_value' and 'reseed' are shared between the main chain and the procedure */
|
||||||
} else if (adjust.variable == 0x7B) {
|
} else if (adjust.variable == 0x7B) {
|
||||||
|
@ -230,9 +226,7 @@ const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) con
|
||||||
|
|
||||||
if (this->calculated_result) {
|
if (this->calculated_result) {
|
||||||
/* nvar == 0 is a special case -- we turn our value into a callback result */
|
/* nvar == 0 is a special case -- we turn our value into a callback result */
|
||||||
static CallbackResultSpriteGroup nvarzero(0);
|
return static_cast<CallbackResult>(GB(value, 0, 15));
|
||||||
nvarzero.result = GB(value, 0, 15);
|
|
||||||
return &nvarzero;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->ranges.size() > 4) {
|
if (this->ranges.size() > 4) {
|
||||||
|
@ -253,7 +247,7 @@ const SpriteGroup *DeterministicSpriteGroup::Resolve(ResolverObject &object) con
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const SpriteGroup *RandomizedSpriteGroup::Resolve(ResolverObject &object) const
|
/* virtual */ ResolverResult RandomizedSpriteGroup::Resolve(ResolverObject &object) const
|
||||||
{
|
{
|
||||||
ScopeResolver *scope = object.GetScope(this->var_scope, this->count);
|
ScopeResolver *scope = object.GetScope(this->var_scope, this->count);
|
||||||
if (object.callback == CBID_RANDOM_TRIGGER) {
|
if (object.callback == CBID_RANDOM_TRIGGER) {
|
||||||
|
@ -273,8 +267,12 @@ const SpriteGroup *RandomizedSpriteGroup::Resolve(ResolverObject &object) const
|
||||||
return SpriteGroup::Resolve(this->groups[index], object, false);
|
return SpriteGroup::Resolve(this->groups[index], object, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* virtual */ ResolverResult CallbackResultSpriteGroup::Resolve(ResolverObject &) const
|
||||||
|
{
|
||||||
|
return this->result;
|
||||||
|
}
|
||||||
|
|
||||||
const SpriteGroup *RealSpriteGroup::Resolve(ResolverObject &object) const
|
/* virtual */ ResolverResult RealSpriteGroup::Resolve(ResolverObject &object) const
|
||||||
{
|
{
|
||||||
return object.ResolveReal(*this);
|
return object.ResolveReal(*this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,15 @@ enum SpriteGroupType : uint8_t {
|
||||||
|
|
||||||
struct SpriteGroup;
|
struct SpriteGroup;
|
||||||
struct ResolverObject;
|
struct ResolverObject;
|
||||||
|
using CallbackResult = uint16_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result of resolving sprite groups:
|
||||||
|
* - std::monostate: Failure.
|
||||||
|
* - CallbackResult: Callback result.
|
||||||
|
* - SpriteGroup: ResultSpriteGroup, TileLayoutSpriteGroup, IndustryProductionSpriteGroup
|
||||||
|
*/
|
||||||
|
using ResolverResult = std::variant<std::monostate, CallbackResult, const SpriteGroup *>;
|
||||||
|
|
||||||
/* SPRITE_WIDTH is 24. ECS has roughly 30 sprite groups per real sprite.
|
/* SPRITE_WIDTH is 24. ECS has roughly 30 sprite groups per real sprite.
|
||||||
* Adding an 'extra' margin would be assuming 64 sprite groups per real
|
* Adding an 'extra' margin would be assuming 64 sprite groups per real
|
||||||
|
@ -59,7 +68,7 @@ struct SpriteGroup : SpriteGroupPool::PoolItem<&_spritegroup_pool> {
|
||||||
protected:
|
protected:
|
||||||
SpriteGroup(SpriteGroupType type) : type(type) {}
|
SpriteGroup(SpriteGroupType type) : type(type) {}
|
||||||
/** Base sprite group resolver */
|
/** Base sprite group resolver */
|
||||||
virtual const SpriteGroup *Resolve([[maybe_unused]] ResolverObject &object) const { return this; };
|
virtual ResolverResult Resolve([[maybe_unused]] ResolverObject &object) const { return this; };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~SpriteGroup() = default;
|
virtual ~SpriteGroup() = default;
|
||||||
|
@ -67,9 +76,7 @@ public:
|
||||||
uint32_t nfo_line = 0;
|
uint32_t nfo_line = 0;
|
||||||
SpriteGroupType type{};
|
SpriteGroupType type{};
|
||||||
|
|
||||||
virtual uint16_t GetCallbackResult() const { return CALLBACK_FAILED; }
|
static ResolverResult Resolve(const SpriteGroup *group, ResolverObject &object, bool top_level = true);
|
||||||
|
|
||||||
static const SpriteGroup *Resolve(const SpriteGroup *group, ResolverObject &object, bool top_level = true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,7 +96,7 @@ struct RealSpriteGroup : SpriteGroup {
|
||||||
std::vector<const SpriteGroup *> loading{}; ///< List of loading groups (can be SpriteIDs or Callback results)
|
std::vector<const SpriteGroup *> loading{}; ///< List of loading groups (can be SpriteIDs or Callback results)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const SpriteGroup *Resolve(ResolverObject &object) const override;
|
ResolverResult Resolve(ResolverObject &object) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Shared by deterministic and random groups. */
|
/* Shared by deterministic and random groups. */
|
||||||
|
@ -178,7 +185,7 @@ struct DeterministicSpriteGroup : SpriteGroup {
|
||||||
const SpriteGroup *error_group = nullptr; // was first range, before sorting ranges
|
const SpriteGroup *error_group = nullptr; // was first range, before sorting ranges
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const SpriteGroup *Resolve(ResolverObject &object) const override;
|
ResolverResult Resolve(ResolverObject &object) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RandomizedSpriteGroupCompareMode : uint8_t {
|
enum RandomizedSpriteGroupCompareMode : uint8_t {
|
||||||
|
@ -200,7 +207,7 @@ struct RandomizedSpriteGroup : SpriteGroup {
|
||||||
std::vector<const SpriteGroup *> groups{}; ///< Take the group with appropriate index:
|
std::vector<const SpriteGroup *> groups{}; ///< Take the group with appropriate index:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const SpriteGroup *Resolve(ResolverObject &object) const override;
|
ResolverResult Resolve(ResolverObject &object) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -211,10 +218,12 @@ struct CallbackResultSpriteGroup : SpriteGroup {
|
||||||
* Creates a spritegroup representing a callback result
|
* Creates a spritegroup representing a callback result
|
||||||
* @param value The value that was used to represent this callback result
|
* @param value The value that was used to represent this callback result
|
||||||
*/
|
*/
|
||||||
explicit CallbackResultSpriteGroup(uint16_t value) : SpriteGroup(SGT_CALLBACK), result(value) {}
|
explicit CallbackResultSpriteGroup(CallbackResult value) : SpriteGroup(SGT_CALLBACK), result(value) {}
|
||||||
|
|
||||||
uint16_t result = 0;
|
CallbackResult result = 0;
|
||||||
uint16_t GetCallbackResult() const override { return this->result; }
|
|
||||||
|
protected:
|
||||||
|
ResolverResult Resolve(ResolverObject &object) const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -311,7 +320,7 @@ struct ResolverObject {
|
||||||
|
|
||||||
virtual ~ResolverObject() = default;
|
virtual ~ResolverObject() = default;
|
||||||
|
|
||||||
const SpriteGroup *DoResolve()
|
ResolverResult DoResolve()
|
||||||
{
|
{
|
||||||
return SpriteGroup::Resolve(this->root_spritegroup, *this);
|
return SpriteGroup::Resolve(this->root_spritegroup, *this);
|
||||||
}
|
}
|
||||||
|
@ -342,8 +351,9 @@ public:
|
||||||
inline const TSpriteGroup *Resolve()
|
inline const TSpriteGroup *Resolve()
|
||||||
{
|
{
|
||||||
auto result = this->DoResolve();
|
auto result = this->DoResolve();
|
||||||
if (result == nullptr || result->type != TSpriteGroup::TYPE) return nullptr;
|
const auto *group = std::get_if<const SpriteGroup *>(&result);
|
||||||
return static_cast<const TSpriteGroup *>(result);
|
if (group == nullptr || *group == nullptr || (*group)->type != TSpriteGroup::TYPE) return nullptr;
|
||||||
|
return static_cast<const TSpriteGroup *>(*group);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -364,13 +374,14 @@ public:
|
||||||
* Resolve callback.
|
* Resolve callback.
|
||||||
* @return Callback result.
|
* @return Callback result.
|
||||||
*/
|
*/
|
||||||
inline uint16_t ResolveCallback()
|
inline CallbackResult ResolveCallback()
|
||||||
{
|
{
|
||||||
const SpriteGroup *result = this->DoResolve();
|
auto result = this->DoResolve();
|
||||||
return result != nullptr ? result->GetCallbackResult() : CALLBACK_FAILED;
|
const auto *value = std::get_if<CallbackResult>(&result);
|
||||||
|
return value != nullptr ? *value : CALLBACK_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual const SpriteGroup *ResolveReal(const RealSpriteGroup &group) const;
|
virtual ResolverResult ResolveReal(const RealSpriteGroup &group) const;
|
||||||
|
|
||||||
virtual ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, uint8_t relative = 0);
|
virtual ScopeResolver *GetScope(VarSpriteGroupScope scope = VSG_SCOPE_SELF, uint8_t relative = 0);
|
||||||
|
|
||||||
|
|
|
@ -519,11 +519,11 @@ uint32_t Waypoint::GetNewGRFVariable(const ResolverObject &, uint8_t variable, [
|
||||||
return UINT_MAX;
|
return UINT_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual */ const SpriteGroup *StationResolverObject::ResolveReal(const RealSpriteGroup &group) const
|
/* virtual */ ResolverResult StationResolverObject::ResolveReal(const RealSpriteGroup &group) const
|
||||||
{
|
{
|
||||||
if (this->station_scope.st == nullptr || !Station::IsExpected(this->station_scope.st)) {
|
if (this->station_scope.st == nullptr || !Station::IsExpected(this->station_scope.st)) {
|
||||||
if (!group.loading.empty()) return group.loading[0];
|
if (!group.loading.empty()) return group.loading[0];
|
||||||
return nullptr;
|
return std::monostate{};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint cargo = 0;
|
uint cargo = 0;
|
||||||
|
@ -566,7 +566,7 @@ uint32_t Waypoint::GetNewGRFVariable(const ResolverObject &, uint8_t variable, [
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!group.loading.empty()) return group.loading[0];
|
if (!group.loading.empty()) return group.loading[0];
|
||||||
return nullptr;
|
return std::monostate{};
|
||||||
}
|
}
|
||||||
|
|
||||||
GrfSpecFeature StationResolverObject::GetFeature() const
|
GrfSpecFeature StationResolverObject::GetFeature() const
|
||||||
|
|
|
@ -75,7 +75,7 @@ struct StationResolverObject : public SpecializedResolverObject<StationRandomTri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SpriteGroup *ResolveReal(const RealSpriteGroup &group) const override;
|
ResolverResult ResolveReal(const RealSpriteGroup &group) const override;
|
||||||
|
|
||||||
GrfSpecFeature GetFeature() const override;
|
GrfSpecFeature GetFeature() const override;
|
||||||
uint32_t GetDebugID() const override;
|
uint32_t GetDebugID() const override;
|
||||||
|
|
Loading…
Reference in New Issue