-
Notifications
You must be signed in to change notification settings - Fork 5
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
Changing value #29
Comments
Just create a wrapper |
Awesome, that works! I'm also trying to figure out how to add new objects or properties if they don't exist. Would you be able to point me in the right direction for that? Thank you, again! |
Vdf.NET is modeled after Json.NET. Most of the logic remains the same - https://stackoverflow.com/questions/15413825/how-do-you-add-a-jtoken-to-an-jobject. Create any new |
Awesome. So I mguessing the final step here is to reserialize the the object (volvo) and then write that to a file, right? |
Just depends on what you want to do with it. This library only deals with the data format and serialization/deserialization. |
I just wanted to rewrite the file with the new entries I added. When I do this, though, all of the properties in the file lose their proper spacing. I have tried setting the serialize settings, as well, but that didn't help. example of how it looks originally
how it looks after
I haven't changed any of these properties. |
Actually, I just found out something unfortunate. It seems that even if I were to be able to rewrite the file, Steam as some kind of feature that checks if the file has been modified and restores it. Do you know if there is a way around this? I am editing the localconfig.vdf in F:\Steam\userdata{user}\config |
Vdf.NET doesn't store whitespace information on deserialization. So it cannot be recreated when serializing. https://github.com/shravan2x/Gameloop.Vdf/issues?q=localconfig |
so I make my changes like so: foreach (var value in ((VProperty)game).Value)
{
((VProperty)value).Key = "template";
((VProperty)value).Value = new VValue($"controller_{system}_gamepad_joystick.vdf");
Console.WriteLine("changed");
} and write like this according to what you said in the other thread File.WriteAllText(file[0], VdfConvert.Serialize(volvo), Encoding.UTF8); but steam does actually overwrite the changes I made. Is this new? Also, does steam not care about these whitespaces, if it is possible to change these files? I've tried changing them on two separate computers to no avail. |
BTW, I think this behavior could possibly be patched in, as it seems that the whitespace is just two tabs, and it seems to only apply when it's in a line that's written with a key-value pair. Possibly change the VDF text writer to ad two tabs to the value, and possibly check if it's a key value pair being written in one line? IDK. Thought I would mention it, and I might mess around with the source code later to see if I can. Anyways, thanks for your time! Edit: I notice there is a whitespace between those pairs, and if you replace all of them with \t\t that could also work. I just don't know if that would work for all files, which is why I suggest it here. in fact, this code is how I solved it temporarily. var replaceWhitespace = VdfConvert.Serialize(volvo);
replaceWhitespace = replaceWhitespace.Replace("\" \"", "\t\t");
File.WriteAllText(file[0], replaceWhitespace, Encoding.UTF8); |
Okay, so I wrote some code to test this, and it seems like the PR I sent you works for most steam files. Basically what I did was I created an original and modified folder on my desktop, and put all my steam.vdf files in the original one. I deserialized every files and then serialized and wrote it back. I then ran each file through a checksum comparison and printed out the files it didn't work for. Of-course, if I just serialize and write it, none of them match. Maybe you know a more elegant way to put in the tabs? :) Here are the results
Here is the code static void Main(string[] args)
{
var files = Directory.GetFiles(@"C:\Users\Nordgaren\Desktop\VDFExperiment\Original\");
foreach (var file in files)
{
try
{
dynamic vdf = VdfConvert.Deserialize(File.ReadAllText(file));
var rewritten = file.Replace("Original", "Modified");
File.WriteAllText(rewritten, VdfConvert.Serialize(vdf), Encoding.UTF8);
}
catch
{
}
}
int isTrue = 0;
int isFalse = 0;
foreach (var file in files)
{
var rewritten = file.Replace("Original", "Modified");
var og = GetChecksum(file);
var md = GetChecksum(rewritten);
if (og == md)
isTrue++;
if (og != md)
{
isFalse++;
Console.WriteLine(file);
}
}
Console.WriteLine($"Match: {isTrue}");
Console.WriteLine($"No Match: {isFalse}");
Console.ReadLine();
}
public static string GetChecksum(string filename)
{
using (var hasher = HashAlgorithm.Create("SHA256"))
{
using (var stream = File.OpenRead(filename))
{
var hash = hasher.ComputeHash(stream);
return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
}
}
} |
It seems that you'd need to somehow add these values when creating the key value pairs on the single line. I don't know if that even makes sense. I also found a bug that has more to do with steam being silly than anything. If you look at your Steam/cached/countrylist.vdf you'll see that there are no quotes on the top object or property, like most files. If you deserialize and reserialize, it shows up with the quotes. Kinda funny. Interesting things valve does. |
I don't see a PR from you. Did you forget to send one?
In any case that I'm aware of, Valve's parser does not care about whitespace. I'm skeptical that the issue you're facing is caused by whitespace differences, unless there has been a recent regression. Could you confirm that the behavior you were seeing before (Steam reverting changes) no longer occurs when you use tabs instead of spaces? If this is the case, could you include specific repro steps so I can confirm it on my end too?
I wouldn't expect the re-serialized files to have their hashes match - for this to be the case, every byte needs to be the exact same as before. In general, it's not the goal of Vdf.NET to produce exact re-serializations. I think whitespace modifications are ok as long as they don't trip up Valve's own parser (there's still some old copies of their code floating around).
Valve is not very consistent in their data formats, it's up to us to deal with it. This library supports reading-in unquoted tokens but does not store that as a quoted/unquoted flag. There just didn't seem to be a need for it. If for some reason this becomes an issue I'll be happy to add it in. |
No, I think this is a thing steam has been doing if you use their cloud service, which means that changing the vdf in the case I want to use it, it wouldn't be guaranteed to work. Here's one thread I found that described the behavior as well, and there were quite a few more I found the other night. I can go looking for them again, if you'd like. So I agree that it's probably not the whitespace that is the problem. It's steams own internal services. I used Notepad++ to confirm this. I changed the value in the file, booted up a game and Notepad++ immediately notified that the file had been updated, so I click yes to reload the file and see the change happen. If, in the future, someone does need to add the tabs, the best solution without making changes to the library is the code that I posted (and updated) above. I'm new to GitHub, and programming in general, so I'll just post the simple change I made here. I changed the serialize return, basically, to do the replacement instead of having to serialize to a string and do the replacement that way. You can test it out if you'd like. I'm pretty sure the tabs would only be in a place where there's two quotation marks surrounding a whitespace, but I'm not 100% on this, as I only opened and looked at a few files. public static string Serialize(VToken value, VdfSerializerSettings settings)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
StringBuilder stringBuilder = new StringBuilder(256);
StringWriter stringWriter = new StringWriter(stringBuilder, CultureInfo.InvariantCulture);
(new VdfSerializer(settings)).Serialize(stringWriter, value);
return stringWriter.ToString().Replace("\" \"", "\t\t");
} Thanks again for the convo. I learned some stuff from this. |
Thanks for confirming, I wasn't familiar with that particular behavior. You might want to combine updating the VDF with sending the new copy to Steam's servers. That would require working with protobufs using SteamKit.
Simply using
Happy to help! I'll go ahead and close this issue now but feel free to comment if there's anything else. |
I have been able to narrow down the values I want to change, but haven't been able to figure out how to cast it to the VToken.
trying to do something like this
Thank you in advance!
The text was updated successfully, but these errors were encountered: