155 lines
4.6 KiB
GDScript
155 lines
4.6 KiB
GDScript
class_name AccountManager
|
|
extends Node
|
|
|
|
signal profile_changed
|
|
|
|
const ACCOUNT_PATH := "user://void_bastion_account.json"
|
|
|
|
var player_id := ""
|
|
var display_name := ""
|
|
var primary_provider := "guest"
|
|
var linked_identities: Array = []
|
|
var highscores: Dictionary = {}
|
|
var pending_submissions: Array = []
|
|
var created_at := 0
|
|
var storage_enabled := true
|
|
|
|
|
|
func _ready() -> void:
|
|
_load_or_create_profile()
|
|
|
|
|
|
func _load_or_create_profile() -> void:
|
|
if FileAccess.file_exists(ACCOUNT_PATH):
|
|
var file := FileAccess.open(ACCOUNT_PATH, FileAccess.READ)
|
|
if file:
|
|
var data = JSON.parse_string(file.get_as_text())
|
|
if data is Dictionary:
|
|
player_id = str(data.get("player_id", ""))
|
|
display_name = str(data.get("display_name", ""))
|
|
primary_provider = str(data.get("primary_provider", "guest"))
|
|
linked_identities = data.get("linked_identities", [])
|
|
highscores = data.get("highscores", {})
|
|
pending_submissions = data.get("pending_submissions", [])
|
|
created_at = int(data.get("created_at", 0))
|
|
if player_id.is_empty():
|
|
_create_guest_profile()
|
|
if display_name.is_empty():
|
|
display_name = "PILOT-%s" % player_id.right(4).to_upper()
|
|
_save_profile()
|
|
|
|
|
|
func _create_guest_profile() -> void:
|
|
var random_bytes := Crypto.new().generate_random_bytes(16)
|
|
player_id = "guest_%s" % random_bytes.hex_encode()
|
|
display_name = "PILOT-%s" % player_id.right(4).to_upper()
|
|
primary_provider = "guest"
|
|
linked_identities = []
|
|
highscores = {}
|
|
pending_submissions = []
|
|
created_at = int(Time.get_unix_time_from_system())
|
|
|
|
|
|
func _save_profile() -> void:
|
|
if not storage_enabled:
|
|
return
|
|
var file := FileAccess.open(ACCOUNT_PATH, FileAccess.WRITE)
|
|
if not file:
|
|
return
|
|
file.store_string(JSON.stringify({
|
|
"player_id": player_id,
|
|
"display_name": display_name,
|
|
"primary_provider": primary_provider,
|
|
"linked_identities": linked_identities,
|
|
"highscores": highscores,
|
|
"pending_submissions": pending_submissions,
|
|
"created_at": created_at
|
|
}))
|
|
|
|
|
|
func record_run(map_index: int, difficulty_index: int, endless: bool, reached_wave: int, score: int) -> bool:
|
|
var mode := "endless" if endless else "mission"
|
|
var key := "%d:%d:%s" % [map_index, difficulty_index, mode]
|
|
var previous: Dictionary = highscores.get(key, {})
|
|
if int(previous.get("score", -1)) >= score:
|
|
return false
|
|
var record := {
|
|
"map": map_index,
|
|
"difficulty": difficulty_index,
|
|
"mode": mode,
|
|
"wave": reached_wave,
|
|
"score": score,
|
|
"recorded_at": int(Time.get_unix_time_from_system())
|
|
}
|
|
highscores[key] = record
|
|
pending_submissions.append(record.duplicate(true))
|
|
_save_profile()
|
|
profile_changed.emit()
|
|
return true
|
|
|
|
|
|
func attach_online_identity(online_user_id: String, online_username: String) -> void:
|
|
if online_user_id.is_empty():
|
|
return
|
|
var identity := {"provider": "nakama", "user_id": online_user_id}
|
|
if not linked_identities.has(identity):
|
|
linked_identities.append(identity)
|
|
if not online_username.is_empty() and display_name.begins_with("PILOT-"):
|
|
display_name = online_username
|
|
_save_profile()
|
|
profile_changed.emit()
|
|
|
|
|
|
func mark_submission_complete(record: Dictionary) -> void:
|
|
for index in range(pending_submissions.size() - 1, -1, -1):
|
|
var queued = pending_submissions[index]
|
|
if queued is Dictionary and _same_run(queued, record):
|
|
pending_submissions.remove_at(index)
|
|
_save_profile()
|
|
profile_changed.emit()
|
|
return
|
|
|
|
|
|
func _same_run(left: Dictionary, right: Dictionary) -> bool:
|
|
return int(left.get("map", -1)) == int(right.get("map", -2)) \
|
|
and int(left.get("difficulty", -1)) == int(right.get("difficulty", -2)) \
|
|
and str(left.get("mode", "")) == str(right.get("mode", "_")) \
|
|
and int(left.get("wave", -1)) == int(right.get("wave", -2)) \
|
|
and int(left.get("score", -1)) == int(right.get("score", -2))
|
|
|
|
|
|
func get_map_best_wave(map_index: int, endless := false) -> int:
|
|
var mode := "endless" if endless else "mission"
|
|
var result := 0
|
|
for difficulty_index in 3:
|
|
var key := "%d:%d:%s" % [map_index, difficulty_index, mode]
|
|
var record: Dictionary = highscores.get(key, {})
|
|
result = maxi(result, int(record.get("wave", 0)))
|
|
return result
|
|
|
|
|
|
func get_map_best_score(map_index: int, endless := false) -> int:
|
|
var mode := "endless" if endless else "mission"
|
|
var result := 0
|
|
for difficulty_index in 3:
|
|
var key := "%d:%d:%s" % [map_index, difficulty_index, mode]
|
|
var record: Dictionary = highscores.get(key, {})
|
|
result = maxi(result, int(record.get("score", 0)))
|
|
return result
|
|
|
|
|
|
func provider_label() -> String:
|
|
match primary_provider:
|
|
"apple":
|
|
return "APPLE / GAME CENTER"
|
|
"google":
|
|
return "GOOGLE PLAY GAMES"
|
|
"email":
|
|
return "E-MAIL"
|
|
_:
|
|
return "GASTPROFIL • NUR DIESES GERÄT"
|
|
|
|
|
|
func short_id() -> String:
|
|
return player_id.right(12).to_upper()
|