You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Can you create a documentation page on how to convert gvas into my own structs? Its very hard to work with the GvasFile directly and I do not understand how accessing data works.
I want to make a save editor. Could you explain how to modify the data inside rust? gvas.txt
Not sure what you mean by convert into your own structs, but if you wanna access and edit data you can look for examples in the tests folder, here's one of them
The GvasFile struct is a wrapper around all of the the things that are needed to recreate the original binary file. For a save editor, you will be primarily interested in looking at the properties map, which is where the game's persisted data is stored.
@scottanderson The problem im facing is I dont understand how to navigate the properties. There are nested lists, structs and objects and idk how to extract information? In json I would just do json["foo"]["bar"] etc. but what do I do here?
Understanding how to navigate the properties map can be challenging due to its variability across different games. Each game may store data differently; some use simple arrays while others employ custom structs. This library accommodates these variations with a flexible structure.
The structure of each property is a Property enum wrapper around a specific property type. For example, if you wanted to store a simple string in a GVAS file, you would actually need to wrap that string in all of the following layers to store it:
An Option, to give the string nullability.
A StrProperty to represent the UE type of the string.
A Property enum to act as a common property type that rust can store in a map.
Some properties are themselves also enums, especially the container types (array, map, etc.). This is primarily done to make the serde serialized output flatter, more readable and concise.
If you prefer to work in JSON, you can use serde to convert a GvasFile to another format. There's also a cli wrapper for this that you may be interested in, which doesn't require you to write any code at all. See gvas2json.
The reason I mentioned serde support is that the file that you shared earlier uses the Debug trait representation. In this crate, the serde representation of a GvasFile is much easier to understand than the Debug trait's representation of the data, so I recommend that you use serde_json::to_string instead of the Debug trait to provide a clearer view of the data.
This project focuses on serializing and de-serializing the GVAS format itself, rather than interpreting the specific game data encoded in GVAS files. For instance, Railroads Online stores different aspects of spline tracks in separate ArrayProperty arrays—each for start locations, end locations, tangents, etc.. This crate handles these ArrayProperty types, but doesn’t inherently understand how these arrays relate to the game's SplineTrack objects. Here’s a simplified representation of such data:
From the Debug trait output you attached earlier, it looks like your StructProperty values are StructPropertyValue::CustomStructs. These discriminants use a Vec<(String, Property)> to represent a custom properties map. Each entry in the Vec is a tuple of one property name and one property value.
If you do not need to support array property values in the CustomStruct, you can coerce that Vec<(String, Property)> to IndexMap<String, Property> with collect() to make it easier to work with.
use indexmap::IndexMap;fnvec_to_indexmap(vec:Vec<(String,Property)>) -> IndexMap<String,Property>{// This will cause data loss if the input vec contains a property array!// See PR #102 for more information about this issue.
vec.into_iter().collect()}fnindexmap_to_vec(map:IndexMap<String,Property>) -> Vec<(String,Property)>{
map.into_iter().collect()}
Activity
scottanderson commentedon Jun 30, 2024
Crate docs are available at https://docs.rs/gvas/latest/gvas/, but they might be incomplete.
Swarkin commentedon Jun 30, 2024
Can you create a documentation page on how to convert gvas into my own structs? Its very hard to work with the GvasFile directly and I do not understand how accessing data works.
I want to make a save editor. Could you explain how to modify the data inside rust?
gvas.txt
localcc commentedon Jun 30, 2024
Not sure what you mean by convert into your own structs, but if you wanna access and edit data you can look for examples in the
testsfolder, here's one of themscottanderson commentedon Jun 30, 2024
The
GvasFilestruct is a wrapper around all of the the things that are needed to recreate the original binary file. For a save editor, you will be primarily interested in looking at thepropertiesmap, which is where the game's persisted data is stored.Swarkin commentedon Jul 1, 2024
@scottanderson The problem im facing is I dont understand how to navigate the
properties. There are nested lists, structs and objects and idk how to extract information? In json I would just do json["foo"]["bar"] etc. but what do I do here?I sent my gvasfile above for reference.
scottanderson commentedon Jul 2, 2024
Understanding how to navigate the properties map can be challenging due to its variability across different games. Each game may store data differently; some use simple arrays while others employ custom structs. This library accommodates these variations with a flexible structure.
The structure of each property is a
Propertyenum wrapper around a specific property type. For example, if you wanted to store a simple string in a GVAS file, you would actually need to wrap that string in all of the following layers to store it:Option, to give the string nullability.StrPropertyto represent the UE type of the string.Propertyenum to act as a common property type that rust can store in a map.The result is an object that looks like:
Some properties are themselves also enums, especially the container types (array, map, etc.). This is primarily done to make the serde serialized output flatter, more readable and concise.
If you prefer to work in JSON, you can use serde to convert a GvasFile to another format. There's also a cli wrapper for this that you may be interested in, which doesn't require you to write any code at all. See gvas2json.
Swarkin commentedon Jul 21, 2024
Im having problems specifically with the Struct properties and how I access things inside them or how I can serde them into my own structs.
scottanderson commentedon Jul 22, 2024
Hi @Swarkin,
The reason I mentioned serde support is that the file that you shared earlier uses the
Debugtrait representation. In this crate, the serde representation of aGvasFileis much easier to understand than theDebugtrait's representation of the data, so I recommend that you useserde_json::to_stringinstead of theDebugtrait to provide a clearer view of the data.This project focuses on serializing and de-serializing the GVAS format itself, rather than interpreting the specific game data encoded in GVAS files. For instance, Railroads Online stores different aspects of spline tracks in separate
ArrayPropertyarrays—each for start locations, end locations, tangents, etc.. This crate handles theseArrayPropertytypes, but doesn’t inherently understand how these arrays relate to the game's SplineTrack objects. Here’s a simplified representation of such data:From the Debug trait output you attached earlier, it looks like your
StructPropertyvalues areStructPropertyValue::CustomStructs. These discriminants use aVec<(String, Property)>to represent a custom properties map. Each entry in theVecis a tuple of one property name and one property value.If you do not need to support array property values in the CustomStruct, you can coerce that
Vec<(String, Property)>toIndexMap<String, Property>withcollect()to make it easier to work with.