Problem with PlayFab (SOLVED)

Hey there.

I am trying to use the PlayFab for game-statistics.
I already read the Leaderboard and I already wrote some data to the Leaderboard.

Now, if I try to login in the current game and read the Leaderboard I’ll always get this error:

{
  error = ServiceUnavailable,
  errorCode = 1123,
  code = 0,
  status = 0,
  errorMessage = Could not deserialize reseponse from server: ,
}

…but I am already logged in. Seems like I have to wait after each command, synchronise. But how?

this is my code

local PlayFabClientApi = require("PlayFab.PlayFabClientApi")
local IPlayFabHttps = require("PlayFab.IPlayFabHttps")
local PlayFabHttps_Defold = require("PlayFab.PlayFabHttps_Defold")
IPlayFabHttps.SetHttp(PlayFabHttps_Defold) -- Assign the Defold-specific IHttps wrapper

PlayFabClientApi.settings.titleId = "XXXX" -- Please change this value to your own titleId from PlayFab Game Manager

PfLoggedIn = false


local function PfError(error)
  print("! PlayFab Error:")
  pprint(error)
end

local function PfDisplayStats(result)
  local output = ""
  for a,b in ipairs(result.Leaderboard) do
    output = output .. tostring(result.Leaderboard[a].Position) .. ". " .. result.Leaderboard[a].StatValue .. "\n"
  end

  gui.set_text(gui.get_node("highscore"), output)
end

local function Pf_GetStats()
  -- GETTING STATS AROUND PLAYER
  local PlayFabCall = {
    MaxResultsCount = 3,
    StatisticName = "highscores"
  }
  print("= Playerstats around")
	PlayFabClientApi.GetLeaderboardAroundPlayer(PlayFabCall, PfDisplayStats, PfError)
end



function init(self)
  msg.post(".", "acquire_input_focus")
  --msg.post("main:/map", "disable")
  msg.post("main:/gui", "disable")

  -- LOGIN to PlayFab
  local PfRequest = {
    TitleId = PlayFabClientApi.settings.titleId,
    CustomId = "FoodRescue",
    CreateAccount = true
  }
  -- Call API
  local result,error = PlayFabClientApi.LoginWithCustomID(PfRequest, Pf_GetStats, PfError)
  if error then
    print("! Cannot login to PlayFab")
  else
    print("* Logged in to PlayFab")
    PfLoggedIn = true
  end
end

If you got en error in dmengine that is normal. Try html5 build.

My module for playfab:

-- Put functions in this file to use them in several other scripts.
-- To get access to the functions, you need to put:
-- require "my_directory.my_file"
-- in any script using the functions.
local PlayFabClientApi = require("PlayFab.PlayFabClientApi")
local IPlayFabHttps = require("PlayFab.IPlayFabHttps")
local PlayFabHttps_Defold = require("PlayFab.PlayFabHttps_Defold")

IPlayFabHttps.SetHttp(PlayFabHttps_Defold) -- Assign the Defold-specific IHttps wrapper
PlayFabClientApi.settings.titleId = "XXXX" -- Please change this value to your own titleId from PlayFab Game Manager
local M={}

local random = math.random
M.uid=""
M.nickname="Player"
M.login=false
M.PlayFabId=""
M.DisplayName=""
function M.uuid()
    math.randomseed(os.time()+os.clock()+random(1,1000))
    local a=random(1,10)+random(1,10)+random(1,10)
    print (a)
    local template ='xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
    return string.gsub(template, '[xy]', function (c)
        local v = (c == 'x') and random(0, 0xf) or random(8, 0xb)
        return string.format('%x', v)
    end)
end

function M.getPlayerProfile(PlayFabId, onSuccess, OnFailed)
    PlayFabClientApi.GetPlayerProfile({PlayFabId=PlayFabId}, function(result)
        pprint(result)
        if result.PlayerProfile then M.DisplayName=result.PlayerProfile.DisplayName end
        onSuccess(result)
     end, OnFailed)
end

function M.sigIn(OnLoginSuccess, OnLoginFailed)
    print("lb.sigIn:",M.login)
    if M.login then
        OnLoginSuccess()
        return
    end
    local loginRequest = {
        CustomId = M.uid,
        CreateAccount = true
    }
    PlayFabClientApi.LoginWithCustomID(loginRequest, function(result)
         M.login=true
         pprint(result)
         M.PlayFabId=result.PlayFabId
         OnLoginSuccess(result)
       end, OnLoginFailed)
end

function M.getLeaderboard(board, onSuccess, OnFailed, MaxResults, StartPosition)
    PlayFabClientApi.GetLeaderboard({
		StatisticName=board,
		MaxResultsCount=MaxResults or 25,
		StartPosition=StartPosition or 0
	},onSuccess, OnFailed)
end
function M.getLeaderboardAroundPlayer(board, onSuccess, OnFailed, MaxResults)
    PlayFabClientApi.GetLeaderboardAroundPlayer({
		StatisticName=board,
		MaxResultsCount=MaxResults or 10
	},onSuccess, OnFailed)
