TwitchPlaysBF2 / GameDataReader

NuGet library providing simple access to game settings. Reading data from games like Battlefield 2 - i.e. to access player data from BF2 specific .con configuration files. Open to extension.
https://www.nuget.org/packages/GameDataReader
MIT License
2 stars 1 forks source link

BF1942 and BFV process detection and con file dynamic file path lookup #7

Closed AnomalousNicole closed 1 year ago

AnomalousNicole commented 1 year ago

Recently, I installed Battlefield Rich Presence and noticed that it did not show game info in Discord while playing BF1942 and BFV. I cloned the repos for Battlefield Rich Presence and GameDataReader and debugged the code to figure out what was happening.

BF1942 had the following Battlefield Rich Presence issue that prevented game information from displaying in my profile in Discord.

Issue: Battlefield Rich Presence was not able to find the BF1942 game process using a RegEx to find the running process.

Fix: I modified Battlefield Rich Presence to look for any processes named "BF1942" and if one match is found then a GameInfo object will be returned from the IsRunning method.

Testing: After the fix above was applied to Battlefield Rich Presence, I built a debug version of Battlefield Rich Presence and ran BF1942 again. This time when BF1942 was run, Battlefield Rich Presence was displayed in my Discord profile. However, it only displayed the "In the menus" status in my profile. When I debugged the Battlefield Rich Presence further, I was able to determine that GameDataReader was passing back the message "Couldn't find configuration data. Is the game installed?" to Battlefield Rich Presence. This is what led me to debug the GameDataReader code.

BF1942 and BFV each had the GameDataReader issue below that was causing the con files for each game to not be found correctly.

Issue: GameDataReader was not able to find the GeneralOptions.con and Profile.con files located within the "mods\bf1942\settings" and "Mods\BfVietnam\settings" folders in each game install folder. GameDataReader was looking in the "%LOCALAPPDATA%\VirtualStore\Program Files (x86)\EA Games\Battlefield 1942\Mods\bf1942\settings" and "%LOCALAPPDATA%\VirtualStore\Program Files (x86)\EA Games\Battlefield Vietnam\Mods\BfVietnam\settings" folders for each game. These folders are used when BF1942 or BFV are installed under Program Files (x86) and the game does not have permission to write to the game install folder. However, when BF1942 or BFV is not installed under Program Files (x86) each game uses the "mods\bf1942\settings" or "Mods\BfVietnam\settings" located in that game's install folder.

Fix: I modified GameDataReader to dynamically lookup the path where the BF1942 or BFV processes are running from. Those paths are then used to check if the GeneralOptions.con and Profile.con files exist within the "mods\bf1942\settings" and "Mods\BfVietnam\settings" folders in each game install folder. If the GeneralOptions.con and Profile.con files are not found, then GameDataReader will check for the existence of the con files in the "%LOCALAPPDATA%\VirtualStore\Program Files (x86)\EA Games\" for each game.

Testing: After the fix above was applied to GameDataReader, I built a debug version of GameDataReader and then copied the GameDataReader DLL to the debug folder for Battlefield Rich Presence. I then ran Battlefield Rich Presence and also launched BF1942 and connected to a multiplayer server. Battlefield Rich Presence then correctly displayed the game and server information in my Discord profile. I repeated the same test for BFV and Battlefield Rich Presence also displayed the game and server information in Discord.

Note: The fix I created for Battlefield Rich Presence is dependent upon the fix for GameDataReader. In each program I have created my fixes in a branch called "bf1492-bfv-fixes". I have submitted pull requests on both the Battlefield Rich Presence and GameDataReader GitHub repo pages.

Below are screenshots of Battlefield Rich Presence displaying game information in Discord for Battlefield 1942 and Battlefield Vietnam.

Battlefield 1942 BattlefieldRichPresence-BF1942

Battlefield Vietnam BattlefieldRichPresence-BFV

Hopefully, the above information has been helpful in explaining the issues that were fixed in each program. Please let me know if more information is needed.

cetteup commented 1 year ago

Nice work! Very detailed description of the underlying issue. 👍

I added a few comments regarding some details. I do, however, see one bigger issue with the current approach: It only works if the game is running. That's fine when GameDataReader is used by something such as BattlefieldRichPresence, but it is neither obvious to any other consumer nor is it the case for any other game supported by this library.

Since the running game process is only used to determine the path the game is running from, a better approach could be to simply get the install path from the registry. This has the drawback of only working if the game is installed properly, but it does ofc work regardless of whether the game is running. The usual registry path when installed in x86 would be

HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\EA Games\Battlefield 1942

That path might look different for you with the game installed elsewhere, which is something to check. Whatever the path, it contains a key called GAMEDIR which points to the install directory. That path could be used instead of the path of any running process.

AnomalousNicole commented 1 year ago

@cetteup Thank you for the feedback on my changes. I am working on implementing the changes you have outlined in your comments.

While testing the latest changes to Battlefield Rich Presence, I did discover another bug with GameDataReader in relation to the playerName that gets passed back to Battlefield Rich Presence. BF1942 and BFV use ANSI character encoding for the CON files. In one of my player names, I use the registered trademark symbol "®". When GameDataReader passes back the player name with the "®" symbol in it, the URL that gets built by Battlefield Rich Presence does not work correctly. I was able to fix that issue in GameDataReader by using the System.Text.Encoding.CodePages NuGet package and making the change below in the ReadConfigFile method in LineBasedConfigFile.

//BF1942 and BFVietnam CON files use ANSI/windows-1252 character encoding var configLines = new List(); if (filePath.ToLower().Contains("bf1942") || filePath.ToLower().Contains("bfvietnam")) { Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); configLines = File.ReadAllLines(filePath, Encoding.GetEncoding("windows-1252")).ToList(); } else { configLines = File.ReadAllLines(filePath).ToList(); }

BF1942/BFV Player Name In CON File: lookoutriddick® Player Name Passed Back From GameDataReader: lookoutriddick�

Non working URLs: https://api.bflist.io/bf1942/v1/players/lookoutriddick%EF%BF%BD/server https://api.bflist.io/bfvietnam/v1/players/lookoutriddick%EF%BF%BD/server

Working URLs: https://api.bflist.io/bf1942/v1/players/lookoutriddick%C2%AE/server https://api.bflist.io/bfvietnam/v1/players/lookoutriddick%C2%AE/server

AnomalousNicole commented 1 year ago

@cetteup I have pushed a commit the resolves the character encoding issue when the bf1942 and bfv con files are read by GameDataReader. I am working on fixes for the other items noted in your comments from my original commits. I plan to push those fixes sometime tomorrow.

AnomalousNicole commented 1 year ago

@cetteup @TwitchPlaysBF2

I have pushed some commits that I believe address the items that were noted regarding the original PR commit. GameDataReader will now try to read the con files from the locations listed in the order below.

Registry: If the game was installed properly, the con file path will be read from the game's GAMEDIR value in the Registry. The Registry lookup will check if the con file exists and if it does exist then the lookup method will return that path to the method that invoked the lookup.

Game Process: If the game was not properly installed, the con file path will be read using the game process path. The Game Process lookup will check if the con file exists and if it does exist then the lookup method will return that path to the method that invoked the lookup.

AppData: If the con files could not be found using the Registry or game process path, then the con file path will be read using the AppData path. The AppData lookup will check if the con file exists and if it does exist then the lookup method will return that path to the method that invoked the lookup.

I have tested all the scenarios above using BF1942 and BFV and it appears that each lookup method is working correctly. Please let me know if you have any questions regarding the changes.

TwitchPlaysBF2 commented 1 year ago

Thanks for your efforts! I have been offline since I was sick, but the changes look mergeable to me 🚀

AnomalousNicole commented 1 year ago

@TwitchPlaysBF2 You're welcome. :) I enjoyed working on the changes and coming up with a solution.

TwitchPlaysBF2 commented 1 year ago

I've created a new release 0.0.4 on NuGet