Skip to main content

GDLevel

Struct GDLevel 

Source
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: GDLevelIdentity

Identity info: ID, name, descriptior, creator, version, level type, password

§content: GDLevelContents

The level’s data: object data, song list, used song ID, length, is platformer/2-player

§ratings: GDLevelRatings

Rating info: downloads, likes, stars, requested stars, epic rate, difficulty, type of demon, is auto

§coins: GDLevelCoins

Coin info: required coins, obtainment status of coins

§player_stats: GDLevelPlayerStats

Player-obtained stats: attempts, jump, percentage, best attempt time, completions, leaderboard standing, verification time, level progresses

§flags: GDLevelFlags

Boolean flags: is editable, is verified, is uploaded, is unlisted, etc.

§editor_state: GDLevelEditorState

State of level in editor: camera position and zoom, build tab pages, last selected layer

§meta: GDLevelMeta

Internal data: kCEK, folder, seconds spent editing, level size, batch node info, capacity string

§integrity: GDLevelIntegrity

Integrity/verification info: level seed, was anticheat triggered, replay data, vFDCHk

§unknowns: GDLevelUnknowns

Unaccounted 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

Source

pub fn from_gmd<T: Into<PathBuf>>(path: T) -> Result<Self, GDError>

Parses a .gmd file to a Self object

Examples found in repository?
examples/minimal.rs (line 8)
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
Hide additional examples
examples/seed_crack.rs (line 14)
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}
Source

pub fn export_to_gmd<T: Into<PathBuf>>(&self, path: T) -> Result<(), GDError>

Exports the level to a .gmd file

Examples found in repository?
examples/minimal.rs (line 19)
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}
Source

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.

Source

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?
examples/seed_crack.rs (line 15)
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}
Source

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?
examples/minimal.rs (line 11)
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}
Source

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

Source

pub fn add_objects<I: IntoIterator<Item = GDObject>>(&mut self, objects: I)

Adds an iterator of GDObjects to self.objects

Source

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.

Source

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.

Source

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.

Trait Implementations§

Source§

impl Clone for GDLevel

Source§

fn clone(&self) -> GDLevel

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for GDLevel

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for GDLevel

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Display for GDLevel

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.