-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use a specific compatibility tool with a Non-Steam Game and write it out to the config.vdf #905
Comments
Though the script uses Python and the VDF library, since this VDF file is text-based and writeable, it should be possible to write out the compatibility tool. There are two components to solving this: We need to be able to write out to the The In the dropdown on the UI, we should show a Proton version list identical to the one used to select a Proton version for a game. However, in terms of the logic behind-the-scenes, before writing out the chosen Proton version we should do some sort of mapping to make things more convenient when working from the commandline. For example, STL should be intelligent enough to see When passing from the commandline, If the compat tool name is not recognised, we should check all Proton versions known to STL to see if it matches the internal name for any tools. Once we have the internal name, we then need to figure out how to write out to a specific point in a file using Bash. At present, I have no idea how to do this. There's probably a way of doing this by grepping for a specific regex to indicate the end of a given section, and then inserting it there, but I'll need to look into how to do this. This part is probably going to be the most challenging, as getting the internal name may require some time but should be relatively straightforward (just a bunch of grepping around I feel like). I am pretty positive it is possible to write out to a file like this using Bash, I just don't know off the top of my head how to do it just yet, and at time of writing I foresee this as the biggest blocker. When implementing this I will probably start by creating the functions to get the internal name and such from a given compatibility tool, then generating the actual text entry that will go into the VDF file. Once we have that, it's a matter of inserting that block into the VDF file. And of course, like with any modification to Steam files like this, Steam will need to be restarted for these kinds of changes to take effect :-) I am interested in this feature, I think this is a good proposal. I don't have an estimate though, I really just work on STL when I'm free and work on whatever I'm motivated too, but since this part of the codebase is fresh in my head I am hoping to get around to this sooner rather than later. Thanks! |
Maybe something like this for inserting content? Example
Example 2:
|
I came up with a solution mostly based on the second solution you provided. The text is... not very elegant, but this works so far: compattoolmapping_line="$(( $( grep -n "CompatToolMapping" config.vdf | cut -d ':' -f1 | xargs ) + 1 ))"
new_block="\t\t\t\t\t\"123123123123\"\n\t\t\t\t\t{\n\t\t\t\t\t\t\"name\"\t\t\"Proton_stl\"\n\t\t\t\t\t\t\"config\"\t\t\"\"\n\t\t\t\t\t\t\"priority\"\t\t\"250\"\n\t\t\t\t\t}"
sed -i "${compattoolmapping_line}a\\${new_block}" config.vdf This gets the first line with The second line with "123123123123"
{
"name" "Proton_stl"
"config" ""
"priority" "250"
} The third line is the in-place edit, which your second solution taught me how to do. I had no idea what this was and had no idea So this above snippet does work, but it's not very readable. I guess it doesn't really have to be, though. I'd prefer create a more generic function for inserting sections into text-based VDF files, and specifying/guessing the indentation level required, and appending the tab characters as-needed. But at a core level, this will work, albeit it's ugly and not very flexible :-) I don't think the indentation matters that much as Steam will probably correct it (didn't test it yet), I also assume Steam would re-order the entries. Steam is pretty good at keeping the internal structure of its files organised, but it's also very good at rejecting bad content in files to avoid corruption, so it could go either way without the indentation :-) This code also does not do any checks for an existing entry in this VDF file, which we'd also probably want to do. Since Steam tries to be smart about its internal files it will probably just remove one (or both) of the entries, but we want to make sure there is only one entry and that it is valid. Maybe to solve this, another generic function that should be created is one to update an existing CompatToolMapping entry by AppID, and if it doesn't exist, create that entry. Might be a lot of work but I like this idea the most, it gives the greatest flexibility :-) |
yeah if only they use json like sane human beings |
JSON has been around since the early 2000s I believe, but likely when Steam was being developed, JSON was not as much of a standard and there was probably not as many standard libraries to parse JSON, especially for C++ back in the day. Steam launched in 2003 and was in use before that as DRM. Probably, Valve made their own format so that they would have that control. VDF was also probably used by Source and such so there was opportunity for reuse, where there wouldn't have been with JSON. Having said that, they've also had 20 years to change that. Steam has also started using more and more web technologies (the whole client uses CEF now, and the library uses React). So they definitely have a lot more scope nowadays, unless Source 2 is still reliant on VDF files. So historically I can see why JSON wasn't chosen, and maybe nowadays it's just too much work to change over to JSON. If it ain't broke, don't fix it, I guess. VDF is also used heavily throughout the Steam client; one look through |
Wrote a completely crazy, insane, messy function to do this. To say this is rough would be an understatement. Here goes: ## Generate entry in given VDF block with matching indentation
## TODO variable naming could be improved a LOT here
function generateVdfEntry {
BLOCKNAME="$1" # Block to start from, e.g. "CompatToolMapping"
NEWBLOCK="$2" # Name of new block, e.g. "<AppID>"
# Arr will look like this, we use a '"' as the delimiter because we know names can't start with this!
# ( 'name"Proton_stl' 'config"' 'priority"250' )
KEYVALARR=(${@:3}) # Nutty stuff for Bash weirdness... Basically create array of all arguments and skip first two, since we know the third value is the array of key/value pairs for VDF block
VDFENTRYSTR="" # String to printf out in the end, this will be a string formatted version of the VDF block to write out
# Indentation for entries in this block to start at (i.e. if BLOCKNAME is preceded with 4 tabs, this will make entries start at 5
BASETAB="$(( $( grep "${BLOCKNAME}" config.vdf | awk '{print gsub(/\t/,"")}' ) + 1 ))"
BLOCKTAB="$(( $BASETAB + 1 ))" # Tabs for content inside the new block, which will be 1 more than the base, which is 1 more than its parent block
BASETABSTR="$( printf '%.0s\t' $(seq 1 $BASETAB) )"
BLOCKTABSTR="$( printf '%.0s\t' $(seq 1 $BLOCKTAB) )"
# Line to start appending new entry from
STARTLINE="$(( $( grep -n "${BLOCKNAME}" config.vdf | cut -d ':' -f1 | xargs ) + 1 ))"
VDFENTRYSTR+="${BASETABSTR}\"${NEWBLOCK}\"\n" # Beginning of new block
VDFENTRYSTR+="${BASETABSTR}{\n" # Opening brace
for i in "${KEYVALARR[@]}"; do
# New VDF block content
# Assume '"' is our delimiter
VDFDATAKEY="$( echo "$i" | cut -d '"' -f1 )"
VDFDATAVAL="$( echo "$i" | cut -d '"' -f2 )"
VDFENTRYSTR+="${BLOCKTABSTR}\"${VDFDATAKEY}\"\t\t\"${VDFDATAVAL}\"\n"
done
VDFENTRYSTR+="${BASETABSTR}}" # Closing brace
printf "$VDFENTRYSTR"
sed -i "${STARTLINE}a\\${VDFENTRYSTR}" config.vdf
}
# Associative arrays were not used because I wanted to preserve order here, not hash oder
NONSTEAMAPP_VDFENTRY=( 'name"Proton_stl' 'config"' 'priority"250' )
generateVdfEntry "CompatToolMapping" "3981288418" "${NONSTEAMAPP_VDFENTRY[@]}" This function builds a string with escape characters to write out to a text-based VDF file. It takes the name of a block to insert a new block into (such as A few changes will probably be made overtime before I even dream of implementing this in STL. The four most notable things are: variable naming here is rough (it's almost 3am for me 😴), I don't like how we pass the array (it makes the function call cleaner but the implementation messier, with how we slice the function arguments, Well, this is a start on an implementation at least. This will write out to the VDF file, to the top of the given block. Though personally I would prefer to write this out to the bottom of the given block. I will try to find a way to do this as well. |
Well, Steam doesn't re-organize the VDF entries, and I don't feel too good about having those being at the top of the entries list. I would really rather have these at the bottom of the For now, I'll focus on cleaning up this function and seeing if I can improve the things I don't like. I confirmed that this will actually write out a compatibility tool (though I made a small typo, the STL internal name is |
I guess you'll find a different way but here's what I got for finding the last line before the end of the CompatToolMapping block (which you could then sed/append the resulting block) as an example:
|
Yeah I used sed to get the full Had to use This basically just starts a search with a start and end pattern. Here, the start pattern is I haven't done it yet, but it should be possible from here to insert something between the last and second last lines. I appreciate posting these solutions though, I'm far from an expert with Bash so seeing other approaches is very cool and also good for anyone looking back on the history of this issue to see the discussion 👍 I used the knowledge here to write another little script which can parse |
How do you know other users config vdfs will all have the same indentation, is that required by how the file is created/managed by the vdf library? |
Yes, much like JSON you should be able to guarantee the indentation level. At least checking my Steam Deck, this matches. It may be worth my checking other PCs though just to make sure. Casing, however, is not guaranteed, as ProtonUp-Qt often has this issue. For some strange, unknown reason, VDF files recently have inconsistent casing. |
Over the course of the day, I have been experimenting and creating some generic Bash functions to parse text-based VDF files, almost exclusively testing against The main one missing that I'm still tinkering around with locally is the method to write out the VDF entry. The function I have locally uses many of the methods in the linked repository, and while it has been refactored a fair bit from what I posted earlier, there are three main things I want to improve upon with it:
I checked, and Steam appears to append new VDF entries to the bottom of a block, at least for It should be possible to insert a block of text before the final closing brace of the section. Not sure how to do it yet, but I will work on it. EDIT: Had a brainwave on this and feel dumb for not thinking of this yet, but we can choose where to insert by calculating the line to insert into. We already do this for the start line, so to insert into the end of the section, we can just take the startline, add the length of the I don't think inserting before/after a given entry is that useful having thought about it some more. I don't see a case where you would need one entry before/after another, but having the option to insert in the top/bottom of a block is useful imo. |
Okay, I've gotten things figured out for the most part now. I got the function to write out to the AppID working, and it can insert into either the top or the bottom of a given VDF block. By default, it appends to the bottom of the block. There are probably some more safety checks that could/should be done before writing out to the VDF, but for now, this should work and shouldn't bork the I have some more testing to do, and then I will open a draft PR, and it will be a very rough draft because I haven't figured out any mapping of the Proton names to the I didn't test the implementation I came up with outside of my own More to come soon hopefully! |
Draft PR is up at #908 which has the VDF utility functions in place, and some basic logic to write out the selected compatibility tool to the VDF file. The list on the UI is hardcoded right now, but from the commandline, it will accept whatever value you pass in (though it has to be the tool internal name). The flag for passing the compatibility tool is If you or anyone else wants to test you're more than welcome to, keeping in mind that this PR is in draft status, and that it has only been tested on my PC. If anyone is welling to test, PLEASE BACK UP YOUR I'm happy with the progress I was able to make on this today, we're most of the way to a working implementation. |
It has been a whirlwind this weekend but I've made good progress since my last comment. The linked PR should implement this feature now. I have implemented basic text-based VDF interaction, as well as logic to fetch a Proton version's internal tool name based on the name and path string from In my testing so far, everything appears to be smooth sailing. The Proton list and logging looks healthy, internal names are fetched properly, the config.vdf is written out to properly as well. One caveat with the last one is that Steam will overwrite any changes made to This feature should hopefully be implemented soon :-) |
Please see comments at the bottom of #738 for more context
We have the App ID now, so we should be able to configure proton compatibility to Non-Steam Games.
In my own script I'm doing something like the following (Obviously you wont be using vdf just including the example for context):
The text was updated successfully, but these errors were encountered: