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 9ea429e..95d14e1 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 @@ -1,10 +1,13 @@ package com.jacobibanez.plugin.android.godotplaygameservices +import android.app.Activity +import android.content.Intent import android.util.Log +import android.view.View import com.google.android.gms.games.PlayGamesSdk import com.jacobibanez.plugin.android.godotplaygameservices.achievements.AchievementsProxy -import com.jacobibanez.plugin.android.godotplaygameservices.players.PlayersProxy import com.jacobibanez.plugin.android.godotplaygameservices.leaderboards.LeaderboardsProxy +import com.jacobibanez.plugin.android.godotplaygameservices.players.PlayersProxy import com.jacobibanez.plugin.android.godotplaygameservices.signals.getSignals import com.jacobibanez.plugin.android.godotplaygameservices.signin.SignInProxy import org.godotengine.godot.Godot @@ -31,6 +34,20 @@ class GodotAndroidPlugin(godot: Godot) : GodotPlugin(godot) { return getSignals() } + /** @suppress */ + override fun onMainCreate(activity: Activity?): View? { + Thread.setDefaultUncaughtExceptionHandler { _, exception -> + Log.e(pluginName, "Uncaught Exception! ${exception.message}") + } + return super.onMainCreate(activity) + } + + /** @suppress */ + override fun onMainActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onMainActivityResult(requestCode, resultCode, data) + playersProxy.onActivityResult(requestCode, resultCode, data) + } + /** * This method initializes the Play Games SDK. It should be called right after checking that * the plugin is loaded into Godot, for example: @@ -268,4 +285,12 @@ class GodotAndroidPlugin(godot: Godot) : GodotPlugin(godot) { otherPlayerInGameName, currentPlayerInGameName ) + + /** + * Displays a screen where the user can search for players. If the user selects a player, then + * the [com.jacobibanez.plugin.android.godotplaygameservices.signals.PlayerSignals.playerSearched] + * signal will be emitted, returning the selected player. + */ + @UsedByGodot + fun searchPlayer() = playersProxy.searchPlayer() } diff --git a/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/players/PlayerMapper.kt b/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/players/PlayerMapper.kt index 7e8b535..d1229f3 100644 --- a/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/players/PlayerMapper.kt +++ b/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/players/PlayerMapper.kt @@ -11,6 +11,7 @@ fun fromPlayer(player: Player): Dictionary = Dictionary().apply { put("bannerImagePortraitUri", player.bannerImagePortraitUri?.toString()) put("displayName", player.displayName) put("hiResImageUri", player.hiResImageUri?.toString()) + put("iconImageUri", player.iconImageUri?.toString()) put("playerId", player.playerId) put("retrievedTimestamp", player.retrievedTimestamp) put("title", player.title) diff --git a/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/players/PlayersProxy.kt b/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/players/PlayersProxy.kt index a235ab1..a1ea26c 100644 --- a/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/players/PlayersProxy.kt +++ b/plugin/src/main/java/com/jacobibanez/plugin/android/godotplaygameservices/players/PlayersProxy.kt @@ -1,13 +1,18 @@ package com.jacobibanez.plugin.android.godotplaygameservices.players +import android.app.Activity +import android.content.Intent import android.util.Log import androidx.core.app.ActivityCompat import com.google.android.gms.games.FriendsResolutionRequiredException import com.google.android.gms.games.PlayGames +import com.google.android.gms.games.Player import com.google.android.gms.games.PlayersClient +import com.google.android.gms.games.PlayersClient.EXTRA_PLAYER_SEARCH_RESULTS import com.google.gson.Gson import com.jacobibanez.plugin.android.godotplaygameservices.BuildConfig import com.jacobibanez.plugin.android.godotplaygameservices.signals.PlayerSignals.friendsLoaded +import com.jacobibanez.plugin.android.godotplaygameservices.signals.PlayerSignals.playerSearched import org.godotengine.godot.Dictionary import org.godotengine.godot.Godot import org.godotengine.godot.plugin.GodotPlugin.emitSignal @@ -23,6 +28,31 @@ class PlayersProxy( private val showSharingFriendsConsentRequestCode = 9006 private val compareProfileRequestCode = 9007 private val compareProfileWithAlternativeNameHintsRequestCode = 9008 + private val searchPlayerCode = 9009 + + /** @suppress */ + fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + if (requestCode == searchPlayerCode && resultCode == Activity.RESULT_OK) { + data?.let { intent -> + try { + val players = intent + .extras?.get(EXTRA_PLAYER_SEARCH_RESULTS) as ArrayList + Log.d(tag, "Players selected from search: $players") + emitSignal( + godot, + BuildConfig.GODOT_PLUGIN_NAME, + playerSearched, + Gson().toJson(fromPlayer(players.first())) + ) + } catch (exception: Exception) { + Log.e( + tag, + "Error while receiving player from search: ${exception.localizedMessage}" + ) + } + } + } + } fun loadFriends(pageSize: Int, forceReload: Boolean, askForPermission: Boolean) { Log.d(tag, "Loading friends with page size of $pageSize and forceReload = $forceReload") @@ -101,6 +131,18 @@ class PlayersProxy( } } + fun searchPlayer() { + Log.d(tag, "Opening search intent.") + playersClient.playerSearchIntent.addOnSuccessListener { intent -> + ActivityCompat.startActivityForResult( + godot.getActivity()!!, + intent, + searchPlayerCode, + null + ) + } + } + private fun askForFriendsListPermission(exception: FriendsResolutionRequiredException) { val pendingIntent = exception.resolution godot.getActivity()!!.startIntentSenderForResult( 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 d3904cb..cab9f9c 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 @@ -17,6 +17,7 @@ fun getSignals(): MutableSet = mutableSetOf( LeaderboardSignals.leaderboardLoaded, PlayerSignals.friendsLoaded, + PlayerSignals.playerSearched, ) /** @@ -77,7 +78,8 @@ object LeaderboardSignals { * * @return `true` if the score is submitted. `false` otherwise. Also returns the id of the leaderboard. */ - val scoreSubmitted = SignalInfo("scoreSubmitted", Boolean::class.javaObjectType, String::class.java) + val scoreSubmitted = + SignalInfo("scoreSubmitted", Boolean::class.javaObjectType, String::class.java) /** * This signal is emitted when calling the [com.jacobibanez.plugin.android.godotplaygameservices.GodotAndroidPlugin.loadPlayerScore] method. @@ -111,4 +113,12 @@ object PlayerSignals { * @return A JSON with a list of [com.google.android.gms.games.Player](https://developers.google.com/android/reference/com/google/android/gms/games/Player). */ val friendsLoaded = SignalInfo("friendsLoaded", String::class.java) + + /** + * This signal is emitted when selecting a player in the search window that is being displayed after + * calling the [com.jacobibanez.plugin.android.godotplaygameservices.GodotAndroidPlugin.searchPlayer] method. + * + * @return A JSON with a [com.google.android.gms.games.Player](https://developers.google.com/android/reference/com/google/android/gms/games/Player). + */ + val playerSearched = SignalInfo("playerSearched", String::class.java) }