├── bin.zip ├── bin ├── libcurl.dll ├── libstdc++-6.dll ├── libgcc_s_dw2-1.dll └── generate_game_infos.exe ├── Readme.md └── src └── generate_game_infos.cpp /bin.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oureveryday/Goldberg-generate_game_info/HEAD/bin.zip -------------------------------------------------------------------------------- /bin/libcurl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oureveryday/Goldberg-generate_game_info/HEAD/bin/libcurl.dll -------------------------------------------------------------------------------- /bin/libstdc++-6.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oureveryday/Goldberg-generate_game_info/HEAD/bin/libstdc++-6.dll -------------------------------------------------------------------------------- /bin/libgcc_s_dw2-1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oureveryday/Goldberg-generate_game_info/HEAD/bin/libgcc_s_dw2-1.dll -------------------------------------------------------------------------------- /bin/generate_game_infos.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oureveryday/Goldberg-generate_game_info/HEAD/bin/generate_game_infos.exe -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Goldberg Generate Game Info 2 | 3 | A build and mod for goldberg Steam EMU generate_game_info.cpp 4 | Normal:Steam API key needed 5 | Mod xan105's api:Don't need steam API key (But can't generate items) 6 | Source: https://gitlab.com/Mr_Goldberg/goldberg_emulator 7 | 8 | # Usage 9 | 10 | generate_game_infos.exe app_id <-s steam_api_key> <-o output_path> <-i> 11 | -s: Using steam API instead of xan105 API 12 | -o: Output path (default is folder with app_id/steam_settings) 13 | -i: Disable generate achievement images 14 | 15 | # Build 16 | 17 | Run command on bash: 18 | `g++ -o generate_game_infos generate_game_infos/generate_game_infos.cpp -lcurl` 19 | 20 | Or on MinGW (Windows): 21 | `g++ -o generate_game_infos.exe generate_game_infos/generate_game_infos.cpp -lcurl.dll` 22 | 23 | Library requirment: 24 | * curl (https://github.com/curl/curl) or (https://curl.se/windows/) 25 | * json (https://github.com/nlohmann/json) 26 | * fifo_map (https://github.com/nlohmann/fifo_map) 27 | 28 | # For Achievements API thanks [xan105](https://github.com/xan105/xan105) 29 | -------------------------------------------------------------------------------- /src/generate_game_infos.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | class CurlGlobal 16 | { 17 | bool _init; 18 | 19 | CurlGlobal() :_init(false) {} 20 | 21 | ~CurlGlobal() { cleanup(); } 22 | 23 | public: 24 | static CurlGlobal& Inst() 25 | { 26 | static CurlGlobal _this; 27 | return _this; 28 | } 29 | 30 | CURLcode init(long flags = CURL_GLOBAL_DEFAULT) { return curl_global_init(flags); } 31 | void cleanup() 32 | { 33 | if (_init) 34 | { 35 | curl_global_cleanup(); 36 | _init = false; 37 | } 38 | } 39 | }; 40 | 41 | class CurlEasy 42 | { 43 | CURL* _me; 44 | bool _init; 45 | std::string _buffer; 46 | 47 | static int writer(char* data, size_t size, size_t nmemb, 48 | CurlEasy *_this) 49 | { 50 | if (_this == nullptr) 51 | return 0; 52 | 53 | _this->_buffer.append(data, size * nmemb); 54 | 55 | return size * nmemb; 56 | } 57 | 58 | public: 59 | CurlEasy() :_me(nullptr), _init(false) {} 60 | ~CurlEasy() { cleanup(); } 61 | 62 | bool init() 63 | { 64 | _init = (_me = curl_easy_init()) != nullptr; 65 | if (_init) 66 | { 67 | if (curl_easy_setopt(_me, CURLOPT_WRITEFUNCTION, writer) != CURLE_OK) 68 | { 69 | cleanup(); 70 | return false; 71 | } 72 | 73 | if (curl_easy_setopt(_me, CURLOPT_WRITEDATA, this) != CURLE_OK) 74 | { 75 | cleanup(); 76 | return false; 77 | } 78 | } 79 | return _init; 80 | } 81 | 82 | void cleanup() 83 | { 84 | if (_init) 85 | { 86 | curl_easy_cleanup(_me); 87 | } 88 | } 89 | 90 | CURLcode set_url(const std::string& url) 91 | { 92 | return curl_easy_setopt(_me, CURLOPT_URL, url.c_str()); 93 | } 94 | 95 | CURLcode skip_verifypeer(bool skip = true) 96 | { 97 | return curl_easy_setopt(_me, CURLOPT_SSL_VERIFYPEER, skip ? 0L : 1L); 98 | } 99 | 100 | CURLcode skip_verifhost(bool skip = true) 101 | { 102 | return curl_easy_setopt(_me, CURLOPT_SSL_VERIFYHOST, skip ? 0L : 1L); 103 | } 104 | 105 | CURLcode connect_only(bool connect = true) 106 | { 107 | return curl_easy_setopt(_me, CURLOPT_CONNECT_ONLY, connect ? 1L : 0L); 108 | } 109 | 110 | CURLcode perform() 111 | { 112 | _buffer.clear(); 113 | return curl_easy_perform(_me); 114 | } 115 | 116 | CURLcode recv(void *buffer, size_t buflen, size_t* read_len) 117 | { 118 | return curl_easy_recv(_me, buffer, buflen, read_len); 119 | } 120 | 121 | CURLcode get_html_code(long &code) 122 | { 123 | return curl_easy_getinfo(_me, CURLINFO_RESPONSE_CODE, &code); 124 | } 125 | 126 | std::string const& get_answer() const { return _buffer; } 127 | }; 128 | 129 | // Get all steam appid with their name: http://api.steampowered.com/ISteamApps/GetAppList/v2/ 130 | // Steam storefront webapi: https://wiki.teamfortress.com/wiki/User:RJackson/StorefrontAPI 131 | // http://api.steampowered.com/ISteamUserStats/GetSchemaForGame/v2/?key=&appid= 132 | /* 133 | { 134 | "game" : { 135 | "gameName" : "", 136 | "availableGameStats" : { 137 | "achievements" : { 138 | ("" : { 139 | "name" : "achievement_name", 140 | "displayName" : "achievement name on screen", 141 | "hidden" : (0|1), 142 | ["description" : "",] 143 | "icon" : "", 144 | "icongray" : "" 145 | }, 146 | ...) 147 | } 148 | } 149 | } 150 | } 151 | */ 152 | // Get appid infos: http://store.steampowered.com/api/appdetails/?appids=218620 153 | /* 154 | "appid" : { 155 | "success" : (true|false), 156 | (success == true "data" : { 157 | ... 158 | "name" : "", 159 | "steam_appid" : , 160 | (OPT "dlc" : [, ]), 161 | "header_image" : "" <-- Use this in the overlay ? 162 | (OPT "achievements" : { 163 | "total" : 164 | }), 165 | "background" : "" <-- Use this as the overlay background ? 166 | (OPT "packages" : [, ]) 167 | }) 168 | } 169 | */ 170 | // --------------------------------- 171 | // -- Special thanks to psychonic -- 172 | // --------------------------------- 173 | // Get game items definition digest (Phase1): https://api.steampowered.com/IInventoryService/GetItemDefMeta/v1?key=&appid=218620 174 | /* 175 | { 176 | "response": { 177 | "modified": 1566848385, 178 | "digest": "3CDFC1CC1AC2B0D55D12C1C130F4294BDD6DF8D0" 179 | } 180 | } 181 | */ 182 | 183 | // Get game items definition: https://api.steampowered.com/IGameInventory/GetItemDefArchive/v0001?appid=218620&digest= 184 | /* 185 | [ 186 | { 187 | "appid":"218620", 188 | "itemdefid":"0", 189 | "Timestamp":"2016-04-08T18:00:21.3643085Z", 190 | "modified":"20160408T180021Z", 191 | "date_created":"20160408T180021Z", 192 | "type":"", 193 | "display_type":"", 194 | "name":"", 195 | "quantity":0, 196 | "description":"", 197 | "tradable":false, 198 | "marketable":false, 199 | "commodity":false, 200 | "drop_interval":0, 201 | "drop_max_per_window":0, 202 | "workshopid":"0" 203 | }, 204 | { 205 | "appid":"218620", 206 | "itemdefid":"50002", 207 | "Timestamp":"2015-11-13T16:01:18.0338618Z", 208 | "modified":"20151113T160117Z", 209 | "date_created":"20151113T160117Z", 210 | "type":"item", 211 | "display_type":"", 212 | "name":"Sputnik Safe", 213 | "quantity":0, 214 | "description":"[color=#2360D8]THE JUDGE SHOTGUN | Pixel [/color]\n[color=#2360D8]KOBUS 90 SUBMACHINE GUN | Red Stars[/color]\n[color=#2360D8]PLAINSRIDER BOW | Arctic Plains[/color]\n[color=#2360D8]GRUBER KURZ PISTOL | Little Leopard[/color]\n[color=#2360D8]HRL-7 ROCKET LAUNCHER | Headline[/color]\n[color=#2360D8]LOCOMOTIVE 12G SHOTGUN | Cosmonaut[/color]\n[color=#9900FF]FLAMETHROWER | St. Basil[/color]\n[color=#9900FF]JP36 RIFLE | Ice Leopard [/color]\n[color=#9900FF]CAR-4 RIFLE | Stripe On[/color]\n[color=#9900FF]BRONCO .44 REVOLVER | Black Bull[/color]\n[color=#FF00FF]BERNETTI 9 PISTOL | Angry Bear[/color]\n[color=#FF00FF]THANATOS .50 CAL SNIPER RIFLE | Matrjoschka[/color]\n[color=#FF00FF]M308 RIFLE | Helmet Space Program[/color]\n[color=#FF0000]CLARION RIFLE | Breaching Owl[/color]\n[color=#FF0000]MOSCONI 12G SHOTGUN | Bullet Bear Gun[/color]\n[color=#FFAA00]or an exceedingly rare special item![/color]", 215 | "icon_url":"http://media.overkillsoftware.com/economy42gF2Y/safes_weapon_01.png", 216 | "icon_url_large":"http://media.overkillsoftware.com/economy42gF2Y/safes_weapon_01.png", 217 | "store_tags":"safe;sputnik safe;", 218 | "tradable":true, 219 | "marketable":true, 220 | "commodity":false, 221 | "drop_interval":0, 222 | "drop_max_per_window":0, 223 | "workshopid":"0", 224 | "dsl_bonus":"false", 225 | "item_name":"weapon_01", 226 | "item_slot":"safes" 227 | } 228 | */ 229 | 230 | #ifdef max 231 | #undef max 232 | #endif 233 | 234 | std::string steam_apikey; 235 | std::string app_id; 236 | std::string output_path; 237 | bool steamapi = false; 238 | bool path = false; 239 | bool image = true; 240 | 241 | 242 | #if defined(WIN32) || defined(_WIN32) 243 | #include 244 | 245 | static bool create_directory(std::string const& strPath) 246 | { 247 | DWORD dwAttrib = GetFileAttributesA(strPath.c_str()); 248 | 249 | if (dwAttrib != INVALID_FILE_ATTRIBUTES && dwAttrib & FILE_ATTRIBUTE_DIRECTORY) 250 | return true; 251 | 252 | return CreateDirectoryA(strPath.c_str(), NULL); 253 | } 254 | #elif defined(__linux__) 255 | #include 256 | #include 257 | #include 258 | 259 | static bool create_directory(std::string const& strPath) 260 | { 261 | struct stat sb; 262 | 263 | if (stat(strPath.c_str(), &sb) != 0) 264 | { 265 | return mkdir(strPath.c_str(), 0755) == 0; 266 | } 267 | if (S_ISDIR(sb.st_mode)) 268 | return true; 269 | 270 | return false; 271 | } 272 | 273 | #endif 274 | 275 | static void generate_achievementsxan105(CurlEasy &easy) 276 | { 277 | std::string url = "https://api.xan105.com/steam/ach/"; 278 | url += app_id; 279 | easy.set_url(url); 280 | easy.perform(); 281 | try 282 | { 283 | std::ofstream ach_file(output_path + "/achievements.json", std::ios::trunc | std::ios::out); 284 | nlohmann::json json = nlohmann::json::parse(easy.get_answer()); 285 | nlohmann::json output_json = nlohmann::json::array(); 286 | 287 | bool first = true; 288 | int i = 0; 289 | for (auto& item : json["data"]["achievement"]["list"].items()) 290 | { 291 | output_json[i]["name"] = item.value()["name"]; 292 | output_json[i]["displayName"] = item.value()["displayName"]; 293 | output_json[i]["hidden"] = std::to_string(item.value()["hidden"].get()); 294 | try 295 | { 296 | if( !item.value()["description"].is_null() ) 297 | output_json[i]["description"] = item.value()["description"]; 298 | else 299 | output_json[i]["description"] = ""; 300 | } 301 | catch (...) 302 | { 303 | output_json[i]["description"] = ""; 304 | } 305 | 306 | if (image) 307 | { 308 | std::string icon_path = "images/" + item.value()["name"].get() + ".jpg"; 309 | std::ofstream achievement_icon(output_path + "/" + icon_path, std::ios::out | std::ios::trunc | std::ios::binary); 310 | if (!achievement_icon) 311 | { 312 | std::cerr << "Cannot create achievement icon \"" << icon_path << "\"" << std::endl; 313 | return; 314 | } 315 | easy.set_url(item.value()["icon"]); 316 | easy.perform(); 317 | 318 | std::string picture = easy.get_answer(); 319 | achievement_icon.write(picture.c_str(), picture.length()); 320 | 321 | output_json[i]["icon"] = icon_path; 322 | 323 | } 324 | if (image) 325 | { 326 | std::string icon_path = "images/" + item.value()["name"].get() + "_gray.jpg"; 327 | std::ofstream achievement_icon(output_path + "/" + icon_path, std::ios::out | std::ios::trunc | std::ios::binary); 328 | if (!achievement_icon) 329 | { 330 | std::cerr << "Cannot create achievement icon \"" << icon_path << "\"" << std::endl; 331 | return; 332 | } 333 | easy.set_url(item.value()["icongray"]); 334 | easy.perform(); 335 | 336 | std::string picture = easy.get_answer(); 337 | achievement_icon.write(picture.c_str(), picture.length()); 338 | 339 | output_json[i]["icongray"] = icon_path; 340 | } 341 | ++i; 342 | } 343 | ach_file << std::setw(2) << output_json; 344 | } 345 | catch (std::exception& e) 346 | { 347 | std::cerr << "Failed to get infos: "; 348 | long code; 349 | if (easy.get_html_code(code) == CURLE_OK && code == 403) 350 | { 351 | std::cerr << "Error in webapi key"; 352 | } 353 | else 354 | { 355 | std::cerr << "Error while parsing json. Try to go at " << url << " and see what you can do to build your achivements.json"; 356 | } 357 | std::cerr << std::endl; 358 | } 359 | } 360 | 361 | static void generate_achievements(CurlEasy &easy) 362 | { 363 | std::string url = "https://api.steampowered.com/ISteamUserStats/GetSchemaForGame/v2/?key="; 364 | url += steam_apikey; 365 | url += "&appid="; 366 | url += app_id; 367 | easy.set_url(url); 368 | easy.perform(); 369 | try 370 | { 371 | std::ofstream ach_file(output_path + "/achievements.json", std::ios::trunc | std::ios::out); 372 | nlohmann::json json = nlohmann::json::parse(easy.get_answer()); 373 | nlohmann::json output_json = nlohmann::json::array(); 374 | 375 | bool first = true; 376 | int i = 0; 377 | for (auto& item : json["game"]["availableGameStats"]["achievements"].items()) 378 | { 379 | output_json[i]["name"] = item.value()["name"]; 380 | output_json[i]["displayName"] = item.value()["displayName"]; 381 | output_json[i]["hidden"] = std::to_string(item.value()["hidden"].get()); 382 | try 383 | { 384 | if( !item.value()["description"].is_null() ) 385 | output_json[i]["description"] = item.value()["description"]; 386 | else 387 | output_json[i]["description"] = ""; 388 | } 389 | catch (...) 390 | { 391 | output_json[i]["description"] = ""; 392 | } 393 | if (image) 394 | { 395 | std::string icon_path = "images/" + item.value()["name"].get() + ".jpg"; 396 | std::ofstream achievement_icon(output_path + "/" + icon_path, std::ios::out | std::ios::trunc | std::ios::binary); 397 | if (!achievement_icon) 398 | { 399 | std::cerr << "Cannot create achievement icon \"" << icon_path << "\"" << std::endl; 400 | return; 401 | } 402 | easy.set_url(item.value()["icon"]); 403 | easy.perform(); 404 | 405 | std::string picture = easy.get_answer(); 406 | achievement_icon.write(picture.c_str(), picture.length()); 407 | 408 | output_json[i]["icon"] = icon_path; 409 | 410 | } 411 | if (image) 412 | { 413 | std::string icon_path = "images/" + item.value()["name"].get() + "_gray.jpg"; 414 | std::ofstream achievement_icon(output_path + "/" + icon_path, std::ios::out | std::ios::trunc | std::ios::binary); 415 | if (!achievement_icon) 416 | { 417 | std::cerr << "Cannot create achievement icon \"" << icon_path << "\"" << std::endl; 418 | return; 419 | } 420 | easy.set_url(item.value()["icongray"]); 421 | easy.perform(); 422 | 423 | std::string picture = easy.get_answer(); 424 | achievement_icon.write(picture.c_str(), picture.length()); 425 | 426 | output_json[i]["icongray"] = icon_path; 427 | } 428 | ++i; 429 | } 430 | ach_file << std::setw(2) << output_json; 431 | } 432 | catch (std::exception& e) 433 | { 434 | std::cerr << "Failed to get infos: "; 435 | long code; 436 | if (easy.get_html_code(code) == CURLE_OK && code == 403) 437 | { 438 | std::cerr << "Error in webapi key"; 439 | } 440 | else 441 | { 442 | std::cerr << "Error while parsing json. Try to go at " << url << " and see what you can do to build your achivements.json"; 443 | } 444 | std::cerr << std::endl; 445 | } 446 | } 447 | 448 | template 449 | using my_workaround_fifo_map = nlohmann::fifo_map, A>; 450 | using fifo_json = nlohmann::basic_json; 451 | 452 | 453 | static void generate_items(CurlEasy& easy) 454 | { 455 | std::string url = "https://api.steampowered.com/IInventoryService/GetItemDefMeta/v1?key="; 456 | url += steam_apikey; 457 | url += "&appid="; 458 | url += app_id; 459 | 460 | easy.set_url(url); 461 | easy.perform(); 462 | 463 | try 464 | { 465 | nlohmann::json json = nlohmann::json::parse(easy.get_answer()); 466 | std::string digest = json["response"]["digest"]; 467 | 468 | url = "https://api.steampowered.com/IGameInventory/GetItemDefArchive/v0001?appid="; 469 | url += app_id; 470 | url += "&digest="; 471 | url += digest; 472 | 473 | easy.set_url(url); 474 | easy.perform(); 475 | 476 | fifo_json item_json; 477 | fifo_json default_item_json; 478 | 479 | json = nlohmann::json::parse(easy.get_answer()); 480 | std::ofstream items_file(output_path + "/items.json", std::ios::trunc | std::ios::out); 481 | std::ofstream default_items_file(output_path + "/default_items.json", std::ios::trunc | std::ios::out); 482 | 483 | for (auto &i : json) 484 | { 485 | for (auto j = i.begin(); j != i.end(); ++j) 486 | { 487 | //if (j.key() == "itemdefid") 488 | //{ 489 | // j.value() = std::stoll(j.value().get()); 490 | //} 491 | //else 492 | { 493 | nlohmann::json& v = j.value(); 494 | switch (v.type()) 495 | { 496 | case nlohmann::json::value_t::boolean: 497 | v = (v.get() ? "true" : "false"); 498 | break; 499 | 500 | case nlohmann::json::value_t::number_float: 501 | v = std::to_string(v.get()); 502 | break; 503 | 504 | case nlohmann::json::value_t::number_integer: 505 | v = std::to_string(v.get()); 506 | break; 507 | 508 | case nlohmann::json::value_t::number_unsigned: 509 | v = std::to_string(v.get()); 510 | break; 511 | } 512 | } 513 | } 514 | item_json[i["itemdefid"].get()] = i; 515 | default_item_json[i["itemdefid"].get()] = 1; 516 | } 517 | 518 | items_file << std::setw(2) << item_json; 519 | default_items_file << std::setw(2) << default_item_json; 520 | } 521 | catch (std::exception& e) 522 | { 523 | std::cerr << "Failed to get infos: "; 524 | long code; 525 | if (easy.get_html_code(code) == CURLE_OK && code == 403) 526 | { 527 | std::cerr << "Error in webapi key"; 528 | } 529 | else 530 | { 531 | std::cerr << "Error while parsing json. Try to go at " << url << " and see what you can do to build your items.json"; 532 | } 533 | std::cerr << std::endl; 534 | } 535 | } 536 | 537 | static std::string get_appid_name(CurlEasy& easy, uint32_t appid) 538 | { 539 | static std::map appid_names; 540 | static bool done; 541 | 542 | if (!done) { 543 | std::string url = "https://api.steampowered.com/ISteamApps/GetAppList/v2/"; 544 | std::cout << "getting app list" << std::endl; 545 | easy.set_url(url); 546 | easy.perform(); 547 | try 548 | { 549 | nlohmann::json json = nlohmann::json::parse(easy.get_answer()); 550 | for (auto &app : json["applist"]["apps"]) { 551 | appid_names[app["appid"].get()] = app["name"].get(); 552 | } 553 | 554 | done = true; 555 | } 556 | catch (std::exception& e) 557 | { 558 | std::cerr << "Failed to get infos: "; 559 | long code; 560 | if (easy.get_html_code(code) == CURLE_OK && code == 403) 561 | { 562 | std::cerr << "Error 403 while getting app list"; 563 | } 564 | else 565 | { 566 | std::cerr << "Error while parsing json. With " << url << ""; 567 | } 568 | std::cerr << std::endl; 569 | } 570 | } 571 | 572 | if (done) { 573 | if (!appid_names.count(appid)) { 574 | std::cout << "getting app name: " << appid << std::endl; 575 | std::string s_appid = std::to_string(appid); 576 | std::string url = "https://store.steampowered.com/api/appdetails/?appids=" + s_appid; 577 | easy.set_url(url); 578 | easy.perform(); 579 | nlohmann::json json = nlohmann::json::parse(easy.get_answer()); 580 | appid_names[appid] = json[s_appid]["data"]["name"].get(); 581 | } 582 | 583 | return appid_names[appid]; 584 | } 585 | 586 | return ""; 587 | } 588 | 589 | static void generate_dlcs(CurlEasy& easy) 590 | { 591 | std::string base_url = "https://store.steampowered.com/api/appdetails/?appids="; 592 | std::string url = base_url + app_id; 593 | easy.set_url(url); 594 | easy.perform(); 595 | 596 | try 597 | { 598 | nlohmann::json json = nlohmann::json::parse(easy.get_answer()); 599 | std::list dlcs; 600 | std::map dlc_names; 601 | 602 | for (auto& dlc : json[app_id]["data"]["dlc"]) 603 | { 604 | dlcs.push_back(dlc.get()); 605 | } 606 | 607 | std::ofstream dlc_file(output_path + "/DLC.txt", std::ios::trunc | std::ios::out); 608 | for (auto &dlc: dlcs) { 609 | dlc_file << dlc << "=" << get_appid_name(easy, dlc) << std::endl; 610 | } 611 | } 612 | catch (std::exception& e) 613 | { 614 | std::cerr << "Failed to get infos: "; 615 | long code; 616 | if (easy.get_html_code(code) == CURLE_OK && code == 403) 617 | { 618 | std::cerr << "Error 403 while getting dlcs"; 619 | } 620 | else 621 | { 622 | std::cerr << "Error while parsing json. With " << url << ""; 623 | } 624 | std::cerr << std::endl; 625 | } 626 | } 627 | 628 | int main(int argc, char **argv) 629 | { 630 | opterr = 0; 631 | int c; 632 | CurlGlobal& cglobal = CurlGlobal::Inst(); 633 | cglobal.init(); 634 | 635 | CurlEasy easy; 636 | if (easy.init()) 637 | { 638 | easy.skip_verifypeer(); 639 | 640 | while ((c = getopt (argc, argv, "s:o:i")) != -1) 641 | { 642 | switch (c) 643 | { 644 | case 's': 645 | printf("Using steam API.\n"); 646 | steamapi = true; 647 | steam_apikey = optarg; 648 | break; 649 | case 'o': 650 | path = true; 651 | output_path = optarg; 652 | std::cout << "Outpath: " << output_path << std::endl; 653 | break; 654 | case 'i': 655 | printf("Disabled generate achievement images.\n"); 656 | image = false; 657 | break; 658 | case '?': 659 | if (optopt == 's') 660 | fprintf (stderr, "Option -%s requires an argument.\n", optopt); 661 | if (optopt == 'o') 662 | fprintf (stderr, "Option -%s requires an argument.\n", optopt); 663 | break; 664 | } 665 | } 666 | 667 | if (argv[optind] != NULL) { 668 | app_id = argv[optind]; 669 | std::cout << "Appid: " < <-o output_path> <-i>" << std::endl; 672 | std::cout << "-s: Using steam API instead of xan105 API" << std::endl; 673 | std::cout << "-o: Output path(default is folder with app_id/steam_settings)" << std::endl; 674 | std::cout << "-i: Disable generate achievement images" << std::endl; 675 | return -1; 676 | } 677 | 678 | 679 | if (steamapi == false) 680 | { 681 | printf("Using xan105 API\n"); 682 | steam_apikey = ""; 683 | } 684 | 685 | if (image == true) 686 | { 687 | printf("Enabled generate achievement images.\n"); 688 | } 689 | 690 | if (path == false) { 691 | output_path = app_id; 692 | create_directory(output_path); 693 | output_path += "/steam_settings"; 694 | } 695 | 696 | if (!create_directory(output_path)) 697 | { 698 | std::cerr << "Cannot create directory: " << output_path << std::endl; 699 | return -1; 700 | } 701 | 702 | if (!create_directory(output_path + "/images")) 703 | { 704 | std::cerr << "Cannot create directory \"images\"" << std::endl; 705 | return -1; 706 | } 707 | 708 | { 709 | std::ofstream appid_file(output_path + "/steam_appid.txt", std::ios::trunc | std::ios::out); 710 | appid_file << app_id; 711 | } 712 | 713 | std::cout << "Generating DLC.txt" << std::endl; 714 | generate_dlcs(easy); 715 | std::cout << "Generating achievements" << std::endl; 716 | if(steamapi) 717 | { 718 | generate_achievements(easy); 719 | } 720 | else 721 | { 722 | generate_achievementsxan105(easy); 723 | } 724 | 725 | if (steamapi){ 726 | std::cout << "Generating items" << std::endl; 727 | generate_items(easy); 728 | } 729 | } 730 | } 731 | --------------------------------------------------------------------------------