GeometryDashAPI icon indicating copy to clipboard operation
GeometryDashAPI copied to clipboard

level.Options.Ka1 does not give AudioTrack

Open RevolvingMadness opened this issue 10 months ago • 5 comments

Describe the bug When accessing Ka1 on LevelOptions it always returns 0

To Reproduce Steps to reproduce the behavior:

  1. Use property Ka1 on LevelOptions
  2. See that it always gives 0

Expected behavior It should return the AudioTrack instead of 0

https://wyliemaster.github.io/gddocs/#/resources/client/level-components/level-start

RevolvingMadness avatar Jan 11 '25 21:01 RevolvingMadness

I've tried to reproduce the example on the v0.2.29 And this looks fine

[TestFixture]
public class LevelTests
{
    [Test]
    public void AudioTrack()
    {
        var level = new Level();
        level.Options.Ka1 = 10;

        var result = level.SaveAsString(compress: false);
        result.Should().Contain("kA1,10");

        level = new Level(result.Replace("kA1,10", "kA1,111"), compressed: false);
        level.Options.Ka1.Should().Be(111);
    }
}

So I want to ask a couple of questions.

Which framework are you using? .NET Framework or .NET (Core) How can I reproduce this behavior through the game?

The reason I'm asking the last question is because kA1 looks obsolete. There are an alternative ways to get Audio Track[^1]:

[TestFixture]
public class LevelTests
{
    [Test]
    public async Task AudioTrack()
    {
        // for online levels
        var client = new GameClient();
        var response = await client.SearchLevelsAsync(new Server.Queries.GetLevelsQuery(Server.Enums.SearchType.Featured));
        var page = response.GetResultOrDefault();
        var levelInfo = page.Levels.FirstOrDefault();
        if (levelInfo.MusicId > 0)
        {
            // retrieve additional info of custom track
            var track = page.Musics.FirstOrDefault(x => x.MusicId == levelInfo.MusicId);
        }
        else
        {
            var officialAudioTrack = levelInfo.OfficialSong;
        }

        // for "my levels" page
        var local = await LocalLevels.LoadFileAsync();
        var localLevel = local.First();
        var musicId = localLevel.MusicId;
        var customMusic = localLevel.CustomMusic; // indicates that official or custom
    }
}

In addition, these methods allow you to get an audio track without loading the entire level into memory. Some levels may take up more than 100 MB of RAM. RobTop also forbids loading online levels too often.

[^1]: The code is incomplete, at each stage you need to perform state checks before relying on calling the First methods.

Folleach avatar Jan 12 '25 10:01 Folleach

The way you showed me using MusicId works but I was calling .LoadLevel() and accessing .Options.Ka1

My .NET version is 7.0.410 and I'm pretty sure I'm using .NET core

I created a level and made it use the song id 123. I used the code:

var localLevels = await LocalLevels.LoadFileAsync();
var level = localLevels.GetLevel("<level name>");
var loadedLevel = level.LoadLevel();
var songID = loadedLevel.Options.Ka1;
Console.WriteLine(songID); // Is 0, not 123

RevolvingMadness avatar Jan 13 '25 22:01 RevolvingMadness

Looks like the game doesn't use Ka1 now. Because when I was developing the library, I couldn't make Ka1 non-0. Might the second example from the comment above be suitable for you?

var localLevels = await LocalLevels.LoadFileAsync();
var level = localLevels.GetLevel("<level name>");

var songID = level.MusicId;
Console.WriteLine(songID); // should be 123

You can check for yourself whether the game set Ka1 if you reach this line in debug mode. data variable will contain the full string representation of the level

Folleach avatar Jan 14 '25 15:01 Folleach

I am downloading a level from the servers and saving it into a text file (not encrypted) and later in my program I want to read the level from the text file and get the song id. I could use MusicId but that is only present on LevelCreatorModel, not Level

RevolvingMadness avatar Jan 14 '25 22:01 RevolvingMadness

I think in that case you can save metadata about level. This will allow you to find out song id, author, name of the level, likes and etc later, because this information is not present in the content of level. For example you can use json format, like this cli utility for Geometry Dash: https://github.com/Folleach/GeometryDash.Console?tab=readme-ov-file#featured

Folleach avatar Jan 15 '25 10:01 Folleach