Skip to content

Instantly share code, notes, and snippets.

@JohannesLoot
Created June 10, 2022 06:42
Show Gist options
  • Save JohannesLoot/20290272a91bb785459dd014b8845c8c to your computer and use it in GitHub Desktop.
Save JohannesLoot/20290272a91bb785459dd014b8845c8c to your computer and use it in GitHub Desktop.
extends Node
# Use this game API key if you want to test it with a functioning leaderboard
# "987dbd0b9e5eb3749072acc47a210996eea9feb0"
var game_API_key = "your-game-API-key-here"
var development_mode = true
var leaderboard_key = "leaderboardKey"
var session_token = ""
var score = 0
# HTTP Request node can only handle one call per node
var auth_http = HTTPRequest.new()
var leaderboard_http = HTTPRequest.new()
var submit_score_http = HTTPRequest.new()
func _ready():
_authentication_request()
func _process(_delta):
if(Input.is_action_just_pressed("ui_up")):
score += 1
print("CurrentScore:"+str(score))
if(Input.is_action_just_pressed("ui_down")):
score -= 1
print("CurrentScore:"+str(score))
# Upload score when pressing enter
if(Input.is_action_just_pressed("ui_accept")):
_upload_score(score)
# Get score when pressing spacebar
if(Input.is_action_just_pressed("ui_select")):
_get_leaderboards()
func _authentication_request():
# Check if a player session has been saved
var player_session_exists = false
var file = File.new()
file.open("user://LootLocker.data", File.READ)
var player_identifier = file.get_as_text()
file.close()
if(player_identifier.length() > 1):
player_session_exists = true
## Convert data to json string:
var data = { "game_key": game_API_key, "game_version": "0.0.0.1", "development_mode": true }
# If a player session already exists, send with the player identifier
if(player_session_exists == true):
data = { "game_key": game_API_key, "player_identifier":player_identifier, "game_version": "0.0.0.1", "development_mode": true }
# Add 'Content-Type' header:
var headers = ["Content-Type: application/json"]
# Create a HTTPRequest node for authentication
auth_http = HTTPRequest.new()
add_child(auth_http)
auth_http.connect("request_completed", self, "_on_authentication_request_completed")
# Send request
auth_http.request("https://api.lootlocker.io/game/v2/session/guest", headers, true, HTTPClient.METHOD_POST, to_json(data))
# Print what we're sending, for debugging purposes:
print(data)
func _on_authentication_request_completed(result, response_code, headers, body):
var json = JSON.parse(body.get_string_from_utf8())
# Save player_identifier to file
var file = File.new()
file.open("user://LootLocker.data", File.WRITE)
file.store_string(json.result.player_identifier)
file.close()
# Save session_token to memory
session_token = json.result.session_token
# Print server response
print(json.result)
# Clear node
auth_http.queue_free()
# Get leaderboards
_get_leaderboards()
func _get_leaderboards():
print("Getting leaderboards")
var url = "https://api.lootlocker.io/game/leaderboards/"+leaderboard_key+"/list?count=10"
var headers = ["Content-Type: application/json", "x-session-token:"+session_token]
# Create a request node for getting the highscore
leaderboard_http = HTTPRequest.new()
add_child(leaderboard_http)
leaderboard_http.connect("request_completed", self, "_on_leaderboard_request_completed")
# Send request
leaderboard_http.request(url, headers, true, HTTPClient.METHOD_GET, "")
func _on_leaderboard_request_completed(result, response_code, headers, body):
var json = JSON.parse(body.get_string_from_utf8())
# Print data
print(json.result)
# Formatting as a leaderboard
var leaderboardFormatted = ""
for n in json.result.items.size():
leaderboardFormatted += str(json.result.items[n].rank)+str(". ")
leaderboardFormatted += str(json.result.items[n].player.id)+str(" - ")
leaderboardFormatted += str(json.result.items[n].score)+str("\n")
# Print the formatted leaderboard to the console
print(leaderboardFormatted)
# Clear node
leaderboard_http.queue_free()
func _upload_score(var score):
var data = { "score": str(score) }
var headers = ["Content-Type: application/json", "x-session-token:"+session_token]
submit_score_http = HTTPRequest.new()
add_child(submit_score_http)
submit_score_http.connect("request_completed", self, "_on_upload_score_request_completed")
# Send request
submit_score_http.request("https://api.lootlocker.io/game/leaderboards/"+leaderboard_key+"/submit", headers, true, HTTPClient.METHOD_POST, to_json(data))
# Print what we're sending, for debugging purposes:
print(data)
func _on_upload_score_request_completed(result, response_code, headers, body) :
var json = JSON.parse(body.get_string_from_utf8())
# Print data
print(json.result)
# Clear node
submit_score_http.queue_free()
@josephdevelops
Copy link

Any chance of getting this updated to godot 4?

@Infini-Creation
Copy link

@josephdevelops : here it is, with some little modifications here or there, unfortunately, markdown is really annoying and I don't bother making it looks good here (here is better) updated & tested with v4.1.stable.official [970459615]

