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

+85
View File
@@ -0,0 +1,85 @@
extends GdUnitTestSuite
## Downloaded songs are kept in files in the songs folder, not in memory.
var _snapshot: AutoloadSnapshot
var _config_dir_before: String
var _mp3: PackedByteArray
func before_test() -> void:
_snapshot = AutoloadSnapshot.take([Playlist])
_config_dir_before = OS.get_environment(Settings.CONFIG_DIR_ENV)
OS.set_environment(Settings.CONFIG_DIR_ENV, create_temp_dir("song_files"))
Playlist.clear_song_files()
Playlist.song_object_array.clear()
_mp3 = FileAccess.get_file_as_bytes("res://tests/data/short.mp3")
func after_test() -> void:
Playlist.clear_song_files()
OS.set_environment(Settings.CONFIG_DIR_ENV, _config_dir_before)
_snapshot.restore()
func _add_song() -> SongObject:
var song_object: SongObject = SongObject.new()
Playlist.store_song(song_object, _mp3)
Playlist.add_to_playlist(song_object)
return song_object
func test_stored_song_is_a_file_and_plays_back() -> void:
var song_object: SongObject = _add_song()
assert_object(song_object.song).is_null()
assert_bool(FileAccess.file_exists(song_object.song_path)).is_true()
var stream: AudioStream = Playlist.get_song(0)
assert_object(stream).is_instanceof(AudioStreamMP3)
assert_float(stream.get_length()).is_greater(0.0)
func test_every_song_gets_a_file_of_its_own() -> void:
var first: SongObject = _add_song()
var second: SongObject = _add_song()
assert_str(first.song_path).is_not_equal(second.song_path)
assert_array(DirAccess.get_files_at(Playlist.songs_folder())).has_size(2)
func test_downloading_a_song_again_replaces_its_file() -> void:
var song_object: SongObject = _add_song()
var old_path: String = song_object.song_path
Playlist.add_song_to_song_object(0, _mp3)
assert_str(song_object.song_path).is_not_equal(old_path)
assert_object(Playlist.get_song(0)).is_not_null()
func test_resetting_the_playlist_deletes_the_files() -> void:
_add_song()
_add_song()
Playlist.reset_playlist()
assert_array(DirAccess.get_files_at(Playlist.songs_folder())).is_empty()
func test_missing_file_gives_no_song_so_it_is_downloaded_again() -> void:
var song_object: SongObject = _add_song()
DirAccess.remove_absolute(song_object.song_path)
assert_object(Playlist.get_song(0)).is_null()
func test_song_stays_in_memory_when_it_cannot_be_saved() -> void:
# A file where the folder should be, so the folder can't be made
var blocker: String = create_temp_dir("song_files_blocked").path_join("not_a_folder")
FileAccess.open(blocker, FileAccess.WRITE).store_string("x")
OS.set_environment(Settings.CONFIG_DIR_ENV, blocker)
var song_object: SongObject = _add_song()
assert_str(song_object.song_path).is_empty()
assert_object(Playlist.get_song(0)).is_instanceof(AudioStreamMP3)