Skip to content

Commit

Permalink
Add player info functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
cgisca committed Aug 28, 2020
1 parent de903d6 commit f3d2868
Show file tree
Hide file tree
Showing 15 changed files with 247 additions and 23 deletions.
9 changes: 9 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions .idea/jarRepositories.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 37 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ This is an Android Play Games Services plugin for Godot Game Engine 3.2.2+.

[![Android](https://img.shields.io/badge/Platform-Android-brightgreen.svg)](https://developer.android.com)
[![Godot](https://img.shields.io/badge/Godot%20Engine-3.2.2-blue.svg)](https://github.com/godotengine/godot/)
[![PGS](https://img.shields.io/badge/Play%20Games%20Services-19.0.0-green.svg)](https://developers.google.com/games/services/android/quickstart)
[![PGS](https://img.shields.io/badge/Play%20Games%20Services-20.0.1-green.svg)](https://developers.google.com/games/services/android/quickstart)
[![MIT license](https://img.shields.io/badge/License-MIT-yellowgreen.svg)](https://lbesson.mit-license.org/)


Expand All @@ -16,6 +16,7 @@ If you want to use the old plugin version visit [Old README file](https://github
- Leaderboards
- Events
- Player Stats
- Player Info
- Saved Games

## Getting started
Expand Down Expand Up @@ -241,6 +242,41 @@ func _on_player_stats_loaded(stats):
func _on_player_stats_loading_failed():
pass
```
#### Player Info
```gdscript
play_games_services.loadPlayerInfo()
# Callbacks:
func _on_player_info_loaded(info):
var info_dictionary: Dictionary = parse_json(info)
# Using below keys you can retrieve player’s info
info_dictionary["display_name"]
info_dictionary["name"]
info_dictionary["title"]
info_dictionary["player_id"]
info_dictionary["hi_res_image_url"]
info_dictionary["icon_image_url"]
info_dictionary["banner_image_landscape_url"]
info_dictionary["banner_image_portrait_url"]
# Also you can get level info for the player
var level_info_dictionary = info_dictionary["level_info"]
level_info_dictionary["current_xp_total"]
level_info_dictionary["last_level_up_timestamp"]
var current_level_dictionary = level_info_dictionary["current_level"]
current_level_dictionary["level_number"]
current_level_dictionary["max_xp"]
current_level_dictionary["min_xp"]
var next_level_dictionary = level_info_dictionary["next_level"]
next_level_dictionary["level_number"]
next_level_dictionary["max_xp"]
next_level_dictionary["min_xp"]
func _on_player_info_loading_failed():
pass
```
#### Saved Games
##### Save game snapshot
```gdscript
Expand Down
5 changes: 3 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ android {
dependencies {
compileOnly project(":godot-lib.3.2.2.stable.release")
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'com.google.android.gms:play-services-games:19.0.0'
implementation 'com.google.android.gms:play-services-games:20.0.1'
implementation 'com.google.android.gms:play-services-auth:18.1.0'
implementation 'com.google.code.gson:gson:2.8.6'

testImplementation 'junit:junit:4.12'
testImplementation 'junit:junit:4.13'
}

29 changes: 26 additions & 3 deletions app/src/main/java/io/cgisca/godot/gpgs/PlayGameServicesGodot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import com.google.android.gms.auth.api.signin.GoogleSignInOptions
import com.google.android.gms.drive.Drive
import com.google.android.gms.games.SnapshotsClient
import com.google.android.gms.games.snapshot.SnapshotMetadata
import io.cgisca.godot.gpgs.accountinfo.PlayerInfoController
import io.cgisca.godot.gpgs.accountinfo.PlayerInfoListener
import io.cgisca.godot.gpgs.achievements.AchievementsController
import io.cgisca.godot.gpgs.achievements.AchievementsListener
import io.cgisca.godot.gpgs.events.EventsController
Expand All @@ -28,14 +30,15 @@ import java.math.BigInteger
import java.util.Random

class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsListener, EventsListener,
LeaderBoardsListener, SavedGamesListener, SignInListener, PlayerStatsListener {
LeaderBoardsListener, SavedGamesListener, SignInListener, PlayerStatsListener, PlayerInfoListener {

private lateinit var connectionController: ConnectionController
private lateinit var signInController: SignInController
private lateinit var achievementsController: AchievementsController
private lateinit var leaderboardsController: LeaderboardsController
private lateinit var eventsController: EventsController
private lateinit var playerStatsController: PlayerStatsController
private lateinit var playerInfoController: PlayerInfoController
private lateinit var savedGamesController: SavedGamesController
private lateinit var googleSignInClient: GoogleSignInClient

Expand Down Expand Up @@ -71,6 +74,8 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList
val SIGNAL_SAVED_GAME_LOAD_SUCCESS = SignalInfo("_on_game_load_success", String::class.java)
val SIGNAL_SAVED_GAME_LOAD_FAIL = SignalInfo("_on_game_load_fail")
val SIGNAL_SAVED_GAME_CREATE_SNAPSHOT = SignalInfo("_on_create_new_snapshot", String::class.java)
val SIGNAL_PLAYER_INFO_LOADED = SignalInfo("_on_player_info_loaded", String::class.java)
val SIGNAL_PLAYER_INFO_LOADED_FAILED = SignalInfo("_on_player_info_loading_failed")
}

override fun getPluginName(): String {
Expand Down Expand Up @@ -98,7 +103,8 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList
"loadPlayerStats",
"showSavedGames",
"saveSnapshot",
"loadSnapshot"
"loadSnapshot",
"loadPlayerInfo"
)
}

Expand Down Expand Up @@ -129,7 +135,9 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList
SIGNAL_SAVED_GAME_FAILED,
SIGNAL_SAVED_GAME_LOAD_SUCCESS,
SIGNAL_SAVED_GAME_LOAD_FAIL,
SIGNAL_SAVED_GAME_CREATE_SNAPSHOT
SIGNAL_SAVED_GAME_CREATE_SNAPSHOT,
SIGNAL_PLAYER_INFO_LOADED,
SIGNAL_PLAYER_INFO_LOADED_FAILED
)
}

Expand Down Expand Up @@ -175,6 +183,7 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList
leaderboardsController = LeaderboardsController(godot as Activity, this, connectionController)
eventsController = EventsController(godot as Activity, this, connectionController)
playerStatsController = PlayerStatsController(godot as Activity, this, connectionController)
playerInfoController = PlayerInfoController(godot as Activity, this, connectionController)
savedGamesController = SavedGamesController(godot as Activity, this, connectionController)

googleSignInClient = GoogleSignIn.getClient(godot as Activity, signInOptions)
Expand Down Expand Up @@ -290,6 +299,12 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList
}
}

fun loadPlayerInfo() {
runOnUiThread {
playerInfoController.fetchPlayerInfo()
}
}

override fun onAchievementUnlocked(achievementName: String) {
emitSignal(SIGNAL_ACHIEVEMENT_UNLOCKED.name, achievementName)
}
Expand Down Expand Up @@ -393,4 +408,12 @@ class PlayGameServicesGodot(godot: Godot) : GodotPlugin(godot), AchievementsList
override fun onPlayerStatsLoadingFailed() {
emitSignal(SIGNAL_PLAYER_STATS_LOADED_FAILED.name)
}

override fun onPlayerInfoLoaded(response: String) {
emitSignal(SIGNAL_PLAYER_INFO_LOADED.name, response)
}

override fun onPlayerInfoLoadingFailed() {
emitSignal(SIGNAL_PLAYER_INFO_LOADED_FAILED.name)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.cgisca.godot.gpgs.accountinfo

import android.app.Activity
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.games.Games
import com.google.gson.Gson
import io.cgisca.godot.gpgs.ConnectionController
import io.cgisca.godot.gpgs.model.PlayerInfo
import io.cgisca.godot.gpgs.model.PlayerLevel
import io.cgisca.godot.gpgs.model.PlayerLevelInfo

class PlayerInfoController(
private val activity: Activity,
private val playerInfoListener: PlayerInfoListener,
private val connectionController: ConnectionController
) {

fun fetchPlayerInfo() {
val googleSignInAccount = GoogleSignIn.getLastSignedInAccount(activity)
if (connectionController.isConnected().first && googleSignInAccount != null) {
Games.getPlayersClient(activity, googleSignInAccount).currentPlayer
.addOnCompleteListener { task ->
val player = task.result
if (task.isSuccessful && player != null) {
val levelInfo = player.levelInfo
val playerLevelInfo = if (levelInfo != null) {
PlayerLevelInfo(
levelInfo.currentXpTotal,
levelInfo.lastLevelUpTimestamp,
if (levelInfo.currentLevel != null) PlayerLevel(
levelInfo.currentLevel.levelNumber,
levelInfo.currentLevel.minXp,
levelInfo.currentLevel.maxXp
) else null,
if (levelInfo.nextLevel != null) PlayerLevel(
levelInfo.nextLevel.levelNumber,
levelInfo.nextLevel.minXp,
levelInfo.nextLevel.maxXp
) else null
)
} else {
null
}

val playerInfo = PlayerInfo(
player.playerId,
player.displayName,
player.name,
player.iconImageUrl,
player.hiResImageUrl,
player.title,
player.bannerImageLandscapeUrl,
player.bannerImagePortraitUrl,
playerLevelInfo
)

playerInfoListener.onPlayerInfoLoaded(Gson().toJson(playerInfo))
} else {
playerInfoListener.onPlayerInfoLoadingFailed()
}
}
} else {
playerInfoListener.onPlayerInfoLoadingFailed()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.cgisca.godot.gpgs.accountinfo

interface PlayerInfoListener {
fun onPlayerInfoLoadingFailed()
fun onPlayerInfoLoaded(response: String)
}
28 changes: 28 additions & 0 deletions app/src/main/java/io/cgisca/godot/gpgs/model/PlayerInfo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.cgisca.godot.gpgs.model

import com.google.gson.annotations.SerializedName

data class PlayerInfo(
@SerializedName("player_id") val playerId: String,
@SerializedName("display_name") val displayName: String,
val name: String,
@SerializedName("icon_image_url") val iconImageUrl: String?,
@SerializedName("hi_res_image_url") val hiResImageUrl: String?,
val title: String?,
@SerializedName("banner_image_landscape_url") val bannerImageLandscapeUrl: String?,
@SerializedName("banner_image_portrait_url") val bannerImagePortraitUrl: String?,
@SerializedName("level_info") val levelInfo: PlayerLevelInfo?
)

data class PlayerLevelInfo(
@SerializedName("current_xp_total") val currentXpTotal: Long,
@SerializedName("last_level_up_timestamp") val lastLevelUpTimestamp: Long,
@SerializedName("current_level") val currentLevel: PlayerLevel?,
@SerializedName("next_level") val nextLevel: PlayerLevel?
)

data class PlayerLevel(
@SerializedName("level_number") val levelNumber: Int,
@SerializedName("min_xp") val minXp: Long,
@SerializedName("max_xp") val maxXp: Long
)
12 changes: 12 additions & 0 deletions app/src/main/java/io/cgisca/godot/gpgs/model/PlayerStats.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package io.cgisca.godot.gpgs.model

import com.google.gson.annotations.SerializedName

data class PlayerStats(
@SerializedName("avg_session_length") val avgSessionLength: Double,
@SerializedName("days_last_played") val daysSinceLastPlayed: Int,
@SerializedName("purchases") val numberOfPurchases: Int,
@SerializedName("sessions") val numberOfSessions: Int,
@SerializedName("session_percentile") val sessionPercentile: Double,
@SerializedName("spend_percentile") val spendPercentile: Double
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package io.cgisca.godot.gpgs.stats
import android.app.Activity
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.games.Games
import com.google.gson.Gson
import io.cgisca.godot.gpgs.ConnectionController
import org.json.JSONException
import org.json.JSONObject
import io.cgisca.godot.gpgs.model.PlayerStats

class PlayerStatsController(
private val activity: Activity,
Expand All @@ -22,18 +22,16 @@ class PlayerStatsController(
val result = task.result
if (task.isSuccessful && result != null && result.get() != null) {
val stats = result.get()
val json = JSONObject()
try {
json.put("avg_session_length", stats!!.averageSessionLength.toDouble())
json.put("days_last_played", stats.daysSinceLastPlayed)
json.put("purchases", stats.numberOfPurchases)
json.put("sessions", stats.numberOfSessions)
json.put("session_percentile", stats.sessionPercentile.toDouble())
json.put("spend_percentile", stats.spendPercentile.toDouble())
} catch (e: JSONException) {
e.printStackTrace()
}
playerStatsListener.onPlayerStatsLoaded(json.toString())
val playerStats = PlayerStats(
stats!!.averageSessionLength.toDouble(),
stats.daysSinceLastPlayed,
stats.numberOfPurchases,
stats.numberOfSessions,
stats.sessionPercentile.toDouble(),
stats.spendPercentile.toDouble()
)

playerStatsListener.onPlayerStatsLoaded(Gson().toJson(playerStats))
} else {
playerStatsListener.onPlayerStatsLoadingFailed()
}
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.3.72"
ext.kotlin_version = "1.4.0"
repositories {
google()
jcenter()
Expand Down
Loading

0 comments on commit f3d2868

Please sign in to comment.