I’m trying to add a highscore system to my game based on the examples in https://github.com/britzl/playfabexamples and am stuck on having the player logged in so their scores can be added to the highscore list.
I see that some things have changed since the examples were written so I’ve updated lines in in authentication.lua like
local auth = savetable.open("auth").load()
to
local auth = savetable.load("auth", savetable.FORMAT_SYS)
For the line
local response, error = playfab.LoginWithPlayFab.flow(request)
I get
ERROR:SCRIPT: /playfab/authentication.lua:94: attempt to index field ‘LoginWithPlayFab’ (a function value)
And don’t understand how to fix it. If I remove the “.flow” part the line executes but I get ‘nil’ as the response and error.
The example you looked at provides a coroutine based sequential way of calling the functions as well:
local response, error = playfab.LoginWithPlayFab.flow({})
if error then
print(error)
return
end
local response, error = playfab.GetUserData.flow({})
if error then
print(error)
return
end
handle user data
local response, error = playfab.GetLeaderboardAroundPlayer.flow({})
if error then
print(error)
return
end
This is only possible if the PlayFab API is modified to support coroutines as well. The setup for this happens here:
Yes, so you need call the playfab.LoginWithPlayFab function from within a coroutine. Like this (you can also use the flow module but it is not strictly needed):
-- create and immediately start coroutine
coroutine.wrap(function()
local response, error = playfab.LoginWithPlayFab.flow(request)
end)()
Ok thanks again! I do like the flow look of the code compared to the nested callbacks.
I’m unsure of how much of my code should be wrapped in the coroutine. Does this look ok?
function M.login(username, password)
local auth = savetable.load("auth", savetable.FORMAT_SYS) or {}
auth.username = username or auth.username
auth.password = password or auth.password
if auth.username and auth.password then
local request = {
TitleId = playfab.settings.titleId,
Username = auth.username,
Password = auth.password,
}
coroutine.wrap(function()
local response, error = playfab.LoginWithPlayFab.flow(request)
if error then
auth.username = nil
auth.password = nil
M.listeners.trigger(M.LOGIN_FAILED, error)
else
auth.response = response
pprint(response)
M.listeners.trigger(M.LOGIN_SUCCESS, response)
end
end)()
savetable.save(auth)
return response, error
else
-- code continues....
Your suggestion will not work. It is only the code within the coroutine that will run in sequence and as soon as the code in the coroutine hits something async (such as playfab.LoginWithPlayFab) the code will stop while waiting for the response and the code outside will continue to run. Consider this: