Cache character pictures and songs on disk
Build / test (push) Successful in 53s
Build / build (push) Successful in 1m13s

Character pictures are kept in characters/ next to the settings, with an
index.json of when the server last changed each one and when it was
downloaded. Only new or changed pictures are downloaded, using the server's new
/character/details. Older servers fall back to the name list, and pictures are
downloaded again after 7 days.

Downloaded songs are written to songs/ and only their paths are kept in memory.
The folder is emptied when the game starts and when the playlist resets.
This commit is contained in:
Sansan committed 2026-10-07 21:57:27 +02:00
1 parent 62fa63fd8b
commit 240c331ab2
17 files changed
+912 -48

No files matched your search

+6 -8
View File
@@ -16,17 +16,15 @@ func _ready() -> void:
mouse_exited.connect(_set_hovered.bind(false))
## Shows [param character_name] and fetches its picture from the server.
func set_character_name(character_name: String) -> void:
## Shows [param character_name] and its picture. [param fetch_image] is called with the
## name and a Callable that takes the picture as an [Image], e.g.
## [method CharacterCache.fetch_image].
func set_character_name(character_name: String, fetch_image: Callable) -> void:
character_name_label.text = display_name(character_name)
tooltip_text = character_name_label.text
var image_fetched: Callable = func image_fetched(image: PackedByteArray) -> void:
var picture: Image = image_from_bytes(image)
if picture == null:
GameLog.warning("Could not load the picture of ", character_name)
return
var image_fetched: Callable = func image_fetched(picture: Image) -> void:
character_image.texture = ImageTexture.create_from_image(picture)
MusicServerClient.fetch_character_image(character_name, image_fetched)
fetch_image.call(character_name, image_fetched)
## The name to show for a picture's [param file_name]: without the file extension, and
+11 -10
View File
@@ -6,6 +6,8 @@ signal character_selected(texture: ImageTexture)
var can_select_character: bool = false
var character: PackedScene = preload("res://popups/CharacterCard.tscn")
## Keeps the pictures on disk, so only changed ones are downloaded.
var character_cache: CharacterCache = CharacterCache.new()
@onready var character_panel: Panel = %CharacterPanel
@onready var title_label: Label = %TitleLabel
@@ -25,17 +27,16 @@ func _on_close_timeout() -> void:
func load_characters() -> void:
GameLog.debug("load_characters")
var fetch_character_list: Callable = func fetch_character_list(list: Variant) -> void:
GameLog.debug("fetch_character_list")
var list_loaded: Callable = func list_loaded(names: Array[String]) -> void:
GameLog.debug("list_loaded")
Settings.delete_children(character_grid)
if typeof(list) == TYPE_ARRAY:
for character_name: String in list:
GameLog.debug("character_name ", character_name)
var character_box: CharacterCard = character.instantiate()
character_grid.add_child(character_box)
character_box.set_character_name(character_name)
character_box.new_character_selected.connect(_on_character_selected)
MusicServerClient.fetch_character_list(fetch_character_list)
for character_name: String in names:
GameLog.debug("character_name ", character_name)
var character_box: CharacterCard = character.instantiate()
character_grid.add_child(character_box)
character_box.set_character_name(character_name, character_cache.fetch_image)
character_box.new_character_selected.connect(_on_character_selected)
character_cache.load_list(list_loaded)
func show_grid(player_name: String) -> void: