139 std::filesystem::path steamLocation;
145 static constexpr DWORD STEAM_LOCATION_MAX_SIZE = 16384;
146 std::unique_ptr<wchar_t[]> steamLocationData{
new wchar_t[STEAM_LOCATION_MAX_SIZE] {}};
150 RegOpenKeyExW(HKEY_LOCAL_MACHINE, L
"SOFTWARE\\Valve\\Steam", 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &steam) != ERROR_SUCCESS &&
151 RegOpenKeyExW(HKEY_LOCAL_MACHINE, L
"SOFTWARE\\Valve\\Steam", 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &steam) != ERROR_SUCCESS
156 DWORD steamLocationSize = STEAM_LOCATION_MAX_SIZE *
sizeof(wchar_t);
157 if (RegQueryValueExW(steam, L
"InstallPath",
nullptr,
nullptr,
reinterpret_cast<LPBYTE
>(steamLocationData.get()), &steamLocationSize) != ERROR_SUCCESS) {
163 steamLocation = steamLocationSize > 0 ? std::filesystem::path{steamLocationData.get()} : std::filesystem::path{};
167 std::filesystem::path HOME{
"~"};
168 if (
const auto* homeEnv = std::getenv(
"HOME")) {
172 steamLocation = HOME /
"Library" /
"Application Support" /
"Steam";
174 std::filesystem::path XDG_DATA_HOME{HOME /
".local" /
"share"};
175 if (
const auto* xdgDataHomeEnv = std::getenv(
"XDG_DATA_HOME")) {
176 XDG_DATA_HOME = xdgDataHomeEnv;
179 const std::array locations{
180 HOME /
"snap" /
"steam" /
"common" /
".local" /
"share" /
"Steam",
181 HOME /
"snap" /
"steam" /
"common" /
".steam" /
"steam",
182 HOME /
".var" /
"app" /
"com.valvesoftware.Steam" /
".local" /
"share" /
"Steam",
183 HOME /
".var" /
"app" /
"com.valvesoftware.Steam" /
".steam" /
"steam",
184 XDG_DATA_HOME /
"Steam",
185 HOME /
".local" /
"share" /
"Steam",
186 HOME /
".steam" /
"steam",
189 for (
const auto& location : locations) {
190 if (std::filesystem::exists(location, ec)) {
191 steamLocation = location;
195 if (steamLocation.empty()) {
197 std::filesystem::path location;
198 std::filesystem::path d{
"cwd/steamclient64.dll"};
199 for (
const auto& entry : std::filesystem::directory_iterator{
"/proc/"}) {
200 if (std::filesystem::exists(entry / d, ec)) {
202 location = std::filesystem::read_symlink(entry.path() /
"cwd", ec);
209 if (location.empty()) {
212 steamLocation = location;
218 if (steamLocation.empty()) {
221 this->steamInstallDir = steamLocation;
223 auto libraryFoldersFilePath = steamLocation /
"config" /
"libraryfolders.vdf";
224 if (!std::filesystem::exists(libraryFoldersFilePath, ec)) {
225 libraryFoldersFilePath = steamLocation /
"steamapps" /
"libraryfolders.vdf";
226 if (!std::filesystem::exists(libraryFoldersFilePath, ec)) {
233 const auto& libraryFoldersValue = libraryFolders[
"libraryfolders"];
234 if (libraryFoldersValue.isInvalid()) {
238 for (uint64_t i = 0; i < libraryFoldersValue.getChildCount(); i++) {
239 const auto& folder = libraryFoldersValue[i];
241 auto folderName = folder.getKey();
242 if (folderName ==
"TimeNextStatsReport" || folderName ==
"ContentStatsID") {
246 const auto& folderPath = folder[
"path"];
247 if (folderPath.isInvalid()) {
251 std::filesystem::path libraryFolderPath{folderPath.getValue()};
252 libraryFolderPath /=
"steamapps";
254 if (!std::filesystem::exists(libraryFolderPath, ec)) {
257 this->libraryDirs.push_back(libraryFolderPath);
259 for (
const auto& entry : std::filesystem::directory_iterator{libraryFolderPath, std::filesystem::directory_options::skip_permission_denied}) {
260 auto entryName = entry.path().filename().string();
261 if (!entryName.starts_with(
"appmanifest_") || !entryName.ends_with(
".acf")) {
267 const auto& appState = appManifest[
"AppState"];
268 if (appState.isInvalid()) {
272 const auto& appName = appState[
"name"];
273 if (appName.isInvalid()) {
276 const auto& appInstallDir = appState[
"installdir"];
277 if (appInstallDir.isInvalid()) {
280 const auto& appID = appState[
"appid"];
281 if (appID.isInvalid()) {
285 this->gameDetails[std::stoi(std::string{appID.getValue()})] = GameInfo{
286 .name = std::string{appName.getValue()},
287 .installDir = std::string{appInstallDir.getValue()},
288 .libraryInstallDirsIndex = this->libraryDirs.size() - 1,
293 const auto assetCacheFilePath = steamLocation /
"appcache" /
"librarycache" /
"assetcache.vdf";
294 if (std::filesystem::exists(assetCacheFilePath, ec)) {