Compare commits

..

2 Commits

Author SHA1 Message Date
b82f5e4c19 adds some documentation 2025-04-24 18:43:26 -04:00
fe38fc49bf completely redoes the caching api 2025-04-24 18:25:28 -04:00
2 changed files with 124 additions and 95 deletions

View File

@ -1,129 +1,152 @@
extends Node extends Node
var _card_id
var _img_path
var _req_headers
signal cache_done signal cache_done
var _req_headers
var _consts = preload("res://data/consts.gd") var _consts = preload("res://data/consts.gd")
func _init() -> void: func _init() -> void:
_req_headers = PackedStringArray(["User-Agent: " + _consts.APP_NAME + "/" + _consts.APP_VERSION, "Accept: */*"]) _req_headers = PackedStringArray(["User-Agent: " + _consts.APP_NAME + "/" + _consts.APP_VERSION, "Accept: */*"])
func _cache_error(err: String) -> String: func _cache_error(err: String) -> String:
return "CACHE::ERROR::" + err + "\n" return "CACHE::ERROR::" + err + "\n"
func _check_cache(id: String) -> bool: func _get_dict_from_file(filepath: String) -> Dictionary:
if !FileAccess.file_exists("user://card_cache/" + id + "/card.json"): var file = FileAccess.open(filepath, FileAccess.READ)
return false var data = JSON.parse_string(file.get_as_text())
if !FileAccess.file_exists("user://card_cache/" + id + "/card.png"):
return false return data
return true
## get_card_data_from_name
##
## _name: String [br]
## A wrapper for searching for a card by name. Use **get_card_data_from_id** where possible, as it avoids an expensive search for the new card, if the card has been cached already.
func get_card_data_from_name(_name: String) -> Dictionary:
return _get_card_data_from_bulk("name", _name)
func custom_query_fetch(query: String) -> String: ## get_card_data_from_id
var error = await _do_custom_http_request_card(query) ##
if error != OK: ## id: String [br]
return "NONE" ## This is the preferred wrapper to use when fetching card data, it checks the cache for preexisting data and uses that if it's available. Otherwise, it will search the bulk json for the data.
OS.delay_msec(100) func get_card_data_from_id(id: String) -> Dictionary:
await _do_http_request_imgs(_card_id) if FileAccess.file_exists("user://card_cache/" + id + "/card.json"):
OS.delay_msec(100) return _get_dict_from_file("user://card_cache/" + id + "/card.json")
cache_done.emit() return _get_card_data_from_bulk("id", id)
return _card_id
func _do_custom_http_request_card(query: String) -> Error: func _get_card_data_from_bulk(field: String, search_query: String) -> Dictionary:
var httpr = HTTPRequest.new() var file = FileAccess.open("user://card_cache/bulk.json", FileAccess.READ)
add_child(httpr) var bulk_json = JSON.parse_string(file.get_as_text())
var error = httpr.request(query, _req_headers)
if error != OK:
push_error(_cache_error("GET_REQUEST") + "An error occurred in the Scryfall request.")
var response = await httpr.request_completed var selected_entry = null
for entry in bulk_json:
if entry[field] == search_query:
selected_entry = entry
break
continue
file = null
if response[0] != HTTPRequest.RESULT_SUCCESS: if selected_entry == null:
push_error(_cache_error("GET_REQUEST") + "Failed to fetch card data from Scryfall") return {}
return FAILED
var unprocessed_body = response[3].get_string_from_utf8() if selected_entry["image_status"] != "missing":
var card_content = JSON.parse_string(unprocessed_body) _fetch_card_img(selected_entry)
if card_content == null:
push_error(_cache_error("PARSING") + "Failed to parse the Scryfall card results.")
_card_id = card_content["id"]
if _check_cache(_card_id):
return FAILED
var dir = DirAccess.open("user://") var dir = DirAccess.open("user://")
dir.make_dir_recursive("user://card_cache/" + _card_id + "/") # lets ensure the path is there dir.make_dir_recursive("user://card_cache/" + selected_entry["id"] + "/")
dir = null dir = null
var card_cache = FileAccess.open("user://card_cache/" + _card_id + "/card.json", FileAccess.WRITE) file = FileAccess.open("user://card_cache/" + selected_entry["id"] + "/card.json", FileAccess.WRITE)
card_cache.store_string(unprocessed_body) # cache the json response file.store_line(JSON.stringify(selected_entry, "\t"))
card_cache = null # closes the file file = null
var image_uris = card_content["image_uris"] return selected_entry
_img_path = image_uris["png"]
func _fetch_card_img(data: Dictionary) -> Error:
if FileAccess.file_exists("user://card_cache/" + data["id"] + "card.png"):
return OK return OK
func fetch_card(id: String) -> void:
if _check_cache(id):
return
await _do_http_id_request_card(id)
OS.delay_msec(100)
await _do_http_request_imgs(id)
OS.delay_msec(100)
cache_done.emit()
func _do_http_request_imgs(id: String) -> void:
var httpr = HTTPRequest.new() var httpr = HTTPRequest.new()
add_child(httpr) add_child(httpr)
var error = httpr.request(_img_path, _req_headers) var err = httpr.request((data["image_uris"])["png"], _req_headers)
if error != OK: if err != OK:
push_error(_cache_error("GET_REQUEST") + "An error occurred in the Scryfall request.") push_error(_cache_error("GET_REQUEST") + "An error occured in the Scryfall request.")
var response = await httpr.request_completed return FAILED
var resp = await httpr.request_completed
var img = Image.new() var img = Image.new()
error = img.load_png_from_buffer(response[3]) err = img.load_png_from_buffer(resp[3])
if error != OK: if err != OK:
push_error(_cache_error("IMG_LOADING") + "Couldn't load the image.") push_error(_cache_error("IMG_LOADING") + "Couldn't load the image.")
return FAILED
img.save_png("user://card_cache/" + id + "/card.png") var dir = DirAccess.open("user://")
dir.make_dir_recursive("user://card_cache/" + data["id"] + "/")
dir = null
img.save_png("user://card_cache/" + data["id"] + "/card.png")
img = null img = null
return OK
func get_bulk_data(force: bool) -> Error:
if FileAccess.file_exists("user://card_cache/bulk.json"):
if force:
DirAccess.remove_absolute("user://card_cahce/bulk.json")
else:
return OK
func _do_http_id_request_card(id: String) -> void:
var httpr = HTTPRequest.new() var httpr = HTTPRequest.new()
add_child(httpr) add_child(httpr)
var error = httpr.request("https://api.scryfall.com/cards/" + id, _req_headers)
var error = httpr.request("https://api.scryfall.com/bulk-data/unique-artwork", _req_headers)
if error != OK: if error != OK:
push_error(_cache_error("GET_REQUEST") + "An error occurred in the Scryfall request.") push_error(_cache_error("GET_REQUEST") + "An error occurred in the Scryfall request.")
return FAILED
var response = await httpr.request_completed var response = await httpr.request_completed
if response[0] != HTTPRequest.RESULT_SUCCESS: if response[0] != HTTPRequest.RESULT_SUCCESS:
push_error(_cache_error("GET_REQUEST") + "Failed to fetch card data from Scryfall") push_error(_cache_error("GET_REQUEST") + "Failed to fetch card data from Scryfall")
return return FAILED
var unprocessed_body = response[3].get_string_from_utf8() var unprocessed_body = response[3].get_string_from_utf8()
var card_content = JSON.parse_string(unprocessed_body) var card_content = JSON.parse_string(unprocessed_body)
if card_content == null: if card_content == null:
push_error(_cache_error("PARSING") + "Failed to parse the Scryfall card results.") push_error(_cache_error("PARSING") + "Failed to parse the Scryfall card results.")
return FAILED
error = httpr.request(card_content["download_uri"], _req_headers)
if error != OK:
push_error(_cache_error("GET_REQUEST") + "An error occurred in the Scryfall request.")
return FAILED
response = await httpr.request_completed
if response[0] != HTTPRequest.RESULT_SUCCESS:
push_error(_cache_error("GET_REQUEST") + "Failed to fetch card data from Scryfall")
return FAILED
unprocessed_body = response[3].get_string_from_utf8()
card_content = JSON.parse_string(unprocessed_body)
if card_content == null:
push_error(_cache_error("PARSING") + "Failed to parse the Scryfall card results.")
return FAILED
var dir = DirAccess.open("user://") var dir = DirAccess.open("user://")
dir.make_dir_recursive("user://card_cache/" + id + "/") # lets ensure the path is there dir.make_dir_recursive("user://card_cache/") # lets ensure the path is there
dir = null dir = null
var card_cache = FileAccess.open("user://card_cache/" + id + "/card.json", FileAccess.WRITE) var data_cache = FileAccess.open("user://card_cache/bulk.json", FileAccess.WRITE)
card_cache.store_string(unprocessed_body) # cache the json response data_cache.store_string(unprocessed_body)
card_cache = null # closes the file data_cache = null
var image_uris = card_content["image_uris"] cache_done.emit()
_img_path = image_uris["png"]
return OK

View File

@ -2,18 +2,24 @@ extends Node2D
var player_class = preload("res://player.gd") var player_class = preload("res://player.gd")
var deck_input = preload("res://deck_input.gd") var deck_input = preload("res://deck_input.gd")
var _caching = preload("res://caching.gd")
# Called when the node enters the scene tree for the first time. # Called when the node enters the scene tree for the first time.
func _ready() -> void: func _ready() -> void:
var cache = _caching.new()
add_child(cache)
cache.get_bulk_data(false)
# TODO: Create 2-4 player instances as children of this tabletop node. # TODO: Create 2-4 player instances as children of this tabletop node.
var player = player_class.new() var player = player_class.new()
add_child(player) add_child(player)
move_child(player, 0) move_child(player, 0)
var deck = deck_input.new() cache.get_card_data_from_name("1996 World Champion")
add_child(deck)
#var deck = deck_input.new()
#add_child(deck)
pass # Replace with function body. pass # Replace with function body.