Skip to content

Commit

Permalink
Merge branch 'develop' into feature/add_logs_to_save_game
Browse files Browse the repository at this point in the history
  • Loading branch information
Abedalkareem authored Aug 8, 2024
2 parents d4f1cc3 + 0e8d4bb commit ea98b2e
Show file tree
Hide file tree
Showing 21 changed files with 274 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,19 @@ class GamesServicesPlugin : FlutterPlugin,
Method.SubmitScore -> {
val leaderboardID = call.argument<String>("leaderboardID") ?: ""
val score = call.argument<Int>("value") ?: 0
leaderboards?.submitScore(leaderboardID, score, result)
val token = call.argument<String>("token") ?: ""
leaderboards?.submitScore(leaderboardID, score, token, result)
}
Method.GetPlayerScore -> {
val leaderboardID = call.argument<String>("leaderboardID") ?: ""
leaderboards?.getPlayerScore(leaderboardID, result)
}
Method.GetPlayerScoreObject -> {
val leaderboardID = call.argument<String>("leaderboardID") ?: ""
val span = call.argument<Int>("span") ?: 0
val leaderboardCollection = call.argument<Int>("leaderboardCollection") ?: 0
leaderboards?.getPlayerScoreObject(activity, leaderboardID, span, leaderboardCollection, result)
}
Method.GetPlayerID -> {
player?.getPlayerID(activity, result)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ class Leaderboards(private var activityPluginBinding: ActivityPluginBinding) :
item.scoreHolderDisplayName,
item.scoreHolder?.playerId,
scoreHolderIconImage
)
),
item.scoreTag
)
)
}
Expand Down Expand Up @@ -178,10 +179,8 @@ class Leaderboards(private var activityPluginBinding: ActivityPluginBinding) :
}
}

