Compare commits
5 Commits
5234d8b0e6
...
1ad2818e28
Author | SHA1 | Date |
---|---|---|
Mr_Goldberg | 1ad2818e28 | |
Mr_Goldberg | 7c419e0afe | |
Mr_Goldberg | e0726f2e9d | |
Mr_Goldberg | 5ce4ac8429 | |
Mr_Goldberg | 0d65114ee6 |
|
@ -830,6 +830,11 @@ bool Steam_Client::BShutdownIfAllPipesClosed()
|
||||||
}
|
}
|
||||||
|
|
||||||
steam_controller->Shutdown();
|
steam_controller->Shutdown();
|
||||||
|
#ifdef EMU_OVERLAY
|
||||||
|
if(!settings_client->disable_overlay)
|
||||||
|
steam_overlay->UnSetupOverlay();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (joinable) {
|
if (joinable) {
|
||||||
background_keepalive.join();
|
background_keepalive.join();
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ struct Controller_Action {
|
||||||
|
|
||||||
struct Rumble_Thread_Data {
|
struct Rumble_Thread_Data {
|
||||||
std::condition_variable rumble_thread_cv;
|
std::condition_variable rumble_thread_cv;
|
||||||
std::atomic_bool kill_rumble_thread;
|
bool kill_rumble_thread;
|
||||||
std::mutex rumble_mutex;
|
std::mutex rumble_mutex;
|
||||||
|
|
||||||
struct Rumble_Data {
|
struct Rumble_Data {
|
||||||
|
@ -232,38 +232,21 @@ public:
|
||||||
|
|
||||||
static void background_rumble(Rumble_Thread_Data *data)
|
static void background_rumble(Rumble_Thread_Data *data)
|
||||||
{
|
{
|
||||||
std::mutex mtx;
|
|
||||||
std::unique_lock<std::mutex> lck(mtx);
|
|
||||||
bool rumbled = false;
|
|
||||||
while (true) {
|
|
||||||
bool new_data = false;
|
|
||||||
if (rumbled) {
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(20));
|
|
||||||
data->rumble_mutex.lock();
|
|
||||||
for (int i = 0; i < GAMEPAD_COUNT; ++i) {
|
|
||||||
if (data->data[i].new_data) {
|
|
||||||
new_data = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data->rumble_mutex.unlock();
|
|
||||||
|
|
||||||
if (data->kill_rumble_thread) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool x = new_data || data->rumble_thread_cv.wait_for(lck, std::chrono::milliseconds(100)) != std::cv_status::timeout;
|
|
||||||
if (data->kill_rumble_thread) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
rumbled = false;
|
|
||||||
while (true) {
|
while (true) {
|
||||||
unsigned short left, right;
|
unsigned short left, right;
|
||||||
unsigned int rumble_length_ms;
|
unsigned int rumble_length_ms;
|
||||||
int gamepad = -1;
|
int gamepad = -1;
|
||||||
data->rumble_mutex.lock();
|
while (gamepad == -1) {
|
||||||
|
std::unique_lock<std::mutex> lck(data->rumble_mutex);
|
||||||
|
if (data->kill_rumble_thread) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->rumble_thread_cv.wait_for(lck, std::chrono::milliseconds(1000));
|
||||||
|
if (data->kill_rumble_thread) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < GAMEPAD_COUNT; ++i) {
|
for (int i = 0; i < GAMEPAD_COUNT; ++i) {
|
||||||
if (data->data[i].new_data) {
|
if (data->data[i].new_data) {
|
||||||
left = data->data[i].left;
|
left = data->data[i].left;
|
||||||
|
@ -278,15 +261,9 @@ static void background_rumble(Rumble_Thread_Data *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data->rumble_mutex.unlock();
|
|
||||||
if (gamepad == -1) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GamepadSetRumble((GAMEPAD_DEVICE)gamepad, ((double)left) / 65535.0, ((double)right) / 65535.0, rumble_length_ms);
|
GamepadSetRumble((GAMEPAD_DEVICE)gamepad, ((double)left) / 65535.0, ((double)right) / 65535.0, rumble_length_ms);
|
||||||
rumbled = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,7 +347,9 @@ bool Shutdown()
|
||||||
}
|
}
|
||||||
|
|
||||||
controllers = std::map<ControllerHandle_t, struct Controller_Action>();
|
controllers = std::map<ControllerHandle_t, struct Controller_Action>();
|
||||||
|
rumble_thread_data->rumble_mutex.lock();
|
||||||
rumble_thread_data->kill_rumble_thread = true;
|
rumble_thread_data->kill_rumble_thread = true;
|
||||||
|
rumble_thread_data->rumble_mutex.unlock();
|
||||||
rumble_thread_data->rumble_thread_cv.notify_one();
|
rumble_thread_data->rumble_thread_cv.notify_one();
|
||||||
background_rumble_thread.join();
|
background_rumble_thread.join();
|
||||||
delete rumble_thread_data;
|
delete rumble_thread_data;
|
||||||
|
|
|
@ -182,6 +182,42 @@ std::vector<Steam_Leaderboard_Score> load_leaderboard_scores(std::string name)
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string get_value_for_language(nlohmann::json &json, std::string key, std::string language)
|
||||||
|
{
|
||||||
|
auto x = json.find(key);
|
||||||
|
if (x == json.end()) return "";
|
||||||
|
if (x.value().is_string()) {
|
||||||
|
return x.value().get<std::string>();
|
||||||
|
} else if (x.value().is_object()) {
|
||||||
|
auto l = x.value().find(language);
|
||||||
|
if (l != x.value().end()) {
|
||||||
|
return l.value().get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
l = x.value().find("english");
|
||||||
|
if (l != x.value().end()) {
|
||||||
|
return l.value().get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
l = x.value().begin();
|
||||||
|
if (l != x.value().end()) {
|
||||||
|
if (l.key() == "token") {
|
||||||
|
std::string token_value = l.value().get<std::string>();
|
||||||
|
l++;
|
||||||
|
if (l != x.value().end()) {
|
||||||
|
return l.value().get<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return token_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.value().get<std::string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Steam_User_Stats(Settings *settings, Local_Storage *local_storage, class SteamCallResults *callback_results, class SteamCallBacks *callbacks, Steam_Overlay* overlay):
|
Steam_User_Stats(Settings *settings, Local_Storage *local_storage, class SteamCallResults *callback_results, class SteamCallBacks *callbacks, Steam_Overlay* overlay):
|
||||||
settings(settings),
|
settings(settings),
|
||||||
|
@ -227,8 +263,8 @@ Steam_User_Stats(Settings *settings, Local_Storage *local_storage, class SteamCa
|
||||||
it["hidden"] = std::to_string(it["hidden"].get<int>());
|
it["hidden"] = std::to_string(it["hidden"].get<int>());
|
||||||
} catch (...) {}
|
} catch (...) {}
|
||||||
|
|
||||||
it["displayName"] = it.value("displayName", "");
|
it["displayName"] = get_value_for_language(it, "displayName", settings->get_language());
|
||||||
it["description"] = it.value("description", "");
|
it["description"] = get_value_for_language(it, "description", settings->get_language());
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: not sure if the sort is actually case insensitive, ach names seem to be treated by steam as case insensitive so I assume they are.
|
//TODO: not sure if the sort is actually case insensitive, ach names seem to be treated by steam as case insensitive so I assume they are.
|
||||||
|
|
|
@ -77,6 +77,10 @@ public:
|
||||||
delete vulkan_hook;
|
delete vulkan_hook;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool force_stop_detection;
|
||||||
|
std::condition_variable detect_renderer_thread_cv;
|
||||||
|
std::mutex destroy_render_thread_mutex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Renderer_Detector():
|
Renderer_Detector():
|
||||||
dxgi_hooked(false),
|
dxgi_hooked(false),
|
||||||
|
@ -94,7 +98,8 @@ private:
|
||||||
dx12_hook(nullptr),
|
dx12_hook(nullptr),
|
||||||
opengl_hook(nullptr),
|
opengl_hook(nullptr),
|
||||||
vulkan_hook(nullptr),
|
vulkan_hook(nullptr),
|
||||||
detection_done(false)
|
detection_done(false),
|
||||||
|
force_stop_detection(false)
|
||||||
{
|
{
|
||||||
std::wstring tmp(4096, L'\0');
|
std::wstring tmp(4096, L'\0');
|
||||||
tmp.resize(GetSystemDirectoryW(&tmp[0], tmp.size()));
|
tmp.resize(GetSystemDirectoryW(&tmp[0], tmp.size()));
|
||||||
|
@ -1064,6 +1069,9 @@ public:
|
||||||
auto start_time = std::chrono::steady_clock::now();
|
auto start_time = std::chrono::steady_clock::now();
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
std::unique_lock<std::mutex> lck(destroy_render_thread_mutex);
|
||||||
|
if (force_stop_detection) break;
|
||||||
|
|
||||||
for (auto const& library : libraries)
|
for (auto const& library : libraries)
|
||||||
{
|
{
|
||||||
void* lib_handle = System::Library::GetLibraryHandle(library.first.c_str());
|
void* lib_handle = System::Library::GetLibraryHandle(library.first.c_str());
|
||||||
|
@ -1074,7 +1082,10 @@ public:
|
||||||
(this->*library.second)(name);
|
(this->*library.second)(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds{ 100 });
|
|
||||||
|
detect_renderer_thread_cv.wait_for(lck, std::chrono::milliseconds(100));
|
||||||
|
if (force_stop_detection) break;
|
||||||
|
|
||||||
} while (!detection_done && (timeout.count() == -1 || (std::chrono::steady_clock::now() - start_time) <= timeout));
|
} while (!detection_done && (timeout.count() == -1 || (std::chrono::steady_clock::now() - start_time) <= timeout));
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1415,3 +1426,11 @@ std::future<Renderer_Hook*> detect_renderer(std::chrono::milliseconds timeout)
|
||||||
{
|
{
|
||||||
return std::async(std::launch::async, &Renderer_Detector::detect_renderer, Renderer_Detector::Inst(), timeout);
|
return std::async(std::launch::async, &Renderer_Detector::detect_renderer, Renderer_Detector::Inst(), timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void stop_renderer_detector()
|
||||||
|
{
|
||||||
|
Renderer_Detector::Inst()->destroy_render_thread_mutex.lock();
|
||||||
|
Renderer_Detector::Inst()->force_stop_detection = true;
|
||||||
|
Renderer_Detector::Inst()->destroy_render_thread_mutex.unlock();
|
||||||
|
Renderer_Detector::Inst()->detect_renderer_thread_cv.notify_all();
|
||||||
|
}
|
||||||
|
|
|
@ -28,3 +28,4 @@
|
||||||
#include "Renderer_Hook.h"
|
#include "Renderer_Hook.h"
|
||||||
|
|
||||||
std::future<Renderer_Hook*> detect_renderer(std::chrono::milliseconds timeout = std::chrono::milliseconds{-1});
|
std::future<Renderer_Hook*> detect_renderer(std::chrono::milliseconds timeout = std::chrono::milliseconds{-1});
|
||||||
|
void stop_renderer_detector();
|
||||||
|
|
|
@ -200,6 +200,17 @@ void Steam_Overlay::SetupOverlay()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Steam_Overlay::UnSetupOverlay()
|
||||||
|
{
|
||||||
|
stop_renderer_detector();
|
||||||
|
if (!Ready() && future_renderer.valid()) {
|
||||||
|
if (future_renderer.wait_for(std::chrono::milliseconds{500}) == std::future_status::ready) {
|
||||||
|
future_renderer.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Steam_Overlay::HookReady(bool ready)
|
void Steam_Overlay::HookReady(bool ready)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|
|
@ -161,6 +161,7 @@ public:
|
||||||
|
|
||||||
void SetNotificationInset(int nHorizontalInset, int nVerticalInset);
|
void SetNotificationInset(int nHorizontalInset, int nVerticalInset);
|
||||||
void SetupOverlay();
|
void SetupOverlay();
|
||||||
|
void UnSetupOverlay();
|
||||||
|
|
||||||
void HookReady(bool ready);
|
void HookReady(bool ready);
|
||||||
|
|
||||||
|
@ -202,6 +203,7 @@ public:
|
||||||
|
|
||||||
void SetNotificationInset(int nHorizontalInset, int nVerticalInset) {}
|
void SetNotificationInset(int nHorizontalInset, int nVerticalInset) {}
|
||||||
void SetupOverlay() {}
|
void SetupOverlay() {}
|
||||||
|
void UnSetupOverlay() {}
|
||||||
|
|
||||||
void HookReady(bool ready) {}
|
void HookReady(bool ready) {}
|
||||||
|
|
||||||
|
|
|
@ -53,14 +53,9 @@ def add_input_bindings(group, bindings, force_binding=None, keymap=keymap_digita
|
||||||
bindings[action_name] = [binding]
|
bindings[action_name] = [binding]
|
||||||
return bindings
|
return bindings
|
||||||
|
|
||||||
if len(sys.argv) < 2:
|
|
||||||
print("format: {} xbox_controller_config.vdf".format(sys.argv[0]))
|
|
||||||
exit(0)
|
|
||||||
|
|
||||||
with open(sys.argv[1], 'rb') as f:
|
def generate_controller_config(controller_vdf, config_dir):
|
||||||
t = f.read().decode('utf-8')
|
d = vdf.loads(controller_vdf, mapper=vdf.VDFDict, merge_duplicate_keys=False)
|
||||||
|
|
||||||
d = vdf.loads(t, mapper=vdf.VDFDict, merge_duplicate_keys=False)
|
|
||||||
|
|
||||||
controller_mappings = d["controller_mappings"]
|
controller_mappings = d["controller_mappings"]
|
||||||
|
|
||||||
|
@ -161,17 +156,25 @@ for p in presets:
|
||||||
|
|
||||||
all_bindings[name] = bindings
|
all_bindings[name] = bindings
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#print(controller_mappings["preset"][(0, "group_source_bindings")])
|
#print(controller_mappings["preset"][(0, "group_source_bindings")])
|
||||||
|
|
||||||
#print(all_bindings)
|
#print(all_bindings)
|
||||||
|
|
||||||
config_directory = sys.argv[1] + "_config/steam_settings" + "/controller/"
|
if not os.path.exists(config_dir):
|
||||||
if not os.path.exists(config_directory):
|
os.makedirs(config_dir)
|
||||||
os.makedirs(config_directory)
|
|
||||||
|
|
||||||
for k in all_bindings:
|
for k in all_bindings:
|
||||||
with open(config_directory + k + '.txt', 'w') as f:
|
with open(os.path.join(config_dir, k + '.txt'), 'w') as f:
|
||||||
for b in all_bindings[k]:
|
for b in all_bindings[k]:
|
||||||
f.write(b + "=" + ','.join(all_bindings[k][b]) + "\n")
|
f.write(b + "=" + ','.join(all_bindings[k][b]) + "\n")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("format: {} xbox_controller_config.vdf".format(sys.argv[0]))
|
||||||
|
exit(0)
|
||||||
|
|
||||||
|
with open(sys.argv[1], 'rb') as f:
|
||||||
|
t = f.read().decode('utf-8')
|
||||||
|
|
||||||
|
generate_controller_config(t, os.path.join(sys.argv[1] + "_config/steam_settings", "controller"))
|
||||||
|
|
|
@ -3,9 +3,10 @@ USERNAME = ""
|
||||||
PASSWORD = ""
|
PASSWORD = ""
|
||||||
|
|
||||||
#steam ids with public profiles that own a lot of games
|
#steam ids with public profiles that own a lot of games
|
||||||
TOP_OWNER_IDS = [76561198028121353, 76561198001237877, 76561198355625888, 76561198001678750, 76561198237402290]
|
TOP_OWNER_IDS = [76561198028121353, 76561198001237877, 76561198355625888, 76561198001678750, 76561198237402290, 76561197979911851, 76561198152618007, 76561197969050296, 76561198213148949, 76561198037867621, 76561198108581917]
|
||||||
|
|
||||||
from stats_schema_achievement_gen import achievements_gen
|
from stats_schema_achievement_gen import achievements_gen
|
||||||
|
from controller_config_generator import parse_controller_vdf
|
||||||
from steam.client import SteamClient
|
from steam.client import SteamClient
|
||||||
from steam.client.cdn import CDNClient
|
from steam.client.cdn import CDNClient
|
||||||
from steam.enums import common
|
from steam.enums import common
|
||||||
|
@ -15,6 +16,7 @@ from steam.core.msg import MsgProto
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
prompt_for_unavailable = True
|
prompt_for_unavailable = True
|
||||||
|
|
||||||
|
@ -35,6 +37,7 @@ if (len(USERNAME) == 0 or len(PASSWORD) == 0):
|
||||||
client.cli_login()
|
client.cli_login()
|
||||||
else:
|
else:
|
||||||
result = client.login(USERNAME, password=PASSWORD)
|
result = client.login(USERNAME, password=PASSWORD)
|
||||||
|
auth_code, two_factor_code = None, None
|
||||||
while result in (EResult.AccountLogonDenied, EResult.InvalidLoginAuthCode,
|
while result in (EResult.AccountLogonDenied, EResult.InvalidLoginAuthCode,
|
||||||
EResult.AccountLoginDeniedNeedTwoFactor, EResult.TwoFactorCodeMismatch,
|
EResult.AccountLoginDeniedNeedTwoFactor, EResult.TwoFactorCodeMismatch,
|
||||||
EResult.TryAnotherCM, EResult.ServiceUnavailable,
|
EResult.TryAnotherCM, EResult.ServiceUnavailable,
|
||||||
|
@ -92,6 +95,65 @@ def generate_achievement_stats(client, game_id, output_directory, backup_directo
|
||||||
else:
|
else:
|
||||||
print("no schema", out)
|
print("no schema", out)
|
||||||
|
|
||||||
|
def get_ugc_info(client, published_file_id):
|
||||||
|
return client.send_um_and_wait('PublishedFile.GetDetails#1', {
|
||||||
|
'publishedfileids': [published_file_id],
|
||||||
|
'includetags': False,
|
||||||
|
'includeadditionalpreviews': False,
|
||||||
|
'includechildren': False,
|
||||||
|
'includekvtags': False,
|
||||||
|
'includevotes': False,
|
||||||
|
'short_description': True,
|
||||||
|
'includeforsaledata': False,
|
||||||
|
'includemetadata': False,
|
||||||
|
'language': 0
|
||||||
|
})
|
||||||
|
|
||||||
|
def download_published_file(client, published_file_id, backup_directory):
|
||||||
|
ugc_info = get_ugc_info(client, published_file_id)
|
||||||
|
|
||||||
|
if (ugc_info is None):
|
||||||
|
print("failed getting published file", published_file_id)
|
||||||
|
return None
|
||||||
|
|
||||||
|
file_details = ugc_info.body.publishedfiledetails[0]
|
||||||
|
if (file_details.result != EResult.OK):
|
||||||
|
print("failed getting published file", published_file_id, file_details.result)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if not os.path.exists(backup_directory):
|
||||||
|
os.makedirs(backup_directory)
|
||||||
|
|
||||||
|
with open(os.path.join(backup_directory, "info.txt"), "w") as f:
|
||||||
|
f.write(str(ugc_info.body))
|
||||||
|
|
||||||
|
with urllib.request.urlopen(file_details.file_url) as response:
|
||||||
|
data = response.read()
|
||||||
|
with open(os.path.join(backup_directory, file_details.filename.replace("/", "_").replace("\\", "_")), "wb") as f:
|
||||||
|
f.write(data)
|
||||||
|
return data
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_dlc(raw_infos):
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
dlc_list = set(map(lambda a: int(a), raw_infos["extended"]["listofdlc"].split(",")))
|
||||||
|
except:
|
||||||
|
dlc_list = set()
|
||||||
|
depot_app_list = set()
|
||||||
|
if "depots" in raw_infos:
|
||||||
|
depots = raw_infos["depots"]
|
||||||
|
for dep in depots:
|
||||||
|
depot_info = depots[dep]
|
||||||
|
if "dlcappid" in depot_info:
|
||||||
|
dlc_list.add(int(depot_info["dlcappid"]))
|
||||||
|
if "depotfromapp" in depot_info:
|
||||||
|
depot_app_list.add(int(depot_info["depotfromapp"]))
|
||||||
|
return (dlc_list, depot_app_list)
|
||||||
|
except:
|
||||||
|
print("could not get dlc infos, are there any dlcs ?")
|
||||||
|
return (set(), set())
|
||||||
|
|
||||||
for appid in appids:
|
for appid in appids:
|
||||||
backup_dir = os.path.join("backup","{}".format(appid))
|
backup_dir = os.path.join("backup","{}".format(appid))
|
||||||
out_dir = os.path.join("{}".format( "{}_output".format(appid)), "steam_settings")
|
out_dir = os.path.join("{}".format( "{}_output".format(appid)), "steam_settings")
|
||||||
|
@ -123,6 +185,40 @@ for appid in appids:
|
||||||
with open(os.path.join(out_dir, "build_id.txt"), 'w') as f:
|
with open(os.path.join(out_dir, "build_id.txt"), 'w') as f:
|
||||||
f.write(str(buildid))
|
f.write(str(buildid))
|
||||||
|
|
||||||
|
dlc_config_list = []
|
||||||
|
dlc_list, depot_app_list = get_dlc(game_info)
|
||||||
|
if (len(dlc_list) > 0):
|
||||||
|
dlc_raw = client.get_product_info(apps=dlc_list)["apps"]
|
||||||
|
for dlc in dlc_raw:
|
||||||
|
try:
|
||||||
|
dlc_config_list.append((dlc, dlc_raw[dlc]["common"]["name"]))
|
||||||
|
except:
|
||||||
|
dlc_config_list.append((dlc, None))
|
||||||
|
|
||||||
|
with open(os.path.join(out_dir, "DLC.txt"), 'w', encoding="utf-8") as f:
|
||||||
|
for x in dlc_config_list:
|
||||||
|
if (x[1] is not None):
|
||||||
|
f.write("{}={}\n".format(x[0], x[1]))
|
||||||
|
|
||||||
|
config_generated = False
|
||||||
|
if "config" in game_info:
|
||||||
|
if "steamcontrollerconfigdetails" in game_info["config"]:
|
||||||
|
controller_details = game_info["config"]["steamcontrollerconfigdetails"]
|
||||||
|
for id in controller_details:
|
||||||
|
details = controller_details[id]
|
||||||
|
controller_type = ""
|
||||||
|
enabled_branches = ""
|
||||||
|
if "controller_type" in details:
|
||||||
|
controller_type = details["controller_type"]
|
||||||
|
if "enabled_branches" in details:
|
||||||
|
enabled_branches = details["enabled_branches"]
|
||||||
|
print(id, controller_type)
|
||||||
|
out_vdf = download_published_file(client, int(id), os.path.join(backup_dir, controller_type + str(id)))
|
||||||
|
if out_vdf is not None and not config_generated:
|
||||||
|
if (controller_type in ["controller_xbox360", "controller_xboxone"] and (("default" in enabled_branches) or ("public" in enabled_branches))):
|
||||||
|
parse_controller_vdf.generate_controller_config(out_vdf.decode('utf-8'), os.path.join(out_dir, "controller"))
|
||||||
|
config_generated = True
|
||||||
|
|
||||||
game_info_backup = json.dumps(game_info, indent=4)
|
game_info_backup = json.dumps(game_info, indent=4)
|
||||||
with open(os.path.join(backup_dir, "product_info.json"), "w") as f:
|
with open(os.path.join(backup_dir, "product_info.json"), "w") as f:
|
||||||
f.write(game_info_backup)
|
f.write(game_info_backup)
|
||||||
|
|
|
@ -4,8 +4,6 @@ import os
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
|
||||||
language = 'english'
|
|
||||||
|
|
||||||
STAT_TYPE_INT = '1'
|
STAT_TYPE_INT = '1'
|
||||||
STAT_TYPE_FLOAT = '2'
|
STAT_TYPE_FLOAT = '2'
|
||||||
STAT_TYPE_AVGRATE = '3'
|
STAT_TYPE_AVGRATE = '3'
|
||||||
|
@ -35,11 +33,6 @@ def generate_stats_achievements(schema, config_directory):
|
||||||
x = 'description'
|
x = 'description'
|
||||||
if x == 'Hidden':
|
if x == 'Hidden':
|
||||||
x = 'hidden'
|
x = 'hidden'
|
||||||
if type(value) is dict:
|
|
||||||
if language in value:
|
|
||||||
value = value[language]
|
|
||||||
else:
|
|
||||||
value = ''
|
|
||||||
out[x] = value
|
out[x] = value
|
||||||
out['name'] = ach['name']
|
out['name'] = ach['name']
|
||||||
if 'progress' in ach:
|
if 'progress' in ach:
|
||||||
|
|
Loading…
Reference in New Issue