The player_index field in question is ultimately what gets used to determine which ranks get displayed in the leaderboards chart, and because this was missing the chart was simply displaying the top four results no matter what.
The cause of the leaderboard spam was primarily this call where if there was an attempt to get leaderboard info and there wasn't already, there would be a fetch request. This is bad for many reasons: some games have hundreds of boards that will be fetched at startup, if there's simply no data to populate that board, this will just continue to fetch every time the dialog needs to update. To mitigate this, I simply don't load leaderboard information until there are events for that leaderboard - less information for the player, sadly, but heavily cuts down on the number of leaderboard fetches.
Now that we have some test data, it wasn't showing up in the leaderboards tab; this fixes it to ensure (1) that the right ID is being passed to UpdateRow and (2) the map of leaderboard entries is being populated correctly.
Currently we're showing OSD messages for unknown patches in known INI
files, but not for unknown patches in unknown INI files. I don't think
this distinction makes much sense to the user. If there's a patch the
user can't use, they probably want to be aware of that fact.
0c14b0c8a7 made Dolphin load a file from
the Sys folder the first time AchievementManager::GetInstance() is
called. Because Android calls AchievementManager::GetInstance() from
setBackgroundExecutionAllowedNative, this had two negative consequences
on Android:
1. The first time setBackgroundExecutionAllowedNative gets called is
often before directory initialization is done. Getting the path of
the Sys folder before directory initialization is done causes a crash.
2. setBackgroundExecutionAllowedNative is called from the GUI thread,
and we don't want file I/O on the GUI thread for performance reasons.
This change makes us load the data from the Sys folder the first time
the data is needed instead. This also saves us from having to load the
data at all when hardcore mode is inactive.
We mustn't use m_system when it is nullptr. This was causing Dolphin to
crash on Android whenever an activity was recreated or resumed while
emulation is running, which is super common.
Prototype of a system to whitelist known game patches that are allowed to be used while RetroAchievements Hardcore mode is active. ApprovedInis.txt contains known hashes for the ini files as they appear in the repo, and can be compared to the local versions of these files to ensure they have not been edited locally by the player. ApprovedInis.txt is hashed and verified similarly first, with its hash residing as a const string within AchievementManager.h, ensuring ApprovedInis and the hashes within cannot be modified without editing Dolphin's source code and recompiling completely.
The challenge popups have proven to be excessive and are no longer useful thanks to the achievements hotkey. Instead, those events will ask for an immediate RP-level update to the achievements dialog, which will among other things re-sort the dialog to show challenges on top faster.
There are two pieces of functionality to be added here. One, we want to disallow pausing too frequently, as it may be used as an artificial slowdown. This is handled within the client, which can tell us if a pause is allowed. Two, we want to call rc_client_idle on a periodic basis so the connection with the server can be maintained even while the emulator is paused.
rc_client calls the provided memory peeker asynchronously in the callback for starting a session, to validate/invalidate the memory used for achievements. Dolphin cannot access memory from any thread but host or CPU so this access has a small chance of being invalid. This commit adds a MemoryVerifier that the AchievementManager will use to perform this, before changing the peek method back to the original MemoryPeeker for normal operation.
If an icon is displayed on screen before it downloads, it was displaying a default icon but it would fail to load the actual icon even after it was downloaded. This fixes that.
Add a two second timer to Achievement Progress Indicators to wait until two seconds after the previous message (when it should have decayed out automatically) before posting any new ones.
AchievementManager maintains a unique pointer to a copy of the current volume so it can asynchronously hash that volume. It is not needed otherwise, so I can release that pointer when hashing is complete. This change fixes a bug whereby changing discs in a game and then changing to a different game would result in the loaded volume pointer still being loaded with and hashing to the previous game.
The names attached to the BadgeStatus object are obsolete and unneeded and are removed from everything that uses them. All BadgeStatus references are updated to just Badge.
The defaults get loaded in by Dolphin at emulator start, and are used if the badge that would normally be displayed has not for whatever reason been downloaded yet. Badges attached to this PR are placeholders (MayIMilae is designing permanent badges) and reside in Sys\Load\RetroAchievements.
Achievement badges/icons are refactored into the type CustomTextureData::ArraySlice::Level as that is the data type images loaded from the filesystem will be. This includes everything that uses the badges in the Qt UI and OnScreenDisplay, and similarly removes the OSD::Icon type because Level already contains that information.
Was informed by the RetroAchievements team that this isn't an option in most emulators, and as the next commits will be to enable default icons, there will always be something to display.
If Rich Presence and Discord Presence are enabled in Achievement Settings, the string generated by rcheevos as the player's current Rich Presence will be sent to the Status field in the Discord Presence object. This will be updated whenever Rich Presence updates.
The "welcome message" that shows up to players when a game starts up and Achievements are active will now either tell the player upon load that there's no support for achievements, or will wait until the first attempt to load the game's badge either succeeds or fails and then display a full message with title and progress and status. This is in part facilitated by a boolean field for when to display a welcome message, set to true upon loading and to false upon a message being displayed.
Spectator Mode is a new mode added by rc_client that allows for achievement and leaderboard functionality, but does not submit this data to the site, partially allowing for offline achievements. It effectively replaces the former settings for disabling achievements, leaderboards, and RP, which are now always active internally as long as the client is active.
The client can take care of itself and handle its own hardcore status when it toggles, so I can tell the settings widget to contact the manager directly to set it.
Also, gradually reorganizing the settings dialog over the next handful of commits.
The client can handle media changes natively so disabling can take place internally. This code uses the same external calls to load data, but will call either BeginLoad or BeginChangeMedia based on whether any media is already loaded.
Due to the client's handling of media changes (it simply disables hardcore if an unknown media is detected) the existing functionality for "disabling" the achievements is no longer necessary and can be deleted.
Two portions of this need updating.
Anything related to points and unlock counts and scoring uses game_summary now instead of the TallyScore method. Unfortunately this comes with the drawback that I cannot easily at this time access the number of points/unlocks from the other hardcore mode, so things like the second progress bar have been deleted.
Rich presence, which no longer needs to be stored, but can be calculated at request. As the AchievementHeader can now update just the Rich Presence, DoFrame can now simply call a header update with .rp=true and the current Rich Presence will be calculated immediately.
As the two items above are the last remaining things to use a number of the components in AchievementManager, this also deletes: Request V1 (V2 is renamed accordingly), ResponseType, PointSpread, TallyScore, UnlockStatus, and the RP generation and ping methods.
UpdateData in AchievementsWindow now only updates the components being requested, massively improving the window's performance. The parameter is UpdatedItems in AchievementManager, which tracks which portions of the system have been updated for every update callback.