Quick Links: Download Gideros Studio | Gideros Documentation | Gideros community chat | DONATE
xtralife include file and tutorial. — Gideros Forum

xtralife include file and tutorial.

SinisterSoftSinisterSoft Maintainer
edited September 2017 in Code snippets
Clan of the Cloud was changed to become xtralife some time ago.

It's an open source gaming back end.

http://xtralife.cloud/

xtralife gives you free cross platform leaderboards and achievements, plus loads of other stuff !

I originally wrote some functions to access clan of the cloud on any of the Gideros platforms using their REST interface.
Although still compatible, my old clan of the cloud routines were a bit clunky and so I've re-written them to be more streamlined.

Here they are:
local bs = {[0]='A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
			'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',}
 
local function base64(s)
	local byte,rep=string.byte,string.rep
	local pad=2-((#s-1)%3)
	s=(s..rep('\0',pad)):gsub("...",function(cs)
		local a,b,c=byte(cs,1,3)
		return bs[a>>2]..bs[(a&3)<<4|b>>4]..bs[(b&15)<<2|c>>6]..bs[c&63]
   end)
   return s:sub(1,#s-pad)..rep('=',pad)
end
 
function xtralifeSave()
	if xtralife then
		local file=io.open("|D|xtralife.txt","w+")
		local saveString=json.encode(xtralife)
		if file then
			file:write(saveString)
			file:close()
		end
	end
end
 
function xtralifeSave()
	if xtralife then
		local file=io.open("|D|xtralife.txt","w+")
		local saveString=json.encode(xtralife)
		if file then
			file:write(saveString)
			file:close()
		end
	end
end
 
function xtralifeProfileEx(reply)
	if xtralife then
		if reply["displayName"] then xtralife.displayName=reply["displayName"] end
		if reply["lang"] then xtralife.language=reply["lang"] end
		if reply["firstName"] then xtralife.forename=reply["firstName"] end
		if reply["lastName"] then xtralife.surname=reply["lastName"] end
		if reply["addr1"] then xtralife.addr1=reply["addr1"] end
		if reply["addr2"] then xtralife.addr2=reply["addr2"] end
		if reply["addr3"] then xtralife.addr3=reply["addr3"] end
		if reply["avatar"] then xtralife.avatar=reply["avatar"] end
	end
end
 
function xtralifeHeader()
	local header={ ["User-Agent"]="Gideros",["x-apikey"]=xtralife.apiKey,["x-apisecret"]=xtralife.apiSecret,["content-type"]="application/json"}
	if xtralife.id and xtralife.secret then header["Authorization"]="Basic "..base64(xtralife.id..":"..xtralife.secret) end
	return header
end
 
function xtralifeCall(call)
	return "<a href="https://"..xtralife.name.."-api0"..xtralife.server..".clanofthecloud.mobi/"..call" rel="nofollow">https://"..xtralife.name.."-api0"..xtralife.server..".clanofthecloud.mobi/"..call</a>
end
 
function xtralifeInit(key,secret,test,server)
	if json then
		if not pcall(function()
			local file=io.open("|D|xtralife.txt","r")
			if file then
				local originaldata=file:read()
				file:close()
				if originaldata then
					xtralife=json.decode(originaldata)
				end
			end
		end) then xtralife={} end
		if not xtralife then xtralife={} end
		local name="prod"
		xtralife.test=test or false
		if test then name="sandbox" end
		xtralife.name=name
		xtralife.server=server or 1
		xtralife.apiKey=key or ""
		xtralife.apiSecret=secret or ""
		xtralife.login=false
	end
end
 
function xtralifeResume()
	if xtralife and not xtralife.login then
		if xtralife.id and xtralife.secret and xtralife.id~="" then
			xtralifeLogin()
		end
	end
end
 
function xtralifeLogin(network,id,secret)
	if xtralife and not xtralife.login then
		print("xtralife Login",network,id,secret)
		local call="v1/login"
		xtralife.login=false
		local body={}
		if xtralife.id and xtralife.secret then
			body={network="anonymous",id=xtralife.id,secret=xtralife.secret,options={preventRegistration=true}}
			xtralife.linkNetwork=network
			xtralife.linkId=id
			xtralife.linkSecret=secret
		elseif id and secret and (network=="facebook" or network=="googleplus" or network=="gamecenter" or network=="email") then
			body={network=network,id=id,secret=secret}
			xtralife.linkNetwork=nil
		else
			call="v1/login/anonymous"
			xtralife.linkNetwork=nil
		end
 
		local request=UrlLoader.new()
		if request then
			request:addEventListener(Event.COMPLETE,function(e)
				--print(e.httpStatusCode,e.data)
				if (e.httpStatusCode==200 or e.httpStatusCode==201) and e.data then
					local reply=json.decode(e.data)
					if reply then
						xtralife.login=true
						if reply["gamer_id"] then xtralife.id=reply["gamer_id"] end
						if reply["gamer_secret"] then xtralife.secret=reply["gamer_secret"] end
						if reply["profile"] then xtralifeProfileEx(reply["profile"]) end
						xtralifeSave()
						if xtralife.linkNetwork then
							xtralifeLink(xtralife.linkNetwork,xtralife.linkId,xtralife.linkSecret)					
						end
 
						-- Here you can put some code if the login has been successful, eg:
						--xtralifeScores(64)
 
 
					end
				elseif e.httpStatusCode==401 and e.data then
					local reply=json.decode(e.data)
					if reply then
						if reply["name"]=="LoginError" and reply["message"]=="Invalid user credentials" then
							xtralife.id=nil
							xtralife.secret=nil
							xtralifeSave()
						end
					end
				end
			end)
			request:addEventListener(Event.ERROR,function(e)
				print("xtralife login failed",e.error)
			end)
			request:load(xtralifeCall(call),UrlLoader.POST,xtralifeHeader(),json.encode(body))
		end
	end
end
 
function xtralifeLogout()
	if xtralife and xtralife.login then
		local call="v1/gamer/logout"
		local request=UrlLoader.new()
		if request then
			request:addEventListener(Event.COMPLETE,function(e)
				--print(e.httpStatusCode,e.data)
				if e.httpStatusCode==200 then
					xtralife.login=false
				end
			end)
			request:addEventListener(Event.ERROR,function(e)
				print("xtralife logout failed",e.error)
			end)
			request:load(xtralifeCall(call),UrlLoader.POST,xtralifeHeader())
		end
	end
end
 
function xtralifeLink(network,id,secret)
	if xtralife and xtralife.login then
		local call="v1/gamer/link"
		local body={network=network,id=id,secret=secret}
		local request=UrlLoader.new()
		if request then
			request:addEventListener(Event.COMPLETE,function(e)
				--print(e.httpStatusCode,e.data)
			end)
			request:addEventListener(Event.ERROR,function(e)
				print("xtralife link failed",e.error)
			end)
			request:load(xtralifeCall(call),UrlLoader.POST,xtralifeHeader(),json.encode(body))
		end
	end
end
 
function xtralifeUnlink(network)
	if xtralife and xtralife.login then
		local call="v1/gamer/unlink"
		local body={network=network}
		local request=UrlLoader.new()
		if request then
			request:addEventListener(Event.COMPLETE,function(e)
				--print(e.httpStatusCode,e.data)
			end)
			request:addEventListener(Event.ERROR,function(e)
				print("xtralife unlink failed",e.error)
			end)
			request:load(xtralifeCall(call),UrlLoader.POST,xtralifeHeader(),json.encode(body))
		end
	end
end
 
-- body is a table with "displayName", "lang", "firstName", "lastName", "addr1", "addr2", "addr3", "avatar" - avatar is a url to and image, lang is a iso-639-1 country code
function xtralifeSetProfile(body)
	if xtralife and xtralife.login then
		local call="v1/gamer/profile"
		local request=UrlLoader.new()
		if request then
			request:addEventListener(Event.COMPLETE,function(e)
				--print(e.httpStatusCode,e.data)
				if e.httpStatusCode==200 then
				end
			end)
			request:addEventListener(Event.ERROR,function(e)
				print("xtralife setprofile failed",e.error)
			end)
			request:load(xtralifeCall(call),UrlLoader.POST,xtralifeHeader(),json.encode(body))
		end
	end
end
continued...

Likes: pie, antix, totebo

Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
https://deluxepixel.com
+1 -1 (+3 / -0 )Share on Facebook

Comments

  • SinisterSoftSinisterSoft Maintainer
    edited September 2017
    pt 2
    function xtralifeGetProfile()
    	if xtralife and xtralife.login then
    		local call="v1/gamer/profile"
    		local request=UrlLoader.new()
    		if request then
    			request:addEventListener(Event.COMPLETE,function(e)
    				--print(e.httpStatusCode,e.data)
    				if e.httpStatusCode==200 and e.data then
    					local reply=json.decode(e.data)
    					if reply then
    						xtralifeProfileEx(reply)
    						xtralifeSave()
    					end
    				end
    			end)
    			request:addEventListener(Event.ERROR,function(e)
    				print("xtralife getprofile failed",e.error)
    			end)
    			request:load(xtralifeCall(call),UrlLoader.GET,xtralifeHeader())
    		end
    	end
    end
     
    function xtralifeScore(val,info,board,reverse)
    	if xtralife and xtralife.login then
    		local domain=xtralife.domain or "private"
    		local tab=board or "leaderboard"
    		local call="v2.6/gamer/scores/"..domain.."/"..tab
    		if reverse then	call=call.."?order=lowtohigh" end
    		local body={score=val,info=info or ""}
    		local request=UrlLoader.new()
    		if request then
    			request:addEventListener(Event.COMPLETE,function(e)
    				--print(e.httpStatusCode,e.data)
    				if e.httpStatusCode==200 and e.data then
    					local reply=json.decode(e.data)
    					if reply then
    						if not xtralife[tab] then xtralife[tab]={} end
    						if reply["rank"] then
    							xtralife[tab].rank=reply["rank"]
     
    							-- Here you can put some code to set a marker if you are within a specific high score range - to grab the new leaderboard
    							-- eg if you normally rquest the top 64 leaderboard entries...
     
    							if tonumber(xtralife[tab].rank)<=64 then
    								xtralifeScoresRefresh=true
    								frontendMode=1 
    							end
     
    						end
    						xtralifeSave()
    					end
    				end
    			end)
    			request:addEventListener(Event.ERROR,function(e)
    				print("xtralife score failed",e.error)
    			end)
    			request:load(xtralifeCall(call),UrlLoader.POST,xtralifeHeader(),json.encode(body))
    		end
    	end
    end
     
    function xtralifeScores(count,board,friends)
    	if xtralife and xtralife.login then
    		local domain=xtralife.domain or "private"
    		local tab=board or "leaderboard"
    		local call="v2.6/gamer/scores/"..domain.."/"..tab.."?count="..(count or 10)
    		if friends then call=call.."&type=friendscore" end
    		local request=UrlLoader.new()
    		if request then
    			request:addEventListener(Event.COMPLETE,function(e)
    				--print(e.httpStatusCode,e.data)
    				if e.httpStatusCode==200 and e.data then
    					local reply=json.decode(e.data)
    					if reply then
    						if reply[tab]["scores"] then
    							local scores=reply[tab]["scores"]
    							if not xtralife[tab] then xtralife[tab]={} end
    							local table=xtralife[tab]
    							for key,val in pairs(scores) do
    								--print(key)
    								if not table[key] then table[key]={} end
    								local tableKey=table[key]
    								for key2,val2 in pairs(val) do
    									if key2=="gamer_id" then tableKey.gamer=val2
    									elseif key2=="score" then
    										if val2["score"] then tableKey.score=val2["score"] end
    										if val2["info"] then tableKey.information=val2["info"] end
    										if val2["timestamp"] then tableKey.time=val2["timestamp"] end
    									elseif key2=="profile" then
    										if val2["displayName"] then tableKey.displayName=val2["displayName"] end
    										if val2["lang"] then tableKey.language=val2["lang"] end
    										if val2["firstName"] then tableKey.forename=val2["firstName"] end
    										if val2["lastName"] then tableKey.surname=val2["lastName"] end
    										if val2["addr1"] then tableKey.addr1=val2["addr1"] end
    										if val2["addr2"] then tableKey.addr2=val2["addr2"] end
    										if val2["addr3"] then tableKey.addr3=val2["addr3"] end
    										if val2["avatar"] then tableKey.avatar=val2["avatar"] end
    									end
    								end
    							end
    							xtralifeSave()
    						end
    					end
    				end
    			end)
    			request:addEventListener(Event.ERROR,function(e)
    				print("xtralife scores failed",e.error)
    			end)
    			request:load(xtralifeCall(call),UrlLoader.GET,xtralifeHeader())
    		end
    	end
    end
    You should copy these to a new lua file, eg xtralife.lua, add it to your project, right-click it in the project tree and exclude from execution.

    It needs a plugin to be present: json. You can easily addit to your project using the new plugin system in the Gideros main project tree. If you are using anything other than the pre-built QT player then you may need to make a new player - eg for Android, iOS, etc...

    Now in your main code, you enable 'json' first.
    pcall(function() require "json" end)
    Now you start xtralife:
    require "xtralife"
    xtralifeInit(" app key goes here "," app secret goes here ",true)  -- true for sandbox, else leave out.
    You can find your app key and secret in the xtralife dashboard once you register and create an app there.

    At some point you should call 'xtralifeResume()', this will login if the user has used xtralife in your game before, if not then it won't do anything. I usually call this on my main game front end loop - the start screen for example in the game.

    Before you update any high scores or achievements - eg - as the gameover starts or level ends, then you should also call 'xtralifeLogin()' - this will create a new xtralife user if you haven't logged in before.

    These two routine calls ensure that all goes smoothly on systems that don't already have a gaming lib - like html5, windows, etc...

    If you are using the Gideros gaming plugin then you can use the gaming lib's 'getPlayerInfo()' to find the users id and alias name.

    continued...
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • pt3...

    Here is the code for the way I init the gaming lib:
    pcall(function() require "gaming" end)
    if Gaming then
    	if android then
    		if kindle then
    			gaming=Gaming.new("gamecircle")
    			gamingNetwork="kindle"
    		else
    			gaming=Gaming.new("googleplay")
    			gamingNetwork="android"
    		end
    	elseif ios then
    		gaming=Gaming.new("gamekit")
    		gamingNetwork="gamecenter"
    	end
    After the login success event I call 'getPlayerInfo()' as mentioned above.

    Here is my typical player_information_complete event code:
    		gaming:addEventListener(Event.PLAYER_INFORMATION_COMPLETE,function(e)
    			print("gaming PLAYER_INFORMATION_COMPLETE")
    			if e.id then
    				gamingName="Guest"
    				if e.name then gamingName=e.name end
    				if gamingNetwork=="android" or gamingNetwork=="kindle" then
    					local n=gamingName:gsub('%W','')
    					xtralifeLogin("email",(n.."<a href="https://forum.giderosmobile.com/profile/..e.id.." rel="nofollow">@..e.id..</a>."..gamingNetwork),"unknown")
    				elseif gamingNetwork=="gamecenter" then
    					xtralifeLogin(gamingNetwork,e.id)
    				end
    				print("network",gamingNetwork,e.id)
    			end
    		end)
    This will attempt to login to xtralife, if xtralife has been used before then it will update the existing login with the alias and id codes for the network. Because we don't have the 'secret' for the gaming libs I have to re-use the 'email' tag on xtralife instead of the proper tags.

    Now you are done!

    All you need to do now is submit scores, grab the leaderboard, etc:
    xtralifeScore(500,"test")   -- submit 500 to the 'test' leaderboard
     
    xtralifeScores()  -- grab the main leaderboard, add "test" to grab the test leaderboard instead.
    Enhancements:

    Notice that people will be logged in as 'Guest'.

    Add this to the beginning of xtralife.lua :
    guestWord1={"Handy","Lost","Clever","Frozen","Alpha","Small","Tiny","Huge"}
    guestWord2={"Box","Car","Circle","Triangle","Book","House","Horse","Cat","Dog"}
    Now replace the xtralifeProfileEx(reply) with this:
    function xtralifeProfileEx(reply)
    	if xtralife then
    		local update={}
    		local doUpdate=false
    		if reply["displayName"] then
    			xtralife.displayName=reply["displayName"]
    			if gamingName~="Guest" and xtralife.displayName~=gamingName then
    				xtralife.displayName=gamingName
    				update.displayName=gamingName
    				xtralifeSetProfile({displayName=xtralife.displayName})
    				doUpdate=true
    			elseif xtralife.displayName=="Guest" then
    				xtralife.displayName=guestWord1[math.random(#guestWord1)]..guestWord2[math.random(#guestWord2)]..math.random(10,99)
    				update.displayName=xtralife.displayName
    				doUpdate=true
    			end
    		end
    		if reply["lang"] then xtralife.language=reply["lang"] end
    		if reply["firstName"] then xtralife.forename=reply["firstName"] end
    		if reply["lastName"] then xtralife.surname=reply["lastName"] end
    		if reply["addr1"] then xtralife.addr1=reply["addr1"] end
    		if reply["addr2"] then xtralife.addr2=reply["addr2"] end
    		if reply["addr3"] then xtralife.addr3=reply["addr3"] end
    		if reply["avatar"] then xtralife.avatar=reply["avatar"] end
    		if doUpdate then xtralifeSetProfile(update) end
    	end
    end
    That will generate a random name for the Guest and update the xtralife servers with the new information.

    If you make these routines better then please add your new code to this thread so everyone benefits. :)

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • hgy29hgy29 Maintainer
    Quick question: if it uses REST api (UrlLoader), why does it require luasocket for ?

    Likes: HubertRonald

    +1 -1 (+1 / -0 )Share on Facebook
  • SinisterSoftSinisterSoft Maintainer
    edited September 2017
    Just mime for b64. Is it in another Gideros 'built-in' lib - if so then I could use them and get rid of socket.

    see function xtralifeHeader()
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • SinisterSoftSinisterSoft Maintainer
    edited September 2017
    btw, I tried something like this before:
    local bs = { [0] =
       'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
       'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
       'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
       'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/',
    }
     
    local function base64(s)
       local byte, rep = string.byte, string.rep
       local pad = 2 - ((#s-1) % 3)
       s = (s..rep('\0', pad)):gsub("...", function(cs)
          local a, b, c = byte(cs, 1, 3)
          return bs[a>>2] .. bs[(a&3)<<4|b>>4] .. bs[(b&15)<<2|c>>6] .. bs[c&63]
       end)
       return s:sub(1, #s-pad) .. rep('=', pad)
    end
    but it didn't work because I think null is expected at the end.
    	print(mime.b64(xtralife.id..":"..xtralife.secret))
    	print(base64(xtralife.id..":"..xtralife.secret))
    outputs:
    NTliYWVhOWFiNTFkZGNhOTA1ZmNiY2U0Ojg2OWM2NzE5MjliOGVhY2NmNGM0ZDgyNDM0YTllMjIwNDc2NjM0YWE=	nil
    NTliYWVhOWFiNTFkZGNhOTA1ZmNiY2U0Ojg2OWM2NzE5MjliOGVhY2NmNGM0ZDgyNDM0YTllMjIwNDc2NjM0YWE=
    I tried adding .."\0" but that doesn't work - it doesn't add the null.
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • SinisterSoftSinisterSoft Maintainer
    edited September 2017
    Updated code/tutorial to not use sockets lib and instead use a base64 function.
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • Thanks very much for sharing this, it looks like an interesting cross platform solution I'd never heard of before. I think this deserves to be in a repo somewhere.

    Likes: SinisterSoft

    +1 -1 (+1 / -0 )Share on Facebook
  • Quick question: if it uses REST api (UrlLoader), why does it require luasocket for ?
    and also @SinisterSoft doesn't use LuaSec
    function xtralifeCall(call)
    	return "<a href="https://&quot;..xtralife.name.."-api0"..xtralife.server..".clanofthecloud.mobi/"..call" rel="nofollow">https://&quot;..xtralife.name.."-api0"..xtralife.server..".clanofthecloud.mobi/"..call</a>
    end
    How is it possible? tell our your magic. :)

    Likes: SinisterSoft

    +1 -1 (+1 / -0 )Share on Facebook
  • SinisterSoftSinisterSoft Maintainer
    edited September 2017
    @HubertRonald Https support is built-in to the various Gideros players. :)

    For windows however you have to include a couple of extra files:
    https://www.dropbox.com/s/y8ixf3d03ygf29t/extra_ssl.rar?dl=0

    Likes: HubertRonald

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+1 / -0 )Share on Facebook
  • SinisterSoftSinisterSoft Maintainer
    edited September 2017
    I'll try and get someone xtralife to join the forum and post about some of the features of the system here. It's *really* good. :)

    Likes: HubertRonald

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+1 / -0 )Share on Facebook
  • Hello, I'm Michael, founder of Clan of the Cloud, which became XtraLife last year.

    Anthony has pretty much said everything (many thanks to him), but just wanted to add that we offer a hosted solution (which means you just need Anthony's SDK and you're good to go), or you can use our Open Source solution. In this case, you install everything on your own servers and you manage it the way you like it!

    Other than that, we provide mostly all the features you'd expect from a backend, including player management (with support for social networks or private user base), leaderboards, achievements, turn by turn multiplayer, virtual currencies, cloud synchronization, sending of data between users, referral system, server side code, and much more.
    Also, we do provide many "low level" features with which you can implement pretty much all your needs. Do you need a very custom clan feature? Check. Challenges based on virtual currencies betting? Check :)

    Do not hesitate to contact us (or me) if you need more info. We like to talk about your needs on Slack!
    +1 -1 (+2 / -0 )Share on Facebook
  • I've updated my files a little re xtralife. Here are the latest versions:
    https://www.dropbox.com/s/4vrput6ytgvsqas/xtralife.lua?dl=0

    It down downloads the avatar of the person if xtralife have it, it shows how to manipulate the image before saving.

    It's all a bit of a hack so use it as the basis for your own mods. I'm updating soon because of work done by @MikeOfTheClan for extra googleplay and gamecircle support. So expect changes!
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • Here is my facebook login, set facebookId to your facebook app id, include the plugin.
    if facebookId then
    	pcall(function() require "facebook" end)
    end
    if facebook then
    	facebook:addEventListener(Event.LOGIN_COMPLETE, function(e)
    		print("login successful")
    		facebookUserToken=facebook:getAccessToken()
    		print(facebook:getProfile())
    	end)
    	facebook:addEventListener(Event.DIALOG_ERROR, function(e)
    		print("dialog error", e.type, e.error)
    	end)
    	facebook:addEventListener(Event.DIALOG_COMPLETE, function(e)
    		print("dialog complete", e.type)
    	end)
    	facebook:addEventListener(Event.LOGOUT_COMPLETE, function()
    		print("logged out")
    	end)
    	facebook:addEventListener(Event.REQUEST_COMPLETE, function(e)
    		print("request complete:", e.type, e.response)
    		if e.type=="me" then
    			if e.response then
    				local response=json.decode(e.response)
    				if response and response.name then
    					gamingName=response.name
    					if response.id and facebookUserToken then
    						xtralifeLogin("facebook",response.id,facebookUserToken)
    					end
    				end
    			end
    		end
    	end)
     
    	facebook:addEventListener(Event.REQUEST_ERROR, function(e)
    		print("request error:", e.type, e.error)
    	end)
     
    	facebook:login(facebookId,{"public_profile","user_friends"})--,"publish_actions"})
    else
    	print("Facebook not available")
    end


    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • Here is my gaming login:
    pcall(function() require "gaming" end)
    if Gaming then
    	if android then
    		if kindle then
    			gaming=Gaming.new("gamecircle")
    			gamingNetwork="kindle"
    		else
    			gaming=Gaming.new("googleplay")
    			gamingNetwork="android"
    		end
    	elseif ios then
    		gaming=Gaming.new("gamekit")
    		gamingNetwork="gamecenter"
    	end
    	if gaming then
    		gaming:addEventListener(Event.LOGIN_COMPLETE,function()
    			print("gaming LOGIN_COMPLETE")
    			login=true
    			if pirateCopy then
    				pirateCopy=false
    				saveSettings()
    			end
    			gaming:getPlayerInfo()
    			--gaming:loadAchievements()
     
    			--gaming:loadScores(leaderboards[1],2,1,25)	--leaderboard,span,collection,max results
     
    			--gaming:loadState(0)
    		end)
     
    		gaming:addEventListener(Event.LOGIN_ERROR,function(e)
    			print("gaming LOGIN_ERROR:"..e.error)
    			if e.error=="No license." then
    				if not pirateCopy then
    					pirateCopy=true
    					saveSettings()
    				end
    			end
    			login=false
    			tryLogin=false
    			gaming:logout()
    		end)
     
    		gaming:addEventListener(Event.PLAYER_INFORMATION_COMPLETE,function(e)
    			print("gaming PLAYER_INFORMATION_COMPLETE")
    			if e.id then
    				gamingName="Guest"
    				if e.name then
    					gamingName=e.name
    					if gamingName=="SinisterSoft" then gamingName="Anthony ("..gamingNetwork..")" end
    				end
    				if gamingNetwork=="android" or gamingNetwork=="kindle" then
    					local n=gamingName:gsub('%W','')
    					xtralifeLogin("email",(n.."<a href="https://forum.giderosmobile.com/profile/..e.id.." rel="nofollow">@..e.id..</a>."..gamingNetwork),"unknown")
    				elseif gamingNetwork=="gamecenter" then
    					xtralifeLogin(gamingNetwork,e.id)
    				end
    				print("network",gamingNetwork,e.id)
    			end
    		end)
     
    		gaming:addEventListener(Event.PLAYER_INFORMATION_ERROR,function(e)
    			print("gaming PLAYER_INFORMATION_ERROR:"..e.error)
    		end)
     
    		gaming:addEventListener(Event.PLAYER_SCORE_COMPLETE,function(e)
    			print("gaming PLAYER_SCORE_COMPLETE")
    			print("Score",e.score,"Rank",e.rank,"Time",e.timestamp)
    		end)
     
    		gaming:addEventListener(Event.PLAYER_SCORE_ERROR,function(e)
    			print("gaming PLAYER_SCORE_ERROR:"..e.error)
    		end)
     
    		gaming:addEventListener(Event.LOAD_ACHIEVEMENTS_COMPLETE,function(e)
    			print("gaming LOAD_ACHIEVEMENTS_COMPLETE")
    		end)
     
    		gaming:addEventListener(Event.LOAD_ACHIEVEMENTS_ERROR,function(e)
    			print("gaming LOAD_ACHIEVEMENTS_ERROR:"..e.error)
    		end)
     
    		gaming:addEventListener(Event.REPORT_ACHIEVEMENT_COMPLETE,function(e)
    			print("gaming REPORT_ACHIEVEMENT_COMPLETE")
    		end)
     
    		gaming:addEventListener(Event.REPORT_ACHIEVEMENT_ERROR,function(e)
    			print("gaming REPORT_ACHIEVEMENT_ERROR:"..e.error)
    		end)
     
    		gaming:addEventListener(Event.LOAD_SCORES_COMPLETE,function(e)
    			print("gaming LOAD_SCORES_COMPLETE")
    			--local scores=e.scores
    			--if scores then
    		--		for loop=1,#scores do
    		--			--print(scores[loop].name,scores[loop].timestamp,scores[loop].formattedScore,scores[loop].score,scores[loop].rank,scores[loop].playerId)
    		--		end
    		--	end
    		end)
     
    		gaming:addEventListener(Event.LOAD_SCORES_ERROR,function(e)
    			print("gaming LOAD_SCORES_ERROR!")
    		end)
     
    		gaming:addEventListener(Event.REPORT_SCORE_COMPLETE,function(e)
    			print("gaming REPORT_SCORE_COMPLETE")
    			print("Score",e.score,"Rank",e.rank,"Time",e.timestamp)
    		end)
     
    		gaming:addEventListener(Event.REPORT_SCORE_ERROR,function(e)
    			print("gaming REPORT_SCORE_ERROR:"..e.error)
    		end)
     
    		gaming:addEventListener(Event.STATE_LOADED,function(e)
    			print("gaming STATE_LOADED")
    		end)
     
    		gaming:addEventListener(Event.STATE_ERROR,function(e)
    			print("gaming STATE_ERROR:"..e.error)
    		end)
     
    		gaming:addEventListener(Event.STATE_CONFLICT,function(e)
    			print("gaming STATE_CONFLICT")
    		end)
     
    		gaming:addEventListener(Event.STATE_DELETED,function(e)
    			print("gaming STATE_DELETED")
    		end)
     
    	end
    else
    	print("Gaming plugin not installed.")
    end
    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
  • On my main game front end I call xtralifeResume()

    This will login to xtralife if previously logged in.

    At the end of the game I check if xtralife is logged in, if not then I try the xtralifeLogin() so it makes up a username/password. That way, in the future, if no facebook, google place, gamecircle or gamecentre then it will still record and compare leaderboards, etc...

    Likes: antix

    Coder, video game industry veteran (since the '80s, ❤'s assembler), arrested - never convicted hacker (in the '90s), dad of five, he/him (if that even matters!).
    https://deluxepixel.com
    +1 -1 (+1 / -0 )Share on Facebook
Sign In or Register to comment.