The Winner popup now shows every player's score after each song as a step line, with the winning score marked, and three facts under it: the longest streak, the longest standstill and the song most players scored on. The data comes from the points each song already records, through the new ScoreHistory. The popup grows to 1600x920 with the graph across the full width, so a 60-song game with five players stays readable. Reset points now starts a new game: it clears the points on the songs and the graph starts after the song that was playing. Songs already on the server at startup count as an earlier game. The screenshot tour has a long five-player game, and only the Winner popup differs from before.
101 lines
3.8 KiB
GDScript
101 lines
3.8 KiB
GDScript
class_name SongLoader
|
|
extends Node
|
|
## Downloads songs from the server into the Playlist ahead of time, so the next song
|
|
## can start at once.
|
|
##
|
|
## How many songs it keeps ready is the cache size in the settings
|
|
## ([code]Playlist.number_of_tracks_to_preload[/code]).
|
|
|
|
## Emitted when the songs already in the server playlist have been loaded into the
|
|
## Playlist.
|
|
|
|
signal song_list_loaded
|
|
|
|
## Emitted when a new song has been downloaded and added to the Playlist.
|
|
signal song_added
|
|
|
|
## Seconds to wait before retrying a download step that failed.
|
|
var retry_seconds: float = 5.0
|
|
|
|
|
|
## Loads the songs already in the server playlist, then starts preloading new ones.
|
|
## Preloading waits for the list, because loading the list clears the playlist.
|
|
func load_song_list() -> void:
|
|
GameLog.debug("load_song_list")
|
|
var song_list_fetched: Callable = func song_list_fetched(songs: Array[SongInfo]) -> void:
|
|
Playlist.clear_song_list()
|
|
for info: SongInfo in songs:
|
|
var new_song_object: SongObject = SongObject.new()
|
|
new_song_object.song_number = info.song_no
|
|
new_song_object.soundtrack_title = info.soundtrack
|
|
new_song_object.song_title = info.song
|
|
new_song_object.is_answered = true
|
|
new_song_object.has_played = true
|
|
Playlist.add_to_playlist(new_song_object)
|
|
Playlist.update_last_played_song()
|
|
# Songs already on the server were played before, so the game starts after them
|
|
Playlist.game_start_song = Playlist.song_object_array.size()
|
|
song_list_loaded.emit()
|
|
fetch_song_if_idle()
|
|
MusicServerClient.fetch_song_list(song_list_fetched, _retry_later.bind(load_song_list))
|
|
|
|
|
|
## Starts downloading one more song, which keeps downloading until the cache is full.
|
|
func fetch_song() -> void:
|
|
GameLog.debug("fetch_song")
|
|
Playlist.is_song_downloading = true
|
|
_download_random_song(SongObject.new())
|
|
|
|
|
|
## Starts downloading a song unless one is already downloading.
|
|
func fetch_song_if_idle() -> void:
|
|
if !Playlist.is_song_downloading:
|
|
fetch_song()
|
|
|
|
|
|
## Starts downloading if nothing is downloading and the cache is not full, e.g. after
|
|
## the cache size was raised.
|
|
func fill_cache() -> void:
|
|
if !Playlist.is_song_downloading && Playlist.should_preload_more_songs():
|
|
fetch_song()
|
|
|
|
|
|
# Fetching a song takes three requests. If one fails, only that step is retried, so
|
|
# the server and the game keep the same songs in their playlists.
|
|
func _download_random_song(new_song_object: SongObject) -> void:
|
|
var song_downloaded: Callable = func song_downloaded(body: PackedByteArray) -> void:
|
|
GameLog.debug("song_downloaded")
|
|
var sound: AudioStream = AudioStreamMP3.new()
|
|
sound.data = body
|
|
new_song_object.song = sound
|
|
_add_song_to_queue(new_song_object)
|
|
MusicServerClient.fetch_random_song(Settings.use_low_played_mode, song_downloaded,
|
|
_retry_later.bind(_download_random_song.bind(new_song_object)))
|
|
|
|
|
|
func _add_song_to_queue(new_song_object: SongObject) -> void:
|
|
MusicServerClient.add_to_queue(_fetch_song_info.bind(new_song_object),
|
|
_retry_later.bind(_add_song_to_queue.bind(new_song_object)))
|
|
|
|
|
|
func _fetch_song_info(new_song_object: SongObject) -> void:
|
|
var song_info_fetched: Callable = func song_info_fetched(info: SongInfo) -> void:
|
|
GameLog.debug("song_info_fetched")
|
|
new_song_object.song_number = info.song_no
|
|
new_song_object.soundtrack_title = info.soundtrack
|
|
new_song_object.song_title = info.song
|
|
GameLog.debug("new_song_object: ", new_song_object.to_string())
|
|
Playlist.add_to_playlist(new_song_object)
|
|
if Playlist.should_preload_more_songs():
|
|
fetch_song()
|
|
else:
|
|
Playlist.is_song_downloading = false
|
|
song_added.emit()
|
|
MusicServerClient.fetch_song_info(song_info_fetched,
|
|
_retry_later.bind(_fetch_song_info.bind(new_song_object)))
|
|
|
|
|
|
func _retry_later(step: Callable) -> void:
|
|
GameLog.warning("Song download failed, retrying in %s seconds" % retry_seconds)
|
|
get_tree().create_timer(retry_seconds).timeout.connect(step)
|