fun submitScore(leaderboardID: String, score: Int, result: MethodChannel.Result) {
leaderboardsClient
.submitScoreImmediate(leaderboardID, score.toLong())
.addOnSuccessListener {
fun submitScore(leaderboardID: String, score: Int, token: String, result: MethodChannel.Result) {
leaderboardsClient.submitScoreImmediate(leaderboardID, score.toLong(), token).addOnSuccessListener {
result.success(null)
}
.addOnFailureListener {
Expand Down Expand Up @@ -212,4 +211,63 @@ class Leaderboards(private var activityPluginBinding: ActivityPluginBinding) :
result.error(PluginError.FailedToGetScore.errorCode(), it.localizedMessage, null)
}
}

fun getPlayerScoreObject(
activity: Activity?,
leaderboardID: String,
span: Int,
leaderboardCollection: Int,
result: MethodChannel.Result
) {
activity ?: return
leaderboardsClient?.loadCurrentPlayerLeaderboardScore(leaderboardID, span, leaderboardCollection)
?.addOnSuccessListener { snapshotResult ->
val data = snapshotResult.get()
if (data == null) {
result.error(
PluginError.FailedToGetScore.errorCode(),
PluginError.FailedToGetScore.errorMessage(),
null
)
return@addOnSuccessListener
}
val handler = CoroutineExceptionHandler { _, exception ->
result.error(
PluginError.FailedToGetScore.errorCode(),
exception.localizedMessage,
null
)
}

CoroutineScope(Dispatchers.Main + handler).launch {
val scoreHolderIconImage =
data.scoreHolderIconImageUri.let { imageLoader.loadImageFromUri(activity, it) }

val score = LeaderboardScoreData(
data.rank,
data.displayScore,
data.rawScore,
data.timestampMillis,
PlayerData(
data.scoreHolderDisplayName,
data.scoreHolder?.playerId,
scoreHolderIconImage
),
data.scoreTag
)

val gson = Gson()
val string = gson.toJson(score) ?: ""

result.success(string)
}
}
?.addOnFailureListener {
result.error(
PluginError.FailedToGetScore.errorCode(),
it.localizedMessage,
null
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ data class LeaderboardScoreData(
val displayScore: String,
val rawScore: Long,
val timestampMillis: Long,
val scoreHolder: PlayerData
val scoreHolder: PlayerData,
val token: String?
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.abedalkareem.games_services.models
enum class Method {
Unlock, Increment, SubmitScore, ShowLeaderboards, ShowAchievements,
LoadAchievements, SignIn, IsSignedIn, GetPlayerID, GetPlayerName,
GetPlayerHiResImage, GetPlayerIconImage, GetPlayerScore, SaveGame,
GetPlayerHiResImage, GetPlayerIconImage, GetPlayerScore, GetPlayerScoreObject, SaveGame,
LoadGame, GetSavedGames, DeleteGame, LoadLeaderboardScores, GetAuthCode
}

Expand Down
18 changes: 15 additions & 3 deletions games_services/darwin/Classes/Achievements.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ class Achievements: BaseGamesServices {
result(nil)
}

func report(achievementID: String, percentComplete: Double, result: @escaping FlutterResult) {
func report(achievementID: String, percentComplete: Double, showsCompletionBanner: Bool, result: @escaping FlutterResult) {
let achievement = GKAchievement(identifier: achievementID)
achievement.percentComplete = percentComplete
achievement.showsCompletionBanner = true
achievement.showsCompletionBanner = showsCompletionBanner
GKAchievement.report([achievement]) { (error) in
guard error == nil else {
result(error?.flutterError(code: .failedToSendAchievement))
Expand Down Expand Up @@ -80,6 +80,18 @@ class Achievements: BaseGamesServices {
result(PluginError.notSupportedForThisOSVersion.flutterError())
}
}


func resetAchievements(result: @escaping FlutterResult) {
if #available(iOS 13.0, *) {
Task {
do {
try await GKAchievement.resetAchievements()
result(nil)
} catch {
result(error.flutterError(code: .failedToResetAchievements))
}
}
}
}
}

61 changes: 58 additions & 3 deletions games_services/darwin/Classes/Leaderboards.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ class Leaderboards: BaseGamesServices {
result(nil)
}

func report(score: Int, leaderboardID: String, result: @escaping FlutterResult) {
func report(score: Int, leaderboardID: String, token: String, result: @escaping FlutterResult) {
let reportedScore = GKScore(leaderboardIdentifier: leaderboardID)
reportedScore.value = Int64(score)
reportedScore.context = UInt64(token) ?? 0
GKScore.report([reportedScore]) { (error) in
guard error == nil else {
result(error?.flutterError(code: .failedToSendScore))
Expand All @@ -44,6 +45,57 @@ class Leaderboards: BaseGamesServices {
result(PluginError.notSupportedForThisOSVersion.flutterError())
}
}

func getPlayerScoreObject(leaderboardID: String, span: Int, leaderboardCollection: Int, result: @escaping FlutterResult) {
if #available(iOS 14.0, *) {
Task {
do {
let leaderboards = try await GKLeaderboard.loadLeaderboards(IDs: [leaderboardID])
guard let leaderboard = leaderboards.first else {
result(PluginError.failedToGetScore.flutterError())
return
}
let response = try await leaderboard.loadEntries(for: [currentPlayer],
timeScope: GKLeaderboard.TimeScope(rawValue: span) ?? .allTime)

let (localPlayerEntry, _) = response

if let localPlayerEntry {
#if os(macOS)
let imageData = try? await localPlayerEntry.player.loadPhoto(for: .normal).tiffRepresentation
#else
let imageData = try? await localPlayerEntry.player.loadPhoto(for: .normal).pngData()
#endif
let scoreHolderIconImage = imageData?.base64EncodedString()
let score = LeaderboardScoreData(rank: localPlayerEntry.rank,
displayScore: localPlayerEntry.formattedScore,
rawScore: localPlayerEntry.score,
timestampMillis: Int(localPlayerEntry.date.timeIntervalSince1970),
scoreHolder: PlayerData(
displayName: localPlayerEntry.player.displayName,
playerID: localPlayerEntry.player.gamePlayerID,
teamPlayerID: localPlayerEntry.player.teamPlayerID,
iconImage: scoreHolderIconImage
),
token: String(localPlayerEntry.context))

if let data = try? JSONEncoder().encode(score) {
let string = String(data: data, encoding: String.Encoding.utf8)
result(string)
} else {
result(PluginError.failedToGetScore.flutterError())
}
} else {
result(PluginError.failedToGetScore.flutterError())
}
} catch {
result(error.flutterError(code: .failedToGetScore))
}
}
} else {
result(PluginError.notSupportedForThisOSVersion.flutterError())
}
}

func loadLeaderboardScores(leaderboardID: String, span: Int, leaderboardCollection: Int, maxResults: Int, result: @escaping FlutterResult) {
if #available(iOS 14.0, *) {
Expand All @@ -70,9 +122,12 @@ class Leaderboards: BaseGamesServices {
rawScore: item.score,
timestampMillis: Int(item.date.timeIntervalSince1970),
scoreHolder: PlayerData(
displayName: item.player.displayName, playerID: item.player.gamePlayerID, teamPlayerID: item.player.teamPlayerID,
displayName: item.player.displayName,
playerID: item.player.gamePlayerID,
teamPlayerID: item.player.teamPlayerID,
iconImage: scoreHolderIconImage
)))
),
token: String(item.context)))
}
if let data = try? JSONEncoder().encode(items) {
let string = String(data: data, encoding: String.Encoding.utf8)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ struct LeaderboardScoreData: Codable {
var rawScore: Int
var timestampMillis: Int
var scoreHolder: PlayerData
var token: String?
}
2 changes: 2 additions & 0 deletions games_services/darwin/Classes/Models/Method.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ enum Method: String {
case getPlayerHiResImage = "getPlayerHiResImage"
case getPlayerIconImage = "getPlayerIconImage"
case getPlayerScore = "getPlayerScore"
case getPlayerScoreObject = "getPlayerScoreObject"
case playerIsUnderage = "playerIsUnderage"
case playerIsMultiplayerGamingRestricted = "playerIsMultiplayerGamingRestricted"
case playerIsPersonalizedCommunicationRestricted = "playerIsPersonalizedCommunicationRestricted"
Expand All @@ -22,5 +23,6 @@ enum Method: String {
case getSavedGames = "getSavedGames"
case deleteGame = "deleteGame"
case loadAchievements = "loadAchievements"
case resetAchievements = "resetAchievements"
case loadLeaderboardScores = "loadLeaderboardScores"
}
16 changes: 14 additions & 2 deletions games_services/darwin/Classes/SwiftGamesServicesPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,27 @@ public class SwiftGamesServicesPlugin: NSObject, FlutterPlugin {
achievements.loadAchievements(result: result)
case .showAchievements:
achievements.showAchievements(result: result)
case .resetAchievements:
achievements.resetAchievements(result: result)
case .unlock:
let achievementID = (arguments?["achievementID"] as? String) ?? ""
let percentComplete = (arguments?["percentComplete"] as? Double) ?? 0.0
achievements.report(achievementID: achievementID, percentComplete: percentComplete, result: result)
let showsCompletionBanner = (arguments?["showsCompletionBanner"] as? Bool) ?? true
achievements.report(achievementID: achievementID, percentComplete: percentComplete, showsCompletionBanner: showsCompletionBanner, result: result)
case .showLeaderboards:
let leaderboardID = (arguments?["leaderboardID"] as? String) ?? ""
leaderboards.showLeaderboardWith(identifier: leaderboardID, result: result)
case .getPlayerScore:
let leaderboardID = (arguments?["leaderboardID"] as? String) ?? ""
leaderboards.getPlayerScore(leaderboardID: leaderboardID, result: result)
case .getPlayerScoreObject:
let leaderboardID = (arguments?["leaderboardID"] as? String) ?? ""
let span = (arguments?["span"] as? Int) ?? 0
let leaderboardCollection = (arguments?["leaderboardCollection"] as? Int) ?? 0
leaderboards.getPlayerScoreObject(leaderboardID: leaderboardID,
span: span,
leaderboardCollection: leaderboardCollection,
result: result)
case .loadLeaderboardScores:
let leaderboardID = (arguments?["leaderboardID"] as? String) ?? ""
let span = (arguments?["span"] as? Int) ?? 0
Expand All @@ -56,7 +67,8 @@ public class SwiftGamesServicesPlugin: NSObject, FlutterPlugin {
case .submitScore:
let leaderboardID = (arguments?["leaderboardID"] as? String) ?? ""
let score = (arguments?["value"] as? Int) ?? 0
leaderboards.report(score: score, leaderboardID: leaderboardID, result: result)
let token = (arguments?["token"] as? String) ?? ""
leaderboards.report(score: score, leaderboardID: leaderboardID, token: token, result: result)
case .hideAccessPoint:
player.hideAccessPoint(result: result)
case .showAccessPoint:
Expand Down
3 changes: 3 additions & 0 deletions games_services/darwin/Classes/Util/Error.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ enum PluginError: String {
return "Failed to delete saved game"
case .failedToLoadAchievements:
return "Failed to get the achievements list"
case .failedToResetAchievements:
return "Failed to reset achievements"
case .failedToLoadLeaderboardScores:
return "Failed to load leaderboard scores"
}
Expand All @@ -58,6 +60,7 @@ enum PluginError: String {
case failedToGetSavedGames = "failed_to_get_saved_games"
case failedToDeleteSavedGame = "failed_to_delete_saved_game"
case failedToLoadAchievements = "failed_to_load_achievements"
case failedToResetAchievements = "failed_to_reset_achievements"
case failedToLoadLeaderboardScores = "failed_to_load_leaderboard_scores"

func flutterError() -> FlutterError {
Expand Down
22 changes: 22 additions & 0 deletions games_services/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ class AppState extends State<App> {
onPressed: _loadAchievement,
child: const Text('Load Achievement'),
),
ElevatedButton(
onPressed: _resetAchievement,
child: const Text('Reset Achievement'),
),
ElevatedButton(
onPressed: _loadLeaderboardScores,
child: const Text('Load Leaderboard Scores'),
Expand All @@ -98,6 +102,10 @@ class AppState extends State<App> {
onPressed: _getPlayerScore,
child: const Text('Get player score'),
),
ElevatedButton(
onPressed: _getPlayerScoreObject,
child: const Text('Load Player Centered Scores'),
),
ElevatedButton(
onPressed: _getPlayerName,
child: const Text('Get player name'),
Expand Down Expand Up @@ -153,6 +161,15 @@ class AppState extends State<App> {
print(result);
}

void _getPlayerScoreObject() async {
final result = await Leaderboards.getPlayerScoreObject(
iOSLeaderboardID: "ios_leaderboard_id",
androidLeaderboardID: "android_leaderboard_id",
scope: PlayerScope.global,
timeScope: TimeScope.allTime);
print(result);
}

void _showAccessPoint() async {
final result = await Player.showAccessPoint(AccessPointLocation.topLeading);
print(result);
Expand All @@ -163,6 +180,11 @@ class AppState extends State<App> {
print(result);
}

void _resetAchievement() async {
final result = await Achievements.resetAchievements();
print(result);
}

void _incrementAchievement() async {
final result = await Achievements.increment(
achievement: Achievement(androidID: 'android_id', steps: 50));
Expand Down
16 changes: 8 additions & 8 deletions games_services/lib/games_services.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
export 'src/game_auth.dart';
export 'package:games_services_platform_interface/models.dart';

export 'src/achievements.dart';
export 'src/game_auth.dart';
export 'src/games_services.dart';
export 'src/leaderboards.dart';
export 'src/player.dart';
export 'src/save_game.dart';
export 'src/models/achievement_item_data.dart';
export 'src/models/saved_game.dart';
export 'src/models/leaderboard_score_data.dart';

export 'src/games_services.dart';

export 'package:games_services_platform_interface/models.dart';
export 'src/models/player_data.dart';
export 'src/models/saved_game.dart';
export 'src/player.dart';
export 'src/save_game.dart';
Loading

0 comments on commit ea98b2e

Please sign in to comment.