end

function M.sendScore(value, onSuccess, onError)
    PlayFabClientApi.UpdatePlayerStatistics({Statistics= {{StatisticName= "loot", Value= value  },{StatisticName= "daily", Value= value  }}}, onSuccess, onError)
end
function M.changeName(nickname, onSuccess, onError)

    if M.login then
        PlayFabClientApi.UpdateUserTitleDisplayName({DisplayName=nickname}, function(result)
            print("New DisplayName:",result.DisplayName)
            M.DisplayName=result.DisplayName
            M.nickname=M.DisplayName
            onSuccess(result)
            end,
            function(error) print(error.errorMessage)
            onError(error)
            end)
    end
end
return M

Usage. First init() in the game code. I’m not login player in playfab before he made first result. So what I did there is generate uid for player.

local lb = require "main.leaderboard.lb"
....
	--
	game.loadFile()
	--
	if lb.uid=="" or lb.uid==nil then
		lb.uid=lb.uuid()
		print("UID=",lb.uid)
		---- save uid
		game.saveFile()
		---
	end
	print("Nickname=",lb.nickname)

Gameover, send the score with sigIn player before that:

lb.sigIn(
		function()
			lb.sendScore(game.totalcoins,
				onSendSuccess,
				function(error) print(error.errorMessage) end
			)
		end,
		function(error) print(error.errorMessage) end
	)
.....
local function onLeaderboardSuccess(result)
    print("Daily leaderboard:")
    --pprint(result)

    gui.set_enabled(gui.get_node("loading"),false)
    local board=result.Leaderboard or {}
    local nametext=""
    local scoretext=""
    for i=1, #board do
        local dn=board[i].DisplayName or "noname"
		local pos=tonumber(board[i].Position)+1
        nametext=nametext..tostring(pos)..". "..dn.."\n"
        local value=board[i].StatValue
        scoretext=scoretext..value.."\n"

		if board[i].PlayFabId==lb.PlayFabId then
			gui.set_position(gui.get_node("me"), vmath.vector3(120, 369-(i-1)*27, 0))
			gui.set_enabled(gui.get_node("me"), true)
		end
    end
    gui.set_text(gui.get_node("name"), nametext)
    gui.set_text(gui.get_node("score"), scoretext)
	print(nametext,scoretext)
end

local function onSendSuccess(result)
	print("score sent:",game.totalcoins)
	flow.start(function()
		print("flow.start")
		flow.delay(.5)
		print("flow.delay")
		lb.getLeaderboardAroundPlayer("daily", onLeaderboardSuccess, onFailed, 6)
	end)
end

Is it? Nah, I’m fairly certain that I got PlayFab working on desktop when PlayFab support was first added.

In bundle or in editor?
I don’t try desktop bundle.

Thanks, both of you.

I already took a look at britzls example, but, he’s always using the ludobits stuff I dont understand o.O
In the Code the trigger and flow is used but I dont really understand that in depth.

The main Problem at playfab is, I call a PF function, lets say Login, if result is positive, next I call another PF function. With an error: Not logged in. Are These functions threaded? It seems like the Login is called and the lua-script (f.e. init()) is continuing without waiting for the end of the prevous function.

Nearly the same if I “stack” them like if Login = success then getLeaderboard. This also runs into an error.

Sure, I could call a PF function and in (f.e.) update() I could “wait” for the result-value and then call the next PF function. Is that the right way? I
Is that whats FLOW and/or TRIGGER are for @britzl?

All PlayFab calls are asynchronous, meaning that they do nit block execution while waiting for a response. The response is received as a callback. If you need to chain multiple PF calls it typically becomes a nested chain of calls and callbacks.

Now, Lua has something called coroutines which allows for collaborative multi tasking. You can start a coroutine, make a PF call, pause the coroutine, resume when you receive a response and through this get nice sequential looking code.

Ah ok.

I quess I have to take a Close look to the ludobits … flow and trigger things.

But, isnt this the way of coroutines (taken this from your pf-example):

local result,error = PlayFabClientApi.LoginWithCustomID(PfRequest, Pf_GetStats, PfError)

@britzl
hmm, seems not only Playfab has problem with connect to server in dmengine (windows 10, 1.2.114):

look, GA, defold stats too:

I don’t known, may be dmengine blocked by Windows Firewall, but I accept it always when update Defold.

in my case its not blocked imho. Its working (most times). Sometimes there is a Kind of timeout.

But my main Problem is -like britzl correctly said- the asychronous handling. I have to Change the “handling” for the external calls of the Playfab functions.

By the way @Dragosha. I mostly have the Problem with hamster that my Name isnt accepted. In different cases. Sometimes I Change my Name, ist written down below, after playing I was saved as “noname”. Sometimes I Change my Name after clicking ok ist back to “noname” etc.
…just by the way :wink: Love your Card-game anyway :slight_smile:

