Skip to content

Commit 93fec0b

Browse files
authored
Keep list of PauseOnX assets instead of scanning every frame (#1304)
1 parent ab6ee6c commit 93fec0b

5 files changed

Lines changed: 191 additions & 77 deletions

File tree

src/data/context/GameAssets.cpp

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,107 @@ ra::data::models::AssetCategory GameAssets::MostPublishedAssetCategory() const
105105
return ra::data::models::AssetCategory::None;
106106
}
107107

108+
void GameAssets::OnModelValueChanged(gsl::index nIndex, const BoolModelProperty::ChangeArgs& args)
109+
{
110+
if (args.Property == ra::data::models::AchievementModel::PauseOnResetProperty)
111+
{
112+
const auto nId = GetItemValue(nIndex, ra::data::models::AssetModelBase::IDProperty);
113+
114+
if (!args.tNewValue) // no longer PauseOnReset, remove from watch list
115+
m_vPauseOnResetAchievementIds.erase(nId);
116+
else
117+
m_vPauseOnResetAchievementIds.insert(nId);
118+
}
119+
120+
ra::data::DataModelCollection<ra::data::models::AssetModelBase>::OnModelValueChanged(nIndex, args);
121+
}
122+
123+
void GameAssets::OnModelValueChanged(gsl::index nIndex, const IntModelProperty::ChangeArgs& args)
124+
{
125+
if (args.Property == ra::data::models::LeaderboardModel::PauseOnResetProperty)
126+
{
127+
const auto nId = GetItemValue(nIndex, ra::data::models::AssetModelBase::IDProperty);
128+
129+
if (args.tNewValue == 0) // no longer PauseOnReset, remove from watch list
130+
m_vPauseOnResetLeaderboardIds.erase(nId);
131+
else
132+
m_vPauseOnResetLeaderboardIds.insert(nId);
133+
}
134+
else if (args.Property == ra::data::models::LeaderboardModel::PauseOnTriggerProperty)
135+
{
136+
const auto nId = GetItemValue(nIndex, ra::data::models::AssetModelBase::IDProperty);
137+
138+
if (args.tNewValue == 0) // no longer PauseOnTrigger, remove from watch list
139+
m_vPauseOnTriggerLeaderboardIds.erase(nId);
140+
else
141+
m_vPauseOnTriggerLeaderboardIds.insert(nId);
142+
}
143+
144+
ra::data::DataModelCollection<ra::data::models::AssetModelBase>::OnModelValueChanged(nIndex, args);
145+
}
146+
147+
bool GameAssets::HasPauseOnXAssets() const noexcept
148+
{
149+
return !m_vPauseOnResetAchievementIds.empty() ||
150+
!m_vPauseOnResetLeaderboardIds.empty() ||
151+
!m_vPauseOnTriggerLeaderboardIds.empty();
152+
}
153+
154+
void GameAssets::GetPauseOnResetAchievements(std::vector<const ra::data::models::AchievementModel*>& vAchievements) const
155+
{
156+
for (const auto nId : m_vPauseOnResetAchievementIds)
157+
{
158+
const auto* vmAchievement = FindAchievement(nId);
159+
if (vmAchievement != nullptr)
160+
vAchievements.push_back(vmAchievement);
161+
}
162+
}
163+
164+
void GameAssets::GetPauseOnResetLeaderboards(std::vector<const ra::data::models::LeaderboardModel*>& vLeaderboards) const
165+
{
166+
for (const auto nId : m_vPauseOnResetLeaderboardIds)
167+
{
168+
const auto* vmLeaderboard = FindLeaderboard(nId);
169+
if (vmLeaderboard != nullptr)
170+
vLeaderboards.push_back(vmLeaderboard);
171+
}
172+
}
173+
174+
void GameAssets::GetPauseOnTriggerLeaderboards(std::vector<const ra::data::models::LeaderboardModel*>& vLeaderboards) const
175+
{
176+
for (const auto nId : m_vPauseOnTriggerLeaderboardIds)
177+
{
178+
const auto* vmLeaderboard = FindLeaderboard(nId);
179+
if (vmLeaderboard != nullptr)
180+
vLeaderboards.push_back(vmLeaderboard);
181+
}
182+
}
183+
108184
void GameAssets::OnBeforeItemRemoved(ModelBase& pModel)
109185
{
110-
auto* pLocalBadges = dynamic_cast<ra::data::models::LocalBadgesModel*>(FindAsset(ra::data::models::AssetType::LocalBadges, 0));
111-
if (pLocalBadges)
186+
const auto* pAchievement = dynamic_cast<const ra::data::models::AchievementModel*>(&pModel);
187+
if (pAchievement)
112188
{
113-
const auto* pAchievement = dynamic_cast<const ra::data::models::AchievementModel*>(&pModel);
114-
if (pAchievement && ra::util::String::StartsWith(pAchievement->GetBadge(), L"local\\"))
115-
pLocalBadges->RemoveReference(pAchievement->GetBadge(), pAchievement->IsBadgeCommitted());
189+
if (ra::util::String::StartsWith(pAchievement->GetBadge(), L"local\\"))
190+
{
191+
auto* pLocalBadges = dynamic_cast<ra::data::models::LocalBadgesModel*>(FindAsset(ra::data::models::AssetType::LocalBadges, 0));
192+
if (pLocalBadges)
193+
pLocalBadges->RemoveReference(pAchievement->GetBadge(), pAchievement->IsBadgeCommitted());
194+
}
195+
196+
if (pAchievement->IsPauseOnReset())
197+
m_vPauseOnResetAchievementIds.erase(pAchievement->GetID());
198+
}
199+
else
200+
{
201+
const auto* pLeaderboard = dynamic_cast<const ra::data::models::LeaderboardModel*>(&pModel);
202+
if (pLeaderboard)
203+
{
204+
if (pLeaderboard->GetPauseOnReset() != ra::data::models::LeaderboardModel::LeaderboardParts::None)
205+
m_vPauseOnResetLeaderboardIds.erase(pLeaderboard->GetID());
206+
if (pLeaderboard->GetPauseOnTrigger() != ra::data::models::LeaderboardModel::LeaderboardParts::None)
207+
m_vPauseOnTriggerLeaderboardIds.erase(pLeaderboard->GetID());
208+
}
116209
}
117210

118211
ra::data::DataModelCollection<ra::data::models::AssetModelBase>::OnBeforeItemRemoved(pModel);

src/data/context/GameAssets.hh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,10 +156,24 @@ public:
156156

157157
static constexpr uint32_t LocalSubsetId = 0xFFFFFFFF;
158158

159+
bool HasPauseOnXAssets() const noexcept;
160+
void GetPauseOnResetAchievements(std::vector<const ra::data::models::AchievementModel*>& vAchievements) const;
161+
void GetPauseOnResetLeaderboards(std::vector<const ra::data::models::LeaderboardModel*>& vLeaderboards) const;
162+
void GetPauseOnTriggerLeaderboards(std::vector<const ra::data::models::LeaderboardModel*>& vLeaderboards) const;
163+
159164
protected:
165+
bool IsWatching() const noexcept override { return true; }
166+
167+
void OnModelValueChanged(gsl::index nIndex, const BoolModelProperty::ChangeArgs& args) override;
168+
void OnModelValueChanged(gsl::index nIndex, const IntModelProperty::ChangeArgs& args) override;
169+
160170
void OnBeforeItemRemoved(ModelBase& pModel) override;
161171

162172
uint32_t m_nNextLocalId = FirstLocalId;
173+
174+
std::set<ra::AchievementID> m_vPauseOnResetAchievementIds;
175+
std::set<ra::LeaderboardID> m_vPauseOnResetLeaderboardIds;
176+
std::set<ra::LeaderboardID> m_vPauseOnTriggerLeaderboardIds;
163177
};
164178

165179
} // namespace context

src/services/AchievementRuntime.cpp

Lines changed: 79 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -887,27 +887,6 @@ void AchievementRuntime::UpdateActiveLeaderboards()
887887
}
888888
}
889889

890-
static rc_client_leaderboard_info_t* GetLeaderboardInfo(rc_client_t* pClient, ra::LeaderboardID nId) noexcept
891-
{
892-
if (!pClient || !pClient->game)
893-
return nullptr;
894-
895-
rc_client_subset_info_t* subset = pClient->game->subsets;
896-
for (; subset; subset = subset->next)
897-
{
898-
rc_client_leaderboard_info_t* leaderboard = subset->leaderboards;
899-
const rc_client_leaderboard_info_t* stop = leaderboard + subset->public_.num_leaderboards;
900-
901-
for (; leaderboard < stop; ++leaderboard)
902-
{
903-
if (leaderboard->public_.id == nId)
904-
return leaderboard;
905-
}
906-
}
907-
908-
return nullptr;
909-
}
910-
911890
bool AchievementRuntime::HasRichPresence() const
912891
{
913892
auto* pClient = ra::services::ServiceLocator::Get<ra::context::IRcClient>().GetClient();
@@ -1307,74 +1286,92 @@ void AchievementRuntime::UnloadGame()
13071286

13081287
/* ---- DoFrame ----- */
13091288

1310-
static void PrepareForPauseOnChangeEvents(rc_client_t* pClient,
1311-
std::vector<rc_client_achievement_info_t*>& vAchievementsWithHits,
1312-
std::map<rc_client_leaderboard_info_t*, ra::data::models::LeaderboardModel::LeaderboardParts>& mLeaderboardsWithHits,
1313-
std::map<rc_client_leaderboard_info_t*, ra::data::models::LeaderboardModel::LeaderboardParts>& mActiveLeaderboards)
1289+
static void PrepareForPauseOnReset(const ra::data::context::GameAssets& pAssets,
1290+
std::vector<const rc_client_achievement_info_t*>& vAchievementsWithHits)
13141291
{
1315-
auto& pGameContext = ra::services::ServiceLocator::GetMutable<ra::data::context::GameContext>();
1316-
for (auto& vmAsset : pGameContext.Assets())
1292+
std::vector<const ra::data::models::AchievementModel*> vAchievements;
1293+
pAssets.GetPauseOnResetAchievements(vAchievements);
1294+
1295+
for (const auto* vmAchievement : vAchievements)
13171296
{
1318-
const auto* vmAchievement = dynamic_cast<ra::data::models::AchievementModel*>(&vmAsset);
1319-
if (vmAchievement != nullptr)
1297+
if (vmAchievement && vmAchievement->IsActive())
13201298
{
1321-
if (vmAchievement->IsPauseOnReset())
1322-
{
1323-
auto* pAchievement = GetAchievementInfo(pClient, vmAchievement->GetID());
1324-
if (pAchievement && pAchievement->trigger && pAchievement->trigger->has_hits)
1325-
vAchievementsWithHits.push_back(pAchievement);
1326-
}
1327-
1328-
continue;
1299+
const auto* pAchievement = vmAchievement->GetRuntimeTrigger();
1300+
if (pAchievement != nullptr && pAchievement->has_hits)
1301+
vAchievementsWithHits.push_back(vmAchievement->GetRuntimeAchievementInfo());
13291302
}
1303+
}
1304+
}
13301305

1331-
const auto* vmLeaderboard = dynamic_cast<ra::data::models::LeaderboardModel*>(&vmAsset);
1332-
if (vmLeaderboard != nullptr)
1333-
{
1334-
using namespace ra::bitwise_ops;
1306+
static void PrepareForPauseOnReset(const ra::data::context::GameAssets& pAssets,
1307+
std::map<const rc_client_leaderboard_info_t*, ra::data::models::LeaderboardModel::LeaderboardParts>& mLeaderboardsWithHits)
1308+
{
1309+
std::vector<const ra::data::models::LeaderboardModel*> vLeaderboards;
1310+
pAssets.GetPauseOnResetLeaderboards(vLeaderboards);
13351311

1336-
auto nPauseOnReset = vmLeaderboard->GetPauseOnReset();
1337-
if (nPauseOnReset != ra::data::models::LeaderboardModel::LeaderboardParts::None)
1312+
for (const auto* vmLeaderboard : vLeaderboards)
1313+
{
1314+
if (vmLeaderboard && vmLeaderboard->IsActive())
1315+
{
1316+
const auto* pLeaderboard = vmLeaderboard->GetRuntimeLeaderboard();
1317+
if (pLeaderboard != nullptr)
13381318
{
1339-
auto* pLeaderboard = GetLeaderboardInfo(pClient, vmLeaderboard->GetID());
1340-
if (pLeaderboard && pLeaderboard->lboard)
1319+
auto nPauseOnReset = vmLeaderboard->GetPauseOnReset();
1320+
if (nPauseOnReset != ra::data::models::LeaderboardModel::LeaderboardParts::None)
13411321
{
1342-
if (!pLeaderboard->lboard->start.has_hits)
1322+
using namespace ra::bitwise_ops;
1323+
1324+
if (!pLeaderboard->start.has_hits)
13431325
nPauseOnReset &= ~ra::data::models::LeaderboardModel::LeaderboardParts::Start;
1344-
if (!pLeaderboard->lboard->cancel.has_hits)
1326+
if (!pLeaderboard->cancel.has_hits)
13451327
nPauseOnReset &= ~ra::data::models::LeaderboardModel::LeaderboardParts::Cancel;
1346-
if (!pLeaderboard->lboard->submit.has_hits)
1328+
if (!pLeaderboard->submit.has_hits)
13471329
nPauseOnReset &= ~ra::data::models::LeaderboardModel::LeaderboardParts::Submit;
1348-
if (!pLeaderboard->lboard->value.value.value)
1330+
if (!pLeaderboard->value.value.value)
13491331
nPauseOnReset &= ~ra::data::models::LeaderboardModel::LeaderboardParts::Value;
13501332

13511333
if (nPauseOnReset != ra::data::models::LeaderboardModel::LeaderboardParts::None)
1352-
mLeaderboardsWithHits[pLeaderboard] = nPauseOnReset;
1334+
mLeaderboardsWithHits[vmLeaderboard->GetRuntimeLeaderboardInfo()] = nPauseOnReset;
13531335
}
13541336
}
1337+
}
1338+
}
1339+
}
13551340

1356-
auto nPauseOnTrigger = vmLeaderboard->GetPauseOnTrigger();
1357-
if (nPauseOnTrigger != ra::data::models::LeaderboardModel::LeaderboardParts::None)
1341+
static void PrepareForPauseOnTrigger(const ra::data::context::GameAssets& pAssets,
1342+
std::map<const rc_client_leaderboard_info_t*, ra::data::models::LeaderboardModel::LeaderboardParts>& mActiveLeaderboards)
1343+
{
1344+
std::vector<const ra::data::models::LeaderboardModel*> vLeaderboards;
1345+
pAssets.GetPauseOnTriggerLeaderboards(vLeaderboards);
1346+
1347+
for (const auto* vmLeaderboard : vLeaderboards)
1348+
{
1349+
if (vmLeaderboard && vmLeaderboard->IsActive())
1350+
{
1351+
const auto* pLeaderboard = vmLeaderboard->GetRuntimeLeaderboard();
1352+
if (pLeaderboard != nullptr)
13581353
{
1359-
auto* pLeaderboard = GetLeaderboardInfo(pClient, vmLeaderboard->GetID());
1360-
if (pLeaderboard && pLeaderboard->lboard)
1354+
auto nPauseOnTrigger = vmLeaderboard->GetPauseOnTrigger();
1355+
if (nPauseOnTrigger != ra::data::models::LeaderboardModel::LeaderboardParts::None)
13611356
{
1362-
if (pLeaderboard->lboard->start.state == RC_TRIGGER_STATE_TRIGGERED)
1357+
using namespace ra::bitwise_ops;
1358+
1359+
if (pLeaderboard->start.state == RC_TRIGGER_STATE_TRIGGERED)
13631360
nPauseOnTrigger &= ~ra::data::models::LeaderboardModel::LeaderboardParts::Start;
1364-
if (pLeaderboard->lboard->cancel.state == RC_TRIGGER_STATE_TRIGGERED)
1361+
if (pLeaderboard->cancel.state == RC_TRIGGER_STATE_TRIGGERED)
13651362
nPauseOnTrigger &= ~ra::data::models::LeaderboardModel::LeaderboardParts::Cancel;
1366-
if (pLeaderboard->lboard->submit.state == RC_TRIGGER_STATE_TRIGGERED)
1363+
if (pLeaderboard->submit.state == RC_TRIGGER_STATE_TRIGGERED)
13671364
nPauseOnTrigger &= ~ra::data::models::LeaderboardModel::LeaderboardParts::Submit;
13681365

13691366
if (nPauseOnTrigger != ra::data::models::LeaderboardModel::LeaderboardParts::None)
1370-
mActiveLeaderboards[pLeaderboard] = nPauseOnTrigger;
1367+
mActiveLeaderboards[vmLeaderboard->GetRuntimeLeaderboardInfo()] = nPauseOnTrigger;
13711368
}
13721369
}
13731370
}
13741371
}
13751372
}
13761373

1377-
static void RaisePauseOnChangeEvents(std::vector<rc_client_achievement_info_t*>& vAchievementsWithHits)
1374+
static void RaisePauseOnChangeEvents(std::vector<const rc_client_achievement_info_t*>& vAchievementsWithHits)
13781375
{
13791376
for (const auto* pAchievement : vAchievementsWithHits)
13801377
{
@@ -1387,8 +1384,7 @@ static void RaisePauseOnChangeEvents(std::vector<rc_client_achievement_info_t*>&
13871384
}
13881385

13891386
static void RaisePauseOnChangeEvents(
1390-
std::map<rc_client_leaderboard_info_t*, ra::data::models::LeaderboardModel::LeaderboardParts>& mLeaderboardsWithHits,
1391-
std::map<rc_client_leaderboard_info_t*, ra::data::models::LeaderboardModel::LeaderboardParts>& mActiveLeaderboards)
1387+
std::map<const rc_client_leaderboard_info_t*, ra::data::models::LeaderboardModel::LeaderboardParts>& mLeaderboardsWithHits)
13921388
{
13931389
for (auto pair : mLeaderboardsWithHits)
13941390
{
@@ -1437,7 +1433,11 @@ static void RaisePauseOnChangeEvents(
14371433
}
14381434
}
14391435
}
1436+
}
14401437

1438+
static void RaisePauseOnTriggerEvents(
1439+
std::map<const rc_client_leaderboard_info_t*, ra::data::models::LeaderboardModel::LeaderboardParts>& mActiveLeaderboards)
1440+
{
14411441
for (auto pair : mActiveLeaderboards)
14421442
{
14431443
if (pair.first && pair.first->lboard)
@@ -1491,18 +1491,30 @@ void AchievementRuntime::DoFrame()
14911491
return;
14921492
}
14931493

1494-
std::vector<rc_client_achievement_info_t*> vAchievementsWithHits;
1495-
std::map<rc_client_leaderboard_info_t*, ra::data::models::LeaderboardModel::LeaderboardParts> mLeaderboardsWithHits;
1496-
std::map<rc_client_leaderboard_info_t*, ra::data::models::LeaderboardModel::LeaderboardParts> mActiveLeaderboards;
1494+
const auto& pAssets = ra::services::ServiceLocator::GetMutable<ra::data::context::GameContext>().Assets();
1495+
if (!pAssets.HasPauseOnXAssets())
1496+
{
1497+
rc_client_do_frame(pClient);
1498+
return;
1499+
}
1500+
1501+
std::vector<const rc_client_achievement_info_t*> vAchievementsWithHits;
1502+
PrepareForPauseOnReset(pAssets, vAchievementsWithHits);
1503+
1504+
std::map<const rc_client_leaderboard_info_t*, ra::data::models::LeaderboardModel::LeaderboardParts> mLeaderboardsWithHits;
1505+
PrepareForPauseOnReset(pAssets, mLeaderboardsWithHits);
14971506

1498-
PrepareForPauseOnChangeEvents(pClient, vAchievementsWithHits, mLeaderboardsWithHits, mActiveLeaderboards);
1507+
std::map<const rc_client_leaderboard_info_t*, ra::data::models::LeaderboardModel::LeaderboardParts> mActiveLeaderboards;
1508+
PrepareForPauseOnTrigger(pAssets, mActiveLeaderboards);
14991509

15001510
rc_client_do_frame(pClient);
15011511

15021512
if (!vAchievementsWithHits.empty())
15031513
RaisePauseOnChangeEvents(vAchievementsWithHits);
1504-
if (!mLeaderboardsWithHits.empty() || !mActiveLeaderboards.empty())
1505-
RaisePauseOnChangeEvents(mLeaderboardsWithHits, mActiveLeaderboards);
1514+
if (!mLeaderboardsWithHits.empty())
1515+
RaisePauseOnChangeEvents(mLeaderboardsWithHits);
1516+
if (!mActiveLeaderboards.empty())
1517+
RaisePauseOnTriggerEvents(mActiveLeaderboards);
15061518
}
15071519

15081520
void AchievementRuntime::Idle() const

src/services/AchievementRuntime.hh

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
#include "data\Types.hh"
66
#include "data\context\EmulatorContext.hh"
77
#include "data\models\AchievementModel.hh"
8-
#include "data\models\LeaderboardModel.hh"
9-
10-
#include "services\TextReader.hh"
118

129
#include <string>
1310

tests/services/AchievementRuntime_Tests.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#include "tests\devkit\context\mocks\MockUserContext.hh"
99
#include "tests\devkit\services\mocks\MockClock.hh"
1010
#include "tests\devkit\services\mocks\MockFileSystem.hh"
11-
#include "tests\devkit\services\mocks\MockHttpRequester.hh"
1211
#include "tests\devkit\services\mocks\MockThreadPool.hh"
1312
#include "tests\devkit\testutil\AssetAsserts.hh"
1413
#include "tests\mocks\MockAudioSystem.hh"
@@ -32,7 +31,6 @@
3231
#include "context\IRcClient.hh"
3332
#include "services\impl\OfflineRcClient.hh"
3433

35-
#include <rcheevos\src\rapi\rc_api_common.h>
3634
#include <rcheevos\src\rc_client_internal.h>
3735
#include <rcheevos\src\rcheevos\rc_internal.h>
3836

0 commit comments

Comments
 (0)