question

opportunitiesgames avatar image
opportunitiesgames asked

Implement LeaderBoards in Corona SDK

Hi guys,

I'm trying to implement leaderboards in my Corona SDK game but there is little to none information on how to really implement all the playfab features in Corona SDK.

I've got my user successfully logged in, but can't find how to make the calls to the server. This is what I've got so far for my leaderboard implementation:

function M.uploadHighScore(highscore)
    local function networkListener( event )


        if ( event.isError ) then
            print( "Network error: ", event.response )
        else
            print ( "Upload complete!" )
        end
    end


    local headers = {}


    headers["Content-Type"] = "application/json"
    headers["X-API-Key"] = "13b6ac91a2"


    local params = {}
    params.headers = headers


    -- Tell network.request() to get the request body from a file:
    params.body = {
        filename = "object.json",
        baseDirectory = system.DocumentsDirectory
    }


    network.request( "https://XXXX.playfabapi.com/Client/UpdatePlayerStatistics", "POST", networkListener, params )
end

(I replaced the XXXX in the link with the correct code)

But I need the user_session_ticket_value for the X-API-KEY part. But how do I get that in Corona? And if I want to upload a single value (highscore = 6), will I have to convert that into a json table?

I'm very new to this so don't throw to many fancy words at me :)

Kind regards

Bram

sdksLeaderboards and Statistics
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

opportunitiesgames avatar image
opportunitiesgames answered

Sure thing:

    local function successFunction(result)
        local json = require("json")
        print("Leaderboard pulled")
        test = json.prettify(result)
        print("test: " .. test)
        leaderboardTable = json.decode(test)
        print("Position: " .. leaderboardTable.Leaderboard[1].StatValue)
        worldHighScore = leaderboardTable.Leaderboard[1].StatValue
    end
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image
brendan answered

What you'll want to do is get the plugin for Corona (here's the client plugin: https://marketplace.coronalabs.com/plugin/playfab-client) and install it in your project. There's an example of how to do that, and of how to make your first call in the readme, here: https://github.com/PlayFab/LuaSdk/tree/master/Corona#client-plugin-instructions.

Once you've got your Title ID set in the project, all the calls are made the same way, and we handle the headers - there's no need to construct network requests directly. You just call

PlayFabClientApi.<ApiName>(request, function(result) end, function(error) end)

for each API method. The request will vary from call to call, but for UpdatePlayerStatistics - and specifically to set highscore to 6, it would be like so:

local request = {
    Statistics = {
        { StatisticName = "highscore", Value = 6 }
    }
}
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

opportunitiesgames avatar image
opportunitiesgames answered

Hi Brendan, thanks for the extremely fast reply!

So I've got this code now:

local function uploadHighScoretime()
    local request = {
        Statistics = {
            { StatisticName = "highscore", Value = 6 }
        }
    }
    PlayFabClientApi.UpdatePlayerStatistics(request, function(result) print("Updated Stats Successfully!") end, function(error) print("Error Updating Stats!") end)
end
timer.performWithDelay(1000, uploadHighScore)

But it is not printing anything out. It's like nothing is executed. I am using the timer to make sure the code is run after the user has logged in.

Any thoughts?

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

opportunitiesgames avatar image opportunitiesgames commented ·

Never mind, I got it to work! My scene was ending before the code could be executed :)

But I've got one more question. The leaderboards is only storing the highest value, I'd like to at least keep track of the top 3. How could I do that?

0 Likes 0 ·
brendan avatar image
brendan answered

You can configure any statistic to the "Max" aggregation method either via the Admin API or in the Game Manager (click to edit the leaderboard). Setting a stat to "Max" aggregation means "only update with the new value if it's greater than the current value for the player".

For the "top 3", do you mean for a single player? A leaderboard contains a single row per player. If you need to track the top 3 scores for every player, you would need to do a more complex implementation: Get the current values for the player, determine if it's greater than any of the player's top three scores, then update appropriately (pushing the previous value down to slot two or three, etc., as needed). That does mean you would lose some of the advantage you get from the Max aggregation model, as you would have to be doing comparisons (and if two scores were reported back-to-back, you could then have an issue with the top 3 not being correct for the player).

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

opportunitiesgames avatar image
opportunitiesgames answered

Hi Brendan, thanks for the quick replies! Just one more question, the leaderboards are updated correctly but now I'm trying to read them from the server by using this code:

        if isLoggedIn then
            print("getting highscores")
            local request = {
                StatisticName = "highscore",
                StartPosition = 0,
                MaxResultsCount = 1
            }
            PlayFabClientApi.GetLeaderboard(request, function(result) print("Leaderboard available, result: " .. result) end, function(error) print("Error Updating Stats!") end)
        end

The user got logged in correctly and the first print statement is showing up, but the GetLeaderboard request is never triggered. I'm not getting any result prints. Am I doing something wrong here?

Also how would I store the received data?

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image
brendan answered

What's the actual function you're passing the results to? That would be the place to collect the results and assign them to some longer-term storage in the client code. Can you have a look at the PlayFabTesting example in the SDK and see how we demonstrate this there?

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

opportunitiesgames avatar image
opportunitiesgames answered

Hi @Brendan, there is only a login example for Corona SDK.

I've got this code at the moment:

    local function successFunction(result)
        print("Leaderboard pulled")
        for key, value in pairs(result) do
            print(key, value)
        end
    end
    PlayFabClientApi.GetLeaderboard(request, successFunction, function(error) print("Error Updating Stats!") end)

I tried getting the result values but just can't figure out howto... My print statement in my for loop is triggered but it's returning: 0xdbbbdec0...

I thought I could get the value by doing this:

myValue = result.Leaderboard.StatValue

But that didn't work :/

Any thoughts?

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image
brendan answered

What you're actually getting back in the result is what you see in the API call (https://api.playfab.com/Documentation/Client/method/GetPlayerStatistics). So, the response contains a Statistics, which is an array of the stats returned, with each having a StatisticName, a Value, and a Version. Since this is in JSON format, the simplest thing for you to do might be to use json.decode to convert it to a data object you can then work with.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

opportunitiesgames avatar image
opportunitiesgames answered

So I tried doing this:

    local function successFunction(result)
        local json = require("json")
        print("Leaderboard pulled")
        myTable = json.decode(result)
        for k, v in pairs(myTable) do
            print(k, v)
        end
    end
    PlayFabClientApi.GetLeaderboard(request, successFunction, function(error) print("Error Updating Stats!") end)

Still no luck... I'm trying to get the leaderboard btw, not the getplayerstatistics :)

Any other thoughts?

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image
brendan answered

This code expects that the result from the GetLeaderboard call is a simple dictionary. which is not the case. It is a JSON object where the root is a Leaderboard. The Leaderboard is an array of entries, each of which contains a PlayFab ID, Statistic Value, Display Name, and Leaderboard Position. So you'll need to process it that way, in order to retrieve the specific information you need from it.

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.