Tried to build https://github.com/britzl/playfabexamples on Windows 10 PC and got the same error in console when dmengine is running.

@britzl any ideas why is it happening?

I tried building and running on OSX and it works. What if you take that URL and paste it into a browser? Can you reach it?

in browser that URL takes HTTP ERROR 404

But all works fine if we do html5 build.

Ok, so the server is reachable. The 404 is probably caused by the browser doing a GET while that url expects a POST.

And it works when doing an HTML5 build? Strange…

yep, in hamster the same problem. Works in browser but not works in dmengine (windows bundle too).

These Error I’ll get very often, thats why I implemented the “RETRY” Button (instead of PLAY) in my game. Sometimes it works, sometimes not. after 1 or 2 more tries it works. Its like a timeout.

There are definitely problems with playfab and defold.

Very often there is no login possible. Sometimes after login and updating highscores the connection is also lost.

debug output while trying to login:

DEBUG:SCRIPT: PF loginname = 688194289677-1506715084
INFO:DLIB: SSDP: Started on address 192.168.178.20
ERROR:SCRIPT: HTTP request to 'https://XXXX.playfabapi.com//Client/LoginWithCustomID' failed (http result: -1  socket result: -5)
DEBUG:SCRIPT: MENU: LMB
DEBUG:SCRIPT: PF loginname = 637434176366-1506715087
ERROR:SCRIPT: HTTP request to 'https://XXXX.playfabapi.com//Client/LoginWithCustomID' failed (http result: -1  socket result: -5)
DEBUG:SCRIPT: MENU: LMB
DEBUG:SCRIPT: MENU: LMB
DEBUG:SCRIPT: PF loginname = 628745872218-1506715090
ERROR:SCRIPT: HTTP request to 'https://XXXX.playfabapi.com//Client/LoginWithCustomID' failed (http result: -1  socket result: -5)
DEBUG:SCRIPT: MENU: LMB
DEBUG:SCRIPT: PF loginname = 695232198612-1506715093
ERROR:SCRIPT: HTTP request to 'https://XXXX.playfabapi.com//Client/LoginWithCustomID' failed (http result: -1  socket result: -5)
DEBUG:SCRIPT: MENU: LMB
DEBUG:SCRIPT: PF loginname = 643152389569-1506715099
ERROR:SCRIPT: HTTP request to 'https://XXXX.playfabapi.com//Client/LoginWithCustomID' failed (http result: -1  socket result: -5)
DEBUG:SCRIPT: MENU: LMB
DEBUG:SCRIPT: PF loginname = 673495369544-1506715108
ERROR:SCRIPT: HTTP request to 'https://XXXX.playfabapi.com//Client/LoginWithCustomID' failed (http result: -1  socket result: -5)
DEBUG:SCRIPT: MENU: LMB
DEBUG:SCRIPT: PF loginname = 675329747257-1506715119
ERROR:SCRIPT: HTTP request to 'https://XXXX.playfabapi.com//Client/LoginWithCustomID' failed (http result: -1  socket result: -5)
DEBUG:SCRIPT: MENU: LMB
DEBUG:SCRIPT: PF loginname = 668838742725-1506715121
ERROR:SCRIPT: HTTP request to 'https://XXXX.playfabapi.com//Client/LoginWithCustomID' failed (http result: -1  socket result: -5)
DEBUG:SCRIPT: MENU: LMB
DEBUG:SCRIPT: PF loginname = 739346275192-1506715123
ERROR:SCRIPT: HTTP request to 'https://XXXX.playfabapi.com//Client/LoginWithCustomID' failed (http result: -1  socket result: -5)

-5 is CONNRESET (connection reset). This can happen for several reasons:

  • the peer deliberately reset the connection
  • the peer closed the connection while he still had unread data pending
  • you had sent data to a connection that had already been closed by the peer
  • you had pending write data and the TCP retries have timed out
  • TCP keepalive detected a lost connection.

So the question is if this is something that happens only for you on a single network or if it is a general problem. I’ve tried my PlatFab example project and haven’t seen any issues with Defold and the PlayFab SDK.

Hm…

Wondering.

Thats the custom-login who has called:

local function Pf_CustomLogin(id)
	if not id then
    math.randomseed(os.clock() + os.time() + math.random(1000))
    local temp = ""
    for c=1, 12 do
      temp = temp .. math.random(9)
    end
    temp = temp .. "-"..  tostring(os.time())
		id = temp
	end
  pprint("PF loginname = " .. id)
	local PfRequest = {
        TitleId = PlayFabClientApi.settings.titleId,
        CustomId = id,
        CreateAccount = true
    }
    -- Call API
    PlayFabClientApi.LoginWithCustomID(PfRequest, Pf_LoginSuccess, Pf_FailureLogin)
end

If I try the game online (HTML5) it seems to work fine.

In editor or win-bundle (local) there are connection problems. Strange. There is no firewall etc at all (deactivated). Other games and services dont have any problems.

I have the same problem in normal build as well.