diff --git a/CHANGELOG.md b/CHANGELOG.md index cc94594..f9d270b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## v1.6.0 +### Load Snapshots +The [loadPlayerCenteredScores](https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient#load(boolean)) method from Google's API has been added, returning the list of Snapshots for the current signed in player. + ## v1.5.0 ### Order of autoloads The autoloads where causing errors on first launch of the project, due to the load order and dependencies between them. The load order has now been fixed to avoid this errors. Also, the plugin is now disabled by default in the demo project. Look at the [demo project documentation](https://github.com/Iakobs/godot-play-game-services/tree/main/plugin/demo) for further info. diff --git a/plugin/export_scripts_template/autoloads/snapshots_client.gd b/plugin/export_scripts_template/autoloads/snapshots_client.gd index ab8ebce..29b844f 100644 --- a/plugin/export_scripts_template/autoloads/snapshots_client.gd +++ b/plugin/export_scripts_template/autoloads/snapshots_client.gd @@ -22,6 +22,11 @@ signal game_loaded(snapshot: Snapshot) ## [param conflict]: The conflict containing and id and both conflicting snapshots. signal conflict_emitted(conflict: SnapshotConflict) +## Signal emitted after calling the [method load_snapshots] method.[br] +## [br] +## [param snapshots]: The list of snapshots for the current signed in player. +signal snapshots_loaded(snapshots: Array[SnapshotMetadata]) + ## Constant passed to the [method show_saved_games] method to not limit the number of displayed saved files. const DISPLAY_LIMIT_NONE := -1 @@ -37,6 +42,13 @@ func _ready() -> void: GodotPlayGameServices.android_plugin.conflictEmitted.connect(func(dictionary: Dictionary): conflict_emitted.emit(SnapshotConflict.new(dictionary)) ) + GodotPlayGameServices.android_plugin.snapshotsLoaded.connect(func(json_data: String): + var safe_array := GodotPlayGameServices.json_marshaller.safe_parse_array(json_data) + var snapshots: Array[SnapshotMetadata] = [] + for dictionary: Dictionary in safe_array: + snapshots.append(SnapshotMetadata.new(dictionary)) + snapshots_loaded.emit(snapshots) + ) ## Opens a new window to display the saved games for the current player. If you select ## a saved game, the [signal game_loaded] signal will be emitted.[br] @@ -77,10 +89,20 @@ func save_game( ## This method emits the [signal game_loaded] signal.[br] ## [br] ## [param fileName]: The name of the save file. Must be between 1 and 100 non-URL-reserved charactes (a-z, A-Z, 0-9, or the symbols "-", ".", "_", or "~"). -func load_game(file_name: String): +func load_game(file_name: String) -> void: if GodotPlayGameServices.android_plugin: GodotPlayGameServices.android_plugin.loadGame(file_name) +## Loads the list of [SnapshotMetadata] of the current signed in player.[br] +## [br] +## [param force_reload]: If true, this call will clear any locally cached +## data and attempt to fetch the latest data from the server. Send it set to [code]true[/code] +## the first time, and [code]false[/code] in subsequent calls, or when you want +## to clear the cache. +func load_snapshots(force_reload: bool) -> void: + if GodotPlayGameServices.android_plugin: + GodotPlayGameServices.android_plugin.loadSnapshots(force_reload) + ## A snapshot. class Snapshot: var content: PackedByteArray ## A [PackedByteArray] with the contents of the snapshot. diff --git a/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/GodotAndroidPlugin.kt b/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/GodotAndroidPlugin.kt index fede57a..8bfc786 100644 --- a/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/GodotAndroidPlugin.kt +++ b/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/GodotAndroidPlugin.kt @@ -426,4 +426,15 @@ class GodotAndroidPlugin(godot: Godot) : GodotPlugin(godot) { */ @UsedByGodot fun loadGame(fileName: String) = snapshotsProxy.loadGame(fileName) + + /** + * Loads the list of [com.google.android.gms.games.snapshot.SnapshotMetadata](https://developers.google.com/android/reference/com/google/android/gms/games/snapshot/SnapshotMetadata) + * for the current signed in Player. This method emits the [com.jacobibanez.plugin.android.godotplaygameservices.signals.SnapshotSignals.snapshotsLoaded] + * signal. + * + * @param forceReload If true, this call will clear any locally cached data and attempt to fetch + * the latest data from the server. + */ + @UsedByGodot + fun loadSnapshots(forceReload: Boolean) = snapshotsProxy.loadSnapshots(forceReload) } diff --git a/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/signals/Signals.kt b/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/signals/Signals.kt index 33a00c2..ef8db5f 100644 --- a/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/signals/Signals.kt +++ b/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/signals/Signals.kt @@ -26,6 +26,7 @@ fun getSignals(): MutableSet = mutableSetOf( SnapshotSignals.gameSaved, SnapshotSignals.gameLoaded, SnapshotSignals.conflictEmitted, + SnapshotSignals.snapshotsLoaded, HelperSignals.imageStored, ) @@ -191,6 +192,13 @@ object SnapshotSignals { * @return A [Dictionary] representing a [com.google.android.gms.games.SnapshotsClient.SnapshotConflict](https://developers.google.com/android/reference/com/google/android/gms/games/SnapshotsClient.SnapshotConflict). */ val conflictEmitted = SignalInfo("conflictEmitted", Dictionary::class.java) + + /** + * This signal is emitted when calling the [com.jacobibanez.plugin.android.godotplaygameservices.GodotAndroidPlugin.loadSnapshots] method. + * + * @return A [List] of [com.google.android.gms.games.snapshot.SnapshotMetadata](https://developers.google.com/android/reference/com/google/android/gms/games/snapshot/SnapshotMetadata). + */ + val snapshotsLoaded = SignalInfo("snapshotsLoaded", String::class.java) } object HelperSignals { diff --git a/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/snapshots/SnapshotsProxy.kt b/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/snapshots/SnapshotsProxy.kt index 79c8b49..17adfa8 100644 --- a/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/snapshots/SnapshotsProxy.kt +++ b/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/snapshots/SnapshotsProxy.kt @@ -12,10 +12,13 @@ import com.google.android.gms.games.SnapshotsClient.RESOLUTION_POLICY_MOST_RECEN import com.google.android.gms.games.SnapshotsClient.SnapshotConflict import com.google.android.gms.games.snapshot.SnapshotMetadata import com.google.android.gms.games.snapshot.SnapshotMetadataChange +import com.google.gson.Gson import com.jacobibanez.plugin.android.godotplaygameservices.BuildConfig.GODOT_PLUGIN_NAME import com.jacobibanez.plugin.android.godotplaygameservices.signals.SnapshotSignals.conflictEmitted import com.jacobibanez.plugin.android.godotplaygameservices.signals.SnapshotSignals.gameLoaded import com.jacobibanez.plugin.android.godotplaygameservices.signals.SnapshotSignals.gameSaved +import com.jacobibanez.plugin.android.godotplaygameservices.signals.SnapshotSignals.snapshotsLoaded +import org.godotengine.godot.Dictionary import org.godotengine.godot.Godot import org.godotengine.godot.plugin.GodotPlugin.emitSignal @@ -116,6 +119,41 @@ class SnapshotsProxy( } } + fun loadSnapshots(forceReload: Boolean) { + Log.d(tag, "Loading snapshots") + snapshotsClient.load(forceReload).addOnCompleteListener { task -> + if (task.isSuccessful) { + Log.d( + tag, + "Snapshots loaded successfully. Data is stale? ${task.result.isStale}" + ) + val snapshots = task.result.get()!! + val result: List = snapshots.map { snapshotMetadata -> + fromSnapshotMetadata(godot, snapshotMetadata) + }.toList() + snapshots.release() + emitSignal( + godot, + GODOT_PLUGIN_NAME, + snapshotsLoaded, + Gson().toJson(result) + ) + } else { + Log.e( + tag, + "Failed to load snapshots. Cause: ${task.exception}", + task.exception + ) + emitSignal( + godot, + GODOT_PLUGIN_NAME, + snapshotsLoaded, + Gson().toJson(null) + ) + } + } + } + private fun handleConflict(conflict: SnapshotConflict?) { conflict?.let { val snapshot = it.snapshot