`extends Node

Use this game API key if you want to test it with a functioning leaderboard

"987dbd0b9e5eb3749072acc47a210996eea9feb0"

var game_API_key = "your-game-API-key-here"
var development_mode = true
var leaderboard_key = "leaderboardKey"
var session_token = ""
var score = 0

HTTP Request node can only handle one call per node

var auth_http = HTTPRequest.new()
var leaderboard_http = HTTPRequest.new()
var submit_score_http = HTTPRequest.new()

func _ready():
_authentication_request()

func _process(_delta):
if(Input.is_action_just_pressed("ui_up")):
score += 1
print("CurrentScore:"+str(score))

if(Input.is_action_just_pressed("ui_down")):
	score -= 1
	print("CurrentScore:"+str(score))

# Upload score when pressing enter
if(Input.is_action_just_pressed("ui_accept")):
	_upload_score(score)

# Get score when pressing spacebar
if(Input.is_action_just_pressed("ui_select")):
	_get_leaderboards()

func _authentication_request():
var player_identifier : String
# Check if a player session has been saved
var player_session_exists = false
var file = FileAccess.open("user://LootLocker.data", FileAccess.READ)
if file != null:
player_identifier = file.get_as_text()
print("played ID="+player_identifier)
file.close()

if player_identifier != null and player_identifier.length() > 1:
	print("player session exists, id="+player_identifier)
	player_session_exists = true
	
## Convert data to json string:
var data = { "game_key": game_API_key, "game_version": "0.0.0.1", "development_mode": true }

# If a player session already exists, send with the player identifier
if(player_session_exists == true):
	data = { "game_key": game_API_key, "player_identifier":player_identifier, "game_version": "0.0.0.1", "development_mode": true }

# Add 'Content-Type' header:
var headers = ["Content-Type: application/json"]

# Create a HTTPRequest node for authentication
auth_http = HTTPRequest.new()
add_child(auth_http)
auth_http.request_completed.connect(_on_authentication_request_completed)

# Print what we're sending, for debugging purposes:
print(data)

auth_http.request("https://api.lootlocker.io/game/v2/session/guest", headers, HTTPClient.METHOD_POST, JSON.stringify(data))

func _on_authentication_request_completed(result, response_code, headers, body):
var json = JSON.parse_string(body.get_string_from_utf8())
print(json)

# Save player_identifier to file
var file = FileAccess.open("user://LootLocker.data", FileAccess.WRITE)
if file != null:
	print("file open for writing")
	if json.has("player_identifier"):
		print("store played id")
		file.store_string(json["player_identifier"])
		file.close()

		# Save session_token to memory
		print("session token="+json["session_token"])
		session_token = json["session_token"]
	else:
		if json.has("error"):
			print("Error: "+json["error"])


# Clear node
auth_http.queue_free()
# Get leaderboards
_get_leaderboards()

func _get_leaderboards():
print("Getting leaderboards")
var url = "https://api.lootlocker.io/game/leaderboards/"+leaderboard_key+"/list?count=10"
var headers = ["Content-Type: application/json", "x-session-token:"+session_token]

# Create a request node for getting the highscore
leaderboard_http = HTTPRequest.new()
add_child(leaderboard_http)
leaderboard_http.request_completed.connect(_on_leaderboard_request_completed)
# Send request
leaderboard_http.request(url, headers, HTTPClient.METHOD_GET, "")

func _on_leaderboard_request_completed(result, response_code, headers, body):
var json = JSON.parse_string(body.get_string_from_utf8())

print(json)
if json.has("error"):
	print("Error: "+json["error"])
else:
	# Formatting as a leaderboard
	var leaderboardFormatted = ""
	for n in json["items"].size():
		leaderboardFormatted += str(json["items"][n].rank)+str(". ")
		leaderboardFormatted += str(json["items"][n].player.id)+str(" - ")
		leaderboardFormatted += str(json["items"][n].score)
		if json["items"][n].metadata != null:
			print("add meta:"+json["items"][n].metadata)
			leaderboardFormatted += str(" - ")+json["items"][n].metadata
		leaderboardFormatted += str("\n")
	
	# Print the formatted leaderboard to the console
	print(leaderboardFormatted)
	
	# Clear node
	leaderboard_http.queue_free()

func _upload_score(score: int):
var data = { "score": str(score) }
var headers = ["Content-Type: application/json", "x-session-token:"+session_token]
submit_score_http = HTTPRequest.new()
add_child(submit_score_http)
submit_score_http.request_completed.connect(_on_upload_score_request_completed)

# Print what we're sending, for debugging purposes:
print(data)

submit_score_http.request("https://api.lootlocker.io/game/leaderboards/"+leaderboard_key+"/submit", headers, HTTPClient.METHOD_POST, JSON.stringify(data))

func _on_upload_score_request_completed(result, response_code, headers, body):
var json = JSON.parse_string(body.get_string_from_utf8())

# Print data
print("upload score result:"+str(json))

# Clear node
submit_score_http.queue_free()

`

@dudecon
Copy link

dudecon commented Dec 1, 2023

Any chance of getting this updated to godot 4?

I just got it working on Godot Engine v4.1.3
Can't figure out how to PR my fork, so for now my working code is here:
https://gist.github.com/dudecon/48105f960a55eccd77ab0517d15d079f

@samtse
Copy link

samtse commented Jun 30, 2024

i just gave this a whirl in godot 3.5 and got an error with this line:
for n in json.result.items.size():
not sure where to go from here..? lootlocker looks brilliant for my purposes so would really like to get past this...
see screenshot here:
2024-06-30_15-37-19

@Infini-Creation
Copy link

@samtse: you got this error because most likely the request return no result at all, thus json.result is null.
Your screenshot unfortunately doesn't show the variables so it needs to be confirmed.

Remember when working with network: ALWAYS, always, check results, all the items from top to bottom, here for instance, json not null, then result not null AND a proper array, and so on...
The code you've used is not actually production ready as it is just a sample which need to be completed to work in ALL possible cases.

@samtse
Copy link

samtse commented Jun 30, 2024 via email

@samtse
Copy link

samtse commented Jul 7, 2024 via email

@samtse
Copy link

samtse commented Jul 7, 2024 via email

@samtse
Copy link

samtse commented Jul 7, 2024 via email

@samtse
Copy link

samtse commented Jul 7, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment