pub struct GDLevel {
pub identity: GDLevelIdentity,
pub content: GDLevelContents,
pub ratings: GDLevelRatings,
pub coins: GDLevelCoins,
pub player_stats: GDLevelPlayerStats,
pub flags: GDLevelFlags,
pub editor_state: GDLevelEditorState,
pub meta: GDLevelMeta,
pub integrity: GDLevelIntegrity,
pub unknowns: GDLevelUnknowns,
}Expand description
The descriptor struct for GD levels which contains all known properties.
Reference: https://wyliemaster.github.io/gddocs/#/resources/client/level
Fields§
§identity: GDLevelIdentityIdentity info: ID, name, descriptior, creator, version, level type, password
content: GDLevelContentsThe level’s data: object data, song list, used song ID, length, is platformer/2-player
ratings: GDLevelRatingsRating info: downloads, likes, stars, requested stars, epic rate, difficulty, type of demon, is auto
coins: GDLevelCoinsCoin info: required coins, obtainment status of coins
player_stats: GDLevelPlayerStatsPlayer-obtained stats: attempts, jump, percentage, best attempt time, completions, leaderboard standing, verification time, level progresses
flags: GDLevelFlagsBoolean flags: is editable, is verified, is uploaded, is unlisted, etc.
editor_state: GDLevelEditorStateState of level in editor: camera position and zoom, build tab pages, last selected layer
meta: GDLevelMetaInternal data: kCEK, folder, seconds spent editing, level size, batch node info, capacity string
integrity: GDLevelIntegrityIntegrity/verification info: level seed, was anticheat triggered, replay data, vFDCHk
unknowns: GDLevelUnknownsUnaccounted for/unknown keys: k91, k92, k101, k106 and all other keys that didn’t fit in any other fields in this struct.
Implementations§
Source§impl GDLevel
impl GDLevel
Sourcepub fn from_gmd<T: Into<PathBuf>>(path: T) -> Result<Self, GDError>
pub fn from_gmd<T: Into<PathBuf>>(path: T) -> Result<Self, GDError>
Parses a .gmd file to a Self object
Examples found in repository?
6fn main() -> Result<(), GDError> {
7 // Load level from .gmd file
8 let mut level = GDLevel::from_gmd("test_gmds/level.gmd")?;
9
10 // Get level data, which is None only if it hasn't been initialized.
11 if let Some(data) = level.get_decrypted_data_ref() {
12 // Add group 42 to all objects
13 for obj in data.objects.iter_mut() {
14 obj.config.add_group(Group::Regular(42));
15 }
16 }
17
18 // Export level
19 level.export_to_gmd("test_gmds/generated_group_42.gmd")?;
20 Ok(())
21}More examples
13fn main() {
14 let level = GDLevel::from_gmd("test_gmds/Chompstep.gmd").unwrap();
15 let mut objects = level.get_decrypted_data().unwrap().objects;
16
17 // filter out all objects that are not advanced random triggers
18 objects.retain(|o| o.id == TRIGGER_ADVANCED_RANDOM && o.config.pos.0 > 0.0);
19 objects.sort_by(|a, b| a.config.pos.0.total_cmp(&b.config.pos.0));
20
21 // the group we want spawned for each trigger
22 // -1: any group is fine
23 let expected = vec![
24 2, -1, 2, -1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1, 2, 2, 2, 2, 2,
25 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
26 ];
27 let mut seed = 0;
28
29 // then try all of the seeds
30 // cap it out at 25 seeds because searching all of them is impractically slow on a CPU
31 while !crack_seed(seed, &expected[..25], &objects) {
32 seed += 1;
33 if seed % 1000000 == 0 {
34 println!("checked seeds until {seed}");
35 }
36 }
37
38 // the seed you get is guaranteed to get you to 79% on Chompstep
39 println!("got seed: {seed}");
40}Sourcepub fn export_to_gmd<T: Into<PathBuf>>(&self, path: T) -> Result<(), GDError>
pub fn export_to_gmd<T: Into<PathBuf>>(&self, path: T) -> Result<(), GDError>
Exports the level to a .gmd file
Examples found in repository?
6fn main() -> Result<(), GDError> {
7 // Load level from .gmd file
8 let mut level = GDLevel::from_gmd("test_gmds/level.gmd")?;
9
10 // Get level data, which is None only if it hasn't been initialized.
11 if let Some(data) = level.get_decrypted_data_ref() {
12 // Add group 42 to all objects
13 for obj in data.objects.iter_mut() {
14 obj.config.add_group(Group::Regular(42));
15 }
16 }
17
18 // Export level
19 level.export_to_gmd("test_gmds/generated_group_42.gmd")?;
20 Ok(())
21}Sourcepub fn decrypt_level_data(&mut self) -> Result<(), GDError>
pub fn decrypt_level_data(&mut self) -> Result<(), GDError>
Returns the Level data as unencrypted. Level data is left unencrypted when parsing the Level as it is slow.
Sourcepub fn get_decrypted_data(&self) -> Option<GDLevelData>
pub fn get_decrypted_data(&self) -> Option<GDLevelData>
Returns the decrypted level data as a GDLevelContents object if there is data.
Examples found in repository?
13fn main() {
14 let level = GDLevel::from_gmd("test_gmds/Chompstep.gmd").unwrap();
15 let mut objects = level.get_decrypted_data().unwrap().objects;
16
17 // filter out all objects that are not advanced random triggers
18 objects.retain(|o| o.id == TRIGGER_ADVANCED_RANDOM && o.config.pos.0 > 0.0);
19 objects.sort_by(|a, b| a.config.pos.0.total_cmp(&b.config.pos.0));
20
21 // the group we want spawned for each trigger
22 // -1: any group is fine
23 let expected = vec![
24 2, -1, 2, -1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, -1, 2, 2, 2, 2, 2,
25 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
26 ];
27 let mut seed = 0;
28
29 // then try all of the seeds
30 // cap it out at 25 seeds because searching all of them is impractically slow on a CPU
31 while !crack_seed(seed, &expected[..25], &objects) {
32 seed += 1;
33 if seed % 1000000 == 0 {
34 println!("checked seeds until {seed}");
35 }
36 }
37
38 // the seed you get is guaranteed to get you to 79% on Chompstep
39 println!("got seed: {seed}");
40}Sourcepub fn get_decrypted_data_ref(&mut self) -> Option<&mut GDLevelData>
pub fn get_decrypted_data_ref(&mut self) -> Option<&mut GDLevelData>
Returns a mutable reference to the decrypted level data as a GDLevelContents object if there is data.
This method calls Self::decrypt_level_data before attempt to return the decrypted level data.
Examples found in repository?
6fn main() -> Result<(), GDError> {
7 // Load level from .gmd file
8 let mut level = GDLevel::from_gmd("test_gmds/level.gmd")?;
9
10 // Get level data, which is None only if it hasn't been initialized.
11 if let Some(data) = level.get_decrypted_data_ref() {
12 // Add group 42 to all objects
13 for obj in data.objects.iter_mut() {
14 obj.config.add_group(Group::Regular(42));
15 }
16 }
17
18 // Export level
19 level.export_to_gmd("test_gmds/generated_group_42.gmd")?;
20 Ok(())
21}Sourcepub fn add_object(&mut self, object: GDObject)
pub fn add_object(&mut self, object: GDObject)
Adds a GDObject to self.objects only if self.content.data is already decrypted, otherwise nothing happens.
To decrypt the level data, see Self::decrypt_level_data or Self::get_decrypted_data_ref
Sourcepub fn add_objects<I: IntoIterator<Item = GDObject>>(&mut self, objects: I)
pub fn add_objects<I: IntoIterator<Item = GDObject>>(&mut self, objects: I)
Adds an iterator of GDObjects to self.objects
Sourcepub fn get_objects_ref(&self) -> Option<&Vec<GDObject>>
pub fn get_objects_ref(&self) -> Option<&Vec<GDObject>>
Returns a reference to self.content.data.objects if this Level has level data and if the data is decrypted.
Sourcepub fn get_objects_mut(&mut self) -> Option<&mut Vec<GDObject>>
pub fn get_objects_mut(&mut self) -> Option<&mut Vec<GDObject>>
Returns a mutable reference to self.content.data.objects if this Level has level data and if the data is decrypted.
Sourcepub fn get_objects_clone(&self) -> Option<Vec<GDObject>>
pub fn get_objects_clone(&self) -> Option<Vec<GDObject>>
Returns a copy of self.content.data.objects if this Level has level data and if the data is decrypted.