[Kernel] Store earned achievements in-memory to prevent achievements spam

This doesn't store them externally so after restarting they will unlock again
This commit is contained in:
Gliniak 2023-10-25 09:17:38 +02:00
parent 2509b03b81
commit ebdea6b02a
3 changed files with 36 additions and 3 deletions

View File

@ -22,10 +22,14 @@ DECLARE_int32(user_language);
namespace xe { namespace xe {
namespace kernel { namespace kernel {
AchievementManager::AchievementManager(){}; AchievementManager::AchievementManager() { unlocked_achievements.clear(); };
void AchievementManager::EarnAchievement(uint64_t xuid, uint32_t title_id, void AchievementManager::EarnAchievement(uint64_t xuid, uint32_t title_id,
uint32_t achievement_id) { uint32_t achievement_id) {
if (IsAchievementUnlocked(achievement_id)) {
return;
}
const Emulator* emulator = kernel_state()->emulator(); const Emulator* emulator = kernel_state()->emulator();
ui::WindowedAppContext& app_context = ui::WindowedAppContext& app_context =
kernel_state()->emulator()->display_window()->app_context(); kernel_state()->emulator()->display_window()->app_context();
@ -48,6 +52,7 @@ void AchievementManager::EarnAchievement(uint64_t xuid, uint32_t title_id,
const std::string description = const std::string description =
fmt::format("{}G - {}", entry.gamerscore, label); fmt::format("{}G - {}", entry.gamerscore, label);
unlocked_achievements[achievement_id] = Clock::QueryHostSystemTime();
// Even if we disable popup we still should store info that this // Even if we disable popup we still should store info that this
// achievement was earned. // achievement was earned.
if (!cvars::show_achievement_notification) { if (!cvars::show_achievement_notification) {
@ -63,5 +68,20 @@ void AchievementManager::EarnAchievement(uint64_t xuid, uint32_t title_id,
} }
} }
bool AchievementManager::IsAchievementUnlocked(uint32_t achievement_id) {
auto itr = unlocked_achievements.find(achievement_id);
return itr != unlocked_achievements.cend();
}
uint64_t AchievementManager::GetAchievementUnlockTime(uint32_t achievement_id) {
auto itr = unlocked_achievements.find(achievement_id);
if (itr == unlocked_achievements.cend()) {
return 0;
}
return itr->second;
}
} // namespace kernel } // namespace kernel
} // namespace xe } // namespace xe

View File

@ -10,6 +10,7 @@
#ifndef XENIA_KERNEL_ACHIEVEMENT_MANAGER_H_ #ifndef XENIA_KERNEL_ACHIEVEMENT_MANAGER_H_
#define XENIA_KERNEL_ACHIEVEMENT_MANAGER_H_ #define XENIA_KERNEL_ACHIEVEMENT_MANAGER_H_
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
@ -25,7 +26,11 @@ class AchievementManager {
void EarnAchievement(uint64_t xuid, uint32_t title_id, void EarnAchievement(uint64_t xuid, uint32_t title_id,
uint32_t achievement_id); uint32_t achievement_id);
bool IsAchievementUnlocked(uint32_t achievement_id);
uint64_t GetAchievementUnlockTime(uint32_t achievement_id);
private: private:
std::map<uint32_t, uint64_t> unlocked_achievements;
// void Load(); // void Load();
// void Save(); // void Save();
}; };

View File

@ -728,6 +728,13 @@ dword_result_t XamUserCreateAchievementEnumerator_entry(
db.GetAchievements(); db.GetAchievements();
for (const util::XdbfAchievementTableEntry& entry : achievement_list) { for (const util::XdbfAchievementTableEntry& entry : achievement_list) {
auto is_unlocked =
kernel_state()->achievement_manager()->IsAchievementUnlocked(
entry.id);
auto unlock_time =
kernel_state()->achievement_manager()->GetAchievementUnlockTime(
entry.id);
auto item = XStaticAchievementEnumerator::AchievementDetails{ auto item = XStaticAchievementEnumerator::AchievementDetails{
entry.id, entry.id,
xe::to_utf16(db.GetStringTableEntry(language, entry.label_id)), xe::to_utf16(db.GetStringTableEntry(language, entry.label_id)),
@ -735,8 +742,9 @@ dword_result_t XamUserCreateAchievementEnumerator_entry(
xe::to_utf16(db.GetStringTableEntry(language, entry.unachieved_id)), xe::to_utf16(db.GetStringTableEntry(language, entry.unachieved_id)),
entry.image_id, entry.image_id,
entry.gamerscore, entry.gamerscore,
{0, 0}, (uint32_t)(unlock_time << 31),
entry.flags}; (uint32_t)unlock_time,
is_unlocked ? entry.flags | 0x20000 : entry.flags};
e->AppendItem(item); e->AppendItem(item);
} }