From cfefacc40ada950a61b8c98f01db205df22db3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20H=C3=A1dl?= Date: Fri, 7 Jun 2013 18:49:32 +0200 Subject: [PATCH 01/13] Rename README to README.md --- README => README.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename README => README.md (100%) diff --git a/README b/README.md similarity index 100% rename from README rename to README.md From 2b0e4e3564aaf0afd7348d45227c5e8d2c69b403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20H=C3=A1dl?= Date: Fri, 7 Jun 2013 19:04:56 +0200 Subject: [PATCH 02/13] Update README.md --- README.md | 91 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 1d7720f..803bb08 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,13 @@ +DDGameKitHelper +=============== + A simpler GameKitHelper inspired by Steffen Itterheim's version (http://www.learn-cocos2d.com). This version takes a different approach by synchronizing a local cache with game center and visa versa. +Story +--------------- + I was having a lot of troubles getting Steffen's library to work nicely on iOS 4.2 devices. For one it was trying to write to the root bundle directory. I've switch it to write to /Library. @@ -21,12 +27,13 @@ reports the score each time (so that daily and weekly comparisons work), it's only cached locally if the high score has been beat. It also displays a message banner. +Also, I've implemented a cache per game center user. + DDGameKitHelper only deals with achievements and scores. Since none of -my games use multiplayer I didn't try to tackle an api for that. I also -have not tackled someone else signing in to game center. Right now I -think everything locally would synch with the new account, which really -isn't what you want neccessarily. So I will be working on a cache per -user. (UPDATE: I've implemented this) +my games use multiplayer I didn't try to tackle an api for that. + +Dependencies +--------------- The DDGameKitHelperDelegate class is dependent on Benjamin Borowski's GKAchievementNotification class. @@ -37,55 +44,73 @@ It does an excellent job of display a slide down notification that fits in seamlessly with game center. The only thing I needed to add to it was an adjustFrame method to compensate for the iPad. -USING IT +If you don't want to use it, then change macro `DDGAMEKIT_USE_NOTIFICATION` to `0`. -Authenticating a player ------------------------ +Installation +------------ -[[DDGameKitHelper sharedGameKitHelper] authenticateLocalPlayer]; +1. Add the `GameKit` and `libcommonCrypto.dylib` frameworks to your Xcode project -Checking authentication ------------------------ +2. Add the following files to your Xcode project (make sure to select Copy Items in the dialog): + - GameCenterManager.h + - GameCenterManager.m + - Reachability.h + - Reachability.m + - NSDataAES256.h + - NSDataAES256.m -[[DDGameKitHelper sharedGameKitHelper] isLocalPlayerAuthenticated]; +3. Open the `GameCenterManager.h` file and change the `kGameCenterManagerKey` constant to the secret key you want to use for encryption/decryption -Unlocking an achievement ------------------------- +4. Import the `GameCenterManager.h` file -[[DDGameKitHelper sharedGameKitHelper] reportAchievement:@"1" -percentComplete:100]; +Usage +----------------------- -Reporting a score ------------------ +###Authenticating a player +
+[[DDGameKitHelper sharedGameKitHelper] authenticateLocalPlayer];
+
+###Checking authentication +
+[[DDGameKitHelper sharedGameKitHelper] isLocalPlayerAuthenticated];
+
+###Unlocking an achievement +
+[[DDGameKitHelper sharedGameKitHelper] reportAchievement:@"1"
+percentComplete:100];
+
+###Reporting a score +
 [[DDGameKitHelper sharedGameKitHelper] submitScore:newscore
 category:@"1"];
-
-Showing achievements 
---------------------
-
+
+###Showing achievements +
 [[DDGameKitHelper sharedGameKitHelper] showAchievements];
-
-Showing scores 
---------------
-
+
+###Showing scores +
 [[DDGameKitHelper sharedGameKitHelper] showLeaderboard];
-
+
+
 [[DDGameKitHelper sharedGameKitHelper] showLeaderboardwithCategory:@"LeaderboardID" timeScope:GKLeaderboardTimeScopeAllTime];
 where GKLeaderboardTimeScopeAllTime is also available in GKLeaderboardTimeScopeToday and GKLeaderboardTimeScopeWeek
-
-Resetting achievements 
-----------------------
-
+
+###Resetting achievements +
 [[DDGameKitHelper sharedGameKitHelper] resetAchievements];
+
- -SUMMARY +Summary +---------- I know all of this functionality is available in iOS 5.x, but I want to still support my 4.x users. This library plays nicely with iOS 4.x and 5.x. +----------- + Doug Davies Owner, Funky Visions www.funkyvisions.com From 90849bde21c38c3e333be6216b5d4e24c2dfcfc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20H=C3=A1dl?= Date: Fri, 7 Jun 2013 20:23:29 +0300 Subject: [PATCH 03/13] Update README.md --- README.md | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 803bb08..bba27e8 100644 --- a/README.md +++ b/README.md @@ -44,24 +44,20 @@ It does an excellent job of display a slide down notification that fits in seamlessly with game center. The only thing I needed to add to it was an adjustFrame method to compensate for the iPad. -If you don't want to use it, then change macro `DDGAMEKIT_USE_NOTIFICATION` to `0`. +If you don't want to use it, then change pre-processor macro `DDGAMEKIT_USE_NOTIFICATION` to `0` in `DDGameKitHelperDelegate.m` file. Installation ------------ -1. Add the `GameKit` and `libcommonCrypto.dylib` frameworks to your Xcode project +1. Add the `GameKit` framework to your Xcode project 2. Add the following files to your Xcode project (make sure to select Copy Items in the dialog): - - GameCenterManager.h - - GameCenterManager.m - - Reachability.h - - Reachability.m - - NSDataAES256.h - - NSDataAES256.m + - DDGameKitHelper.h + - DDGameKitHelper.m + - DDGameKitHelperDelegate.h + - DDGameKitHelperDelegate.m -3. Open the `GameCenterManager.h` file and change the `kGameCenterManagerKey` constant to the secret key you want to use for encryption/decryption - -4. Import the `GameCenterManager.h` file +3. Import the `DDGameKitHelper.h` file Usage ----------------------- From 22a882822755a50419a992083ba1f3a686575f64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20H=C3=A1dl?= Date: Fri, 7 Jun 2013 20:49:19 +0300 Subject: [PATCH 04/13] Update README.md --- README.md | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index bba27e8..505a06a 100644 --- a/README.md +++ b/README.md @@ -61,34 +61,43 @@ Installation Usage ----------------------- - -###Authenticating a player - +###Initializing +You should call this prefferably in the `application:didFinishLaunchingWithOptions:` method, when starting your app. +
+[DDGameKitHelper sharedGameKitHelper];
+
+###Authentication +Handles authentication of the game center user and creates a cache per each new/different user. +Shows the default game center authentication dialog.
 [[DDGameKitHelper sharedGameKitHelper] authenticateLocalPlayer];
 
-###Checking authentication +Returns a `BOOL` depending on player authentication.
 [[DDGameKitHelper sharedGameKitHelper] isLocalPlayerAuthenticated];
 
-###Unlocking an achievement +###Achievements +Handles reporting and showing of achievements.
 [[DDGameKitHelper sharedGameKitHelper] reportAchievement:@"1"
 percentComplete:100];
 
-###Reporting a score +Shows the default game center view with the achievements section opened.
-[[DDGameKitHelper sharedGameKitHelper] submitScore:newscore
-category:@"1"];
+[[DDGameKitHelper sharedGameKitHelper] showAchievements];
 
-###Showing achievements +###Leaderboard +Handles reporting and showing leaderboard score.
-[[DDGameKitHelper sharedGameKitHelper] showAchievements];
+[[DDGameKitHelper sharedGameKitHelper] submitScore:newscore
+category:@"1"];
 
-###Showing scores +Shows the default game center view with the leaderboards section opened.
 [[DDGameKitHelper sharedGameKitHelper] showLeaderboard];
 
+Shows the default game center view with the leaderboards section opened and specific time scope selected. +Besides `GKLeaderboardTimeScopeAllTime` you can also use `GKLeaderboardTimeScopeToday` and `GKLeaderboardTimeScopeWeek`.
 [[DDGameKitHelper sharedGameKitHelper] showLeaderboardwithCategory:@"LeaderboardID" timeScope:GKLeaderboardTimeScopeAllTime];
 where GKLeaderboardTimeScopeAllTime is also available in GKLeaderboardTimeScopeToday and GKLeaderboardTimeScopeWeek
@@ -102,11 +111,10 @@ Summary
 ----------
 
 I know all of this functionality is available in iOS 5.x, but I want to
-still support my 4.x users.  This library plays nicely with iOS 4.x and
+still support my 4.x users.
+  This library plays nicely with iOS 4.x and
 5.x.
 
------------
-
 Doug Davies 
 Owner, Funky Visions 
 www.funkyvisions.com

From 5c5840e3ce90086b5248ab0e1f7229d59bfff456 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dominik=20H=C3=A1dl?= 
Date: Fri, 7 Jun 2013 19:55:15 +0200
Subject: [PATCH 05/13] Update README.md

---
 README.md | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/README.md b/README.md
index 505a06a..c36ebef 100644
--- a/README.md
+++ b/README.md
@@ -46,6 +46,11 @@ adjustFrame method to compensate for the iPad.
 
 If you don't want to use it, then change pre-processor macro `DDGAMEKIT_USE_NOTIFICATION` to `0` in `DDGameKitHelperDelegate.m` file.
 
+ARC Support
+---------------
+
+This class doesn't support ARC, however still works well with `-fno-objc-arc` compiler flag in ARC projects.
+
 Installation
 ------------
 
@@ -68,6 +73,7 @@ You should call this prefferably in the `application:didFinishLaunchingWithOptio
 
###Authentication Handles authentication of the game center user and creates a cache per each new/different user. + Shows the default game center authentication dialog.
 [[DDGameKitHelper sharedGameKitHelper] authenticateLocalPlayer];

From c8f6e546a042048235f32c0b75429ce01cd537a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dominik=20H=C3=A1dl?= 
Date: Sat, 8 Jun 2013 11:25:37 +0300
Subject: [PATCH 06/13] Update README.md

---
 README.md | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md
index c36ebef..17b5d4b 100644
--- a/README.md
+++ b/README.md
@@ -44,7 +44,8 @@ It does an excellent job of display a slide down notification that fits in
 seamlessly with game center. The only thing I needed to add to it was an
 adjustFrame method to compensate for the iPad.
 
-If you don't want to use it, then change pre-processor macro `DDGAMEKIT_USE_NOTIFICATION` to `0` in `DDGameKitHelperDelegate.m` file.
+If you don't want to use it, then change pre-processor macro `DDGAMEKIT_USE_NOTIFICATION` to `0`  
+in `DDGameKitHelperDelegate.m` file.
 
 ARC Support
 ---------------
@@ -102,11 +103,10 @@ Shows the default game center view with the leaderboards section opened.
 
 [[DDGameKitHelper sharedGameKitHelper] showLeaderboard];
 
-Shows the default game center view with the leaderboards section opened and specific time scope selected. +Shows the default game center view with the leaderboards section opened and specific time scope selected. Besides `GKLeaderboardTimeScopeAllTime` you can also use `GKLeaderboardTimeScopeToday` and `GKLeaderboardTimeScopeWeek`.
 [[DDGameKitHelper sharedGameKitHelper] showLeaderboardwithCategory:@"LeaderboardID" timeScope:GKLeaderboardTimeScopeAllTime];
-where GKLeaderboardTimeScopeAllTime is also available in GKLeaderboardTimeScopeToday and GKLeaderboardTimeScopeWeek
 
###Resetting achievements
@@ -117,10 +117,10 @@ Summary
 ----------
 
 I know all of this functionality is available in iOS 5.x, but I want to
-still support my 4.x users.
-  This library plays nicely with iOS 4.x and
+still support my 4.x users.  
+This library plays nicely with iOS 4.x and
 5.x.
 
-Doug Davies 
-Owner, Funky Visions 
+Doug Davies  
+Owner, Funky Visions  
 www.funkyvisions.com

From bebfb72742a0c48fa2ad1c6b3417d8e934c5c855 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Dominik=20H=C3=A1dl?= 
Date: Sat, 8 Jun 2013 12:27:17 +0300
Subject: [PATCH 07/13] Update README.md

---
 README.md | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/README.md b/README.md
index 17b5d4b..edc9f87 100644
--- a/README.md
+++ b/README.md
@@ -113,6 +113,11 @@ Besides `GKLeaderboardTimeScopeAllTime` you can also use `GKLeaderboardTimeScope
 [[DDGameKitHelper sharedGameKitHelper] resetAchievements];
 
+Logging +---------- +You can change if DDGameKitHelper should log messages to the output. +Setting `DDGAMEKIT_LOGGING` (in `DDGameKitHelper.h`) pre-processor macro to `0` or `1` will disable or enable logging. + Summary ---------- From 70bbeef42f5bbf35fca9a16a0a1b4fa2b876bbd1 Mon Sep 17 00:00:00 2001 From: Dominik Hadl Date: Sat, 8 Jun 2013 11:30:36 +0200 Subject: [PATCH 08/13] Improve readability, convert to ARC and fix typos --- DDGameKitHelper.h | 75 ++-- DDGameKitHelper.m | 776 +++++++++++++++++++++----------------- DDGameKitHelperDelegate.m | 35 +- 3 files changed, 499 insertions(+), 387 deletions(-) diff --git a/DDGameKitHelper.h b/DDGameKitHelper.h index abec820..0bd8ff1 100755 --- a/DDGameKitHelper.h +++ b/DDGameKitHelper.h @@ -6,57 +6,70 @@ #import +// ----------------------------------------------------------------- +#define DDGAMEKIT_LOGGING 0 +// ----------------------------------------------------------------- + @protocol DDGameKitHelperProtocol --(bool) compare:(int64_t)score1 to:(int64_t)score2; --(void) onSubmitScore:(int64_t)score; --(void) onReportAchievement:(GKAchievement*)achievement; +- (BOOL) compareScore:(int64_t)score1 toScore:(int64_t)score2; +- (void) onSubmitScore:(int64_t)score; +- (void) onReportAchievement:(GKAchievement*)achievement; @end +// ----------------------------------------------------------------- + @interface DDGameKitHelper : NSObject { - id delegate; - bool isGameCenterAvailable; - NSMutableDictionary* achievements; - NSMutableDictionary* scores; - NSMutableDictionary* achievementDescriptions; - NSString* currentPlayerID; + id _delegate; + BOOL _isGameCenterAvailable; + NSMutableDictionary* _achievements; + NSMutableDictionary* _scores; + NSMutableDictionary* _achievementDescriptions; + NSString* _currentPlayerID; } -@property (nonatomic, retain) id delegate; -@property (nonatomic, readonly) bool isGameCenterAvailable; +// ----------------------------------------------------------------- + +@property (nonatomic, strong) id delegate; +@property (nonatomic, readonly) BOOL isGameCenterAvailable; @property (nonatomic, readonly) NSMutableDictionary* achievements; @property (nonatomic, readonly) NSMutableDictionary* scores; @property (nonatomic, readonly) NSMutableDictionary* achievementDescriptions; -@property (nonatomic, retain) NSString* currentPlayerID; - -+(DDGameKitHelper*) sharedGameKitHelper; - --(void) setNotAvailable; +@property (nonatomic, strong) NSString* currentPlayerID; --(bool) isAvailable; +// ----------------------------------------------------------------- --(void) authenticateLocalPlayer; +// Singleton instance ++ (DDGameKitHelper*) sharedGameKitHelper; --(bool) isLocalPlayerAuthenticated; +// ----------------------------------------------------------------- --(void) submitScore:(int64_t)value category:(NSString*)category; +// Check and set availability +- (void) setNotAvailable; +- (BOOL) isAvailable; --(void) reportAchievement:(NSString*)identifier percentComplete:(float)percent; +// Authenticate and check authentication +- (void) authenticateLocalPlayer; +- (BOOL) isLocalPlayerAuthenticated; --(void) resetAchievements; +// Submitting score and achievements +- (void) submitScore:(int64_t)value category:(NSString*)category; +- (void) reportAchievement:(NSString*)identifier percentComplete:(float)percent; --(void) showGameCenter; +// Resetting achievements +- (void) resetAchievements; --(void) showLeaderboard; - --(void) showLeaderboardwithCategory:(NSString*)category timeScope:(int)tscope; - --(void) showAchievements; - --(GKAchievementDescription*) getAchievementDescription:(NSString*)identifier; +// Showing GameCenter +- (void) showGameCenter; +- (void) showLeaderboard; +- (void) showLeaderboardWithCategory:(NSString*)category timeScope:(int)tscope; +- (void) showAchievements; +// Achievement info - (int) numberOfTotalAchievements; - - (int) numberOfCompletedAchievements; +- (GKAchievementDescription*) getAchievementDescription:(NSString*)identifier; +// ----------------------------------------------------------------- @end +// ----------------------------------------------------------------- \ No newline at end of file diff --git a/DDGameKitHelper.m b/DDGameKitHelper.m index 70f963b..9409846 100755 --- a/DDGameKitHelper.m +++ b/DDGameKitHelper.m @@ -8,80 +8,63 @@ #import "DDGameKitHelperDelegate.h" #import +// ----------------------------------------------------------------- + static NSString* kAchievementsFile = @".achievements"; static NSString* kScoresFile = @".scores"; +// ----------------------------------------------------------------- + @interface DDGameKitHelper (Private) --(void) registerForLocalPlayerAuthChange; --(void) initScores; --(void) initAchievements; --(void) synchronizeAchievements; --(void) synchronizeScores; --(void) saveScores; --(void) saveAchievements; --(void) loadAchievementDescriptions; --(GKScore*) getScoreByCategory:(NSString*)category; --(GKAchievement*) getAchievement:(NSString*)identifier; --(UIViewController*) getRootViewController; +// Init +- (void) initScores; +- (void) initAchievements; +- (void) loadAchievementDescriptions; +// Saving +- (void) saveScores; +- (void) saveAchievements; +// Synchronizing +- (void) synchronizeAchievements; +- (void) synchronizeScores; +// Authentication +- (void) registerForLocalPlayerAuthChange; +// Getters +- (UIViewController*) getRootViewController; +- (GKScore*) getScoreByCategory:(NSString*)category; +- (GKAchievement*) getAchievement:(NSString*)identifier; @end +// ----------------------------------------------------------------- @implementation DDGameKitHelper +// ----------------------------------------------------------------- -static DDGameKitHelper *instanceOfGameKitHelper; +// ----------------------------------------------------------------- +#pragma mark - Singleton +#pragma mark - +// ----------------------------------------------------------------- -+(id) alloc ++ (instancetype) sharedGameKitHelper { - @synchronized(self) - { - NSAssert(instanceOfGameKitHelper == nil, @"Attempted to allocate a second instance of the singleton: GameKitHelper"); - instanceOfGameKitHelper = [[super alloc] retain]; - return instanceOfGameKitHelper; - } + dispatch_once_t pred; + __strong static DDGameKitHelper *sharedGameKitHelper = nil; - return nil; -} - -+(DDGameKitHelper*) sharedGameKitHelper -{ - @synchronized(self) - { - if (instanceOfGameKitHelper == nil) - { - [[DDGameKitHelper alloc] init]; - } - - return instanceOfGameKitHelper; - } + dispatch_once(&pred, ^{ + sharedGameKitHelper = [[self alloc] init]; + }); - return nil; + return sharedGameKitHelper; } -@synthesize delegate; -@synthesize isGameCenterAvailable; -@synthesize achievements; -@synthesize scores; -@synthesize achievementDescriptions; -@synthesize currentPlayerID; +// ----------------------------------------------------------------- +#pragma mark - 00 Init & Dealloc +#pragma mark - +// ----------------------------------------------------------------- --(NSString *) returnMD5Hash:(NSString*)concat -{ - const char *concat_str = [concat UTF8String]; - unsigned char result[CC_MD5_DIGEST_LENGTH]; - CC_MD5(concat_str, strlen(concat_str), result); - NSMutableString *hash = [NSMutableString string]; - for (int i = 0; i < 16; i++) - { - [hash appendFormat:@"%02X", result[i]]; - } - - return [hash lowercaseString]; -} - --(id) init +- (instancetype) init { if ((self = [super init])) { - delegate = [[DDGameKitHelperDelegate alloc] init]; + _delegate = [[DDGameKitHelperDelegate alloc] init]; // Test for Game Center availability Class gameKitLocalPlayerClass = NSClassFromString(@"GKLocalPlayer"); @@ -92,49 +75,53 @@ -(id) init NSString* currSysVer = [[UIDevice currentDevice] systemVersion]; bool isOSVer41 = ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending); - isGameCenterAvailable = (isLocalPlayerAvailable && isOSVer41); - NSLog(@"GameCenter available = %@", isGameCenterAvailable ? @"YES" : @"NO"); + _isGameCenterAvailable = (isLocalPlayerAvailable && isOSVer41); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"GameCenter available = %@", _isGameCenterAvailable ? @"YES" : @"NO"); - if (isGameCenterAvailable) + if (_isGameCenterAvailable) [self registerForLocalPlayerAuthChange]; } return self; } --(void) dealloc +// ----------------------------------------------------------------- + +- (void) dealloc { - [instanceOfGameKitHelper release]; - instanceOfGameKitHelper = nil; - [self saveScores]; [self saveAchievements]; - [scores release]; - [achievements release]; - [achievementDescriptions release]; - - [currentPlayerID release]; - [[NSNotificationCenter defaultCenter] removeObserver:self]; - [super dealloc]; } --(void) setNotAvailable +// ----------------------------------------------------------------- +#pragma mark - 01 Public +#pragma mark - +#pragma mark a) Availability +// ----------------------------------------------------------------- + +- (void) setNotAvailable { - isGameCenterAvailable = NO; + _isGameCenterAvailable = NO; [[NSNotificationCenter defaultCenter] removeObserver:self]; } --(bool) isAvailable +// ----------------------------------------------------------------- + +- (BOOL) isAvailable { - return isGameCenterAvailable; + return _isGameCenterAvailable; } --(void) authenticateLocalPlayer +// ----------------------------------------------------------------- +#pragma mark b) Authentication +// ----------------------------------------------------------------- + +- (void) authenticateLocalPlayer { - if (isGameCenterAvailable == NO) + if (_isGameCenterAvailable == NO) return; GKLocalPlayer* localPlayer = [GKLocalPlayer localPlayer]; @@ -144,216 +131,411 @@ -(void) authenticateLocalPlayer { if (error != nil) { - NSLog(@"error authenticating player: %@", [error localizedDescription]); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"error authenticating player: %@", [error localizedDescription]); } else { - NSLog(@"player authenticated"); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"player authenticated"); } }]; } } --(bool) isLocalPlayerAuthenticated -{ - if (isGameCenterAvailable == NO) - return isGameCenterAvailable; +// ----------------------------------------------------------------- +- (BOOL) isLocalPlayerAuthenticated +{ + if (_isGameCenterAvailable == NO) + return _isGameCenterAvailable; + GKLocalPlayer* localPlayer = [GKLocalPlayer localPlayer]; return localPlayer.authenticated; } --(void) onLocalPlayerAuthenticationChanged +// ----------------------------------------------------------------- +#pragma mark c) Submit Progress +// ----------------------------------------------------------------- + +- (void) submitScore:(int64_t)value category:(NSString*)category { - NSString* newPlayerID; - GKLocalPlayer* localPlayer = [GKLocalPlayer localPlayer]; + if (_isGameCenterAvailable == NO) + return; - // if not authenticating then just return + // always report the new score + if (DDGAMEKIT_LOGGING == 1) NSLog(@"reporting score of %lld for %@", value, category); + GKScore* newScore = [[GKScore alloc] initWithCategory:category]; + newScore.value = value; + [newScore reportScoreWithCompletionHandler:^(NSError* error) + { + // if it's better than the previous score, then save it and notify the user + GKScore* score = [self getScoreByCategory:category]; + if ([_delegate compareScore:value toScore:score.value]) + { + if (DDGAMEKIT_LOGGING == 1) NSLog(@"new high score of %lld for %@", score.value, category); + score.value = value; + [self saveScores]; + [_delegate onSubmitScore:value]; + } + }]; - if (!localPlayer.isAuthenticated) - { +} + +// ----------------------------------------------------------------- + +- (void) reportAchievement:(NSString*)identifier percentComplete:(float)percent +{ + if (_isGameCenterAvailable == NO) return; + + GKAchievement* achievement = [self getAchievement:identifier]; + if (achievement.percentComplete < percent) + { + if (DDGAMEKIT_LOGGING == 1) NSLog(@"new achievement %@ reported", achievement.identifier); + achievement.percentComplete = percent; + [achievement reportAchievementWithCompletionHandler:^(NSError* error) + { + [_delegate onReportAchievement:(GKAchievement*)achievement]; + }]; + + [self saveAchievements]; } +} + +// ----------------------------------------------------------------- +#pragma mark d) Resetting Achievements +// ----------------------------------------------------------------- + +- (void) resetAchievements +{ + if (_isGameCenterAvailable == NO) + return; + + [_achievements removeAllObjects]; + [self saveAchievements]; - NSLog(@"onLocalPlayerAuthenticationChanged. reloading scores and achievements and resynchronzing."); + [GKAchievement resetAchievementsWithCompletionHandler:^(NSError* error) {}]; - if (localPlayer.playerID != nil) + if (DDGAMEKIT_LOGGING == 1) NSLog(@"achievements reset"); +} +// ----------------------------------------------------------------- +#pragma mark e) Showing Game Center +// ----------------------------------------------------------------- + +- (void) showGameCenter +{ + if (_isGameCenterAvailable == NO) { - newPlayerID = [self returnMD5Hash:localPlayer.playerID]; + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Game Center" message:@"Game Center is not available" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil, nil]; + [alert show]; + + return; + } + + if ([GKGameCenterViewController class]) + { + GKGameCenterViewController *gameCenterController = [[GKGameCenterViewController alloc] init]; + if (gameCenterController != nil) + { + gameCenterController.gameCenterDelegate = self; + [self presentViewController:gameCenterController]; + } } else { - newPlayerID = @"unknown"; + [self showLeaderboard]; } - - if (currentPlayerID != nil && [currentPlayerID compare:newPlayerID] == NSOrderedSame) +} + +// ----------------------------------------------------------------- + +- (void) showLeaderboard +{ + if (_isGameCenterAvailable == NO) { - NSLog(@"player is the same"); + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Game Center" message:@"Game Center is not available" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil, nil]; + [alert show]; + return; } - self.currentPlayerID = newPlayerID; - NSLog(@"currentPlayerID=%@", currentPlayerID); - - [self initScores]; - [self initAchievements]; + GKLeaderboardViewController* leaderboardVC = [[GKLeaderboardViewController alloc] init]; + if (leaderboardVC != nil) + { + leaderboardVC.leaderboardDelegate = self; + [self presentViewController:leaderboardVC]; + } +} + +// ----------------------------------------------------------------- + +- (void) showLeaderboardWithCategory:(NSString*)category timeScope:(int)tscope +{ + if (_isGameCenterAvailable == NO) + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Game Center" message:@"Game Center is not available" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil, nil]; + [alert show]; + + return; + } - [self synchronizeScores]; - [self synchronizeAchievements]; - [self loadAchievementDescriptions]; + GKLeaderboardViewController* leaderboardVC = [[GKLeaderboardViewController alloc] init]; + if (leaderboardVC != nil) + { + leaderboardVC.leaderboardDelegate = self; + leaderboardVC.category = category; + leaderboardVC.timeScope = tscope; + [self presentViewController:leaderboardVC]; + } } --(void) registerForLocalPlayerAuthChange +// ----------------------------------------------------------------- + +- (void) showAchievements { - if (isGameCenterAvailable == NO) + if (_isGameCenterAvailable == NO) + { + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Game Center" message:@"Game Center is not available" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil, nil]; + [alert show]; + return; + } - NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; - [nc addObserver:self selector:@selector(onLocalPlayerAuthenticationChanged) name:GKPlayerAuthenticationDidChangeNotificationName object:nil]; + GKAchievementViewController* achievementsVC = [[GKAchievementViewController alloc] init]; + if (achievementsVC != nil) + { + achievementsVC.achievementDelegate = self; + [self presentViewController:achievementsVC]; + } +} + +// ----------------------------------------------------------------- +#pragma mark f) Achievement Numbers +// ----------------------------------------------------------------- + +- (int) numberOfTotalAchievements +{ + int count = 0; + if (_isGameCenterAvailable) + { + count = [_achievementDescriptions allValues].count; + } + return count; +} + + +// ----------------------------------------------------------------- + +- (int) numberOfCompletedAchievements +{ + int count = 0; + if (_isGameCenterAvailable) + { + NSArray* gcAchievementsArray = [_achievements allValues]; + for (GKAchievement* gcAchievement in gcAchievementsArray) + { + if (gcAchievement.completed) + count++; + } + } + return count; } --(void) initScores +// ----------------------------------------------------------------- +#pragma mark g) Achievement Description +// ----------------------------------------------------------------- + +- (GKAchievementDescription*) getAchievementDescription:(NSString*)identifier +{ + GKAchievementDescription* description = [_achievementDescriptions objectForKey:identifier]; + return description; +} + +// ----------------------------------------------------------------- +#pragma mark - 02 Private +#pragma mark - +#pragma mark a) Init +// ----------------------------------------------------------------- + +- (void) initScores { NSString* libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - NSString* file = [libraryPath stringByAppendingPathComponent:currentPlayerID]; + NSString* file = [libraryPath stringByAppendingPathComponent:_currentPlayerID]; file = [file stringByAppendingString:kScoresFile]; id object = [NSKeyedUnarchiver unarchiveObjectWithFile:file]; if ([object isKindOfClass:[NSMutableDictionary class]]) { NSMutableDictionary* loadedScores = (NSMutableDictionary*)object; - scores = [[NSMutableDictionary alloc] initWithDictionary:loadedScores]; + _scores = [[NSMutableDictionary alloc] initWithDictionary:loadedScores]; } else { - scores = [[NSMutableDictionary alloc] init]; + _scores = [[NSMutableDictionary alloc] init]; } - NSLog(@"scores initialized: %d", scores.count); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"scores initialized: %d", _scores.count); } --(void) initAchievements +// ----------------------------------------------------------------- + +- (void) initAchievements { NSString* libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - NSString* file = [libraryPath stringByAppendingPathComponent:currentPlayerID]; + NSString* file = [libraryPath stringByAppendingPathComponent:_currentPlayerID]; file = [file stringByAppendingString:kAchievementsFile]; id object = [NSKeyedUnarchiver unarchiveObjectWithFile:file]; if ([object isKindOfClass:[NSMutableDictionary class]]) { NSMutableDictionary* loadedAchievements = (NSMutableDictionary*)object; - achievements = [[NSMutableDictionary alloc] initWithDictionary:loadedAchievements]; + _achievements = [[NSMutableDictionary alloc] initWithDictionary:loadedAchievements]; } else { - achievements = [[NSMutableDictionary alloc] init]; + _achievements = [[NSMutableDictionary alloc] init]; } - NSLog(@"achievements initialized: %d", achievements.count); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"achievements initialized: %d", _achievements.count); +} + +// ----------------------------------------------------------------- + +- (void)loadAchievementDescriptions +{ + if (DDGAMEKIT_LOGGING == 1) NSLog(@"loading achievement descriptions"); + + [GKAchievementDescription loadAchievementDescriptionsWithCompletionHandler:^(NSArray *achievementDesc, NSError *error) + { + _achievementDescriptions = [[NSMutableDictionary alloc] init]; + + if (error != nil) + { + if (DDGAMEKIT_LOGGING == 1) NSLog(@"unable to load achievements"); + return; + } + + for (GKAchievementDescription *description in achievementDesc) + { + [_achievementDescriptions setObject:description forKey:description.identifier]; + } + + if (DDGAMEKIT_LOGGING == 1) NSLog(@"achievement descriptions initialized: %d", _achievementDescriptions.count); + }]; } +// ----------------------------------------------------------------- +#pragma mark b) Saving +// ----------------------------------------------------------------- + - (void) saveScores { NSString* libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - NSString* file = [libraryPath stringByAppendingPathComponent:currentPlayerID]; + NSString* file = [libraryPath stringByAppendingPathComponent:_currentPlayerID]; file = [file stringByAppendingString:kScoresFile]; - [NSKeyedArchiver archiveRootObject:scores toFile:file]; - NSLog(@"scores saved: %d", scores.count); + [NSKeyedArchiver archiveRootObject:_scores toFile:file]; + if (DDGAMEKIT_LOGGING == 1) NSLog(@"scores saved: %d", _scores.count); } --(void) saveAchievements +// ----------------------------------------------------------------- + +- (void) saveAchievements { NSString* libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; - NSString* file = [libraryPath stringByAppendingPathComponent:currentPlayerID]; + NSString* file = [libraryPath stringByAppendingPathComponent:_currentPlayerID]; file = [file stringByAppendingString:kAchievementsFile]; - [NSKeyedArchiver archiveRootObject:achievements toFile:file]; - NSLog(@"achievements saved: %d", achievements.count); + [NSKeyedArchiver archiveRootObject:_achievements toFile:file]; + if (DDGAMEKIT_LOGGING == 1) NSLog(@"achievements saved: %d", _achievements.count); } --(void) synchronizeScores +// ----------------------------------------------------------------- +#pragma mark c) Synchronizing +// ----------------------------------------------------------------- + +- (void) synchronizeScores { - NSLog(@"synchronizing scores"); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"synchronizing scores"); // get the top score for each category for current player and compare it to the game center score for the same category - [GKLeaderboard loadCategoriesWithCompletionHandler:^(NSArray *categories, NSArray *titles, NSError *error) + [GKLeaderboard loadCategoriesWithCompletionHandler:^(NSArray *categories, NSArray *titles, NSError *error) { if (error != nil) { - NSLog(@"unable to synchronize scores"); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"unable to synchronize scores"); return; } NSString* playerId = [GKLocalPlayer localPlayer].playerID; - for (NSString* category in categories) - { + for (NSString* category in categories) + { GKLeaderboard *leaderboardRequest = [[GKLeaderboard alloc] initWithPlayerIDs:[NSArray arrayWithObject:playerId]]; leaderboardRequest.category = category; leaderboardRequest.timeScope = GKLeaderboardTimeScopeAllTime; leaderboardRequest.range = NSMakeRange(1,1); - [leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *playerScores, NSError *error) + [leaderboardRequest loadScoresWithCompletionHandler: ^(NSArray *playerScores, NSError *error) { if (error != nil) { - NSLog(@"unable to synchronize scores"); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"unable to synchronize scores"); return; } GKScore* gcScore = nil; if ([playerScores count] > 0) gcScore = [playerScores objectAtIndex:0]; - GKScore* localScore = [scores objectForKey:category]; + GKScore* localScore = [_scores objectForKey:category]; //Must add the next two lines in order to prevent a 'A GKScore must contain an initialized value' crash - GKScore *toReport = [[[GKScore alloc] initWithCategory:category] autorelease]; + GKScore *toReport = [[GKScore alloc] initWithCategory:category]; toReport.value = localScore.value; if (gcScore == nil && localScore == nil) { - NSLog(@"%@(%lld,%lld): no score yet. nothing to synch", category, gcScore.value, localScore.value); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"%@(%lld,%lld): no score yet. nothing to synch", category, gcScore.value, localScore.value); } else if (gcScore == nil) { - NSLog(@"%@(%lld,%lld): gc score missing. reporting local score", category, gcScore.value, localScore.value); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"%@(%lld,%lld): gc score missing. reporting local score", category, gcScore.value, localScore.value); [localScore reportScoreWithCompletionHandler:^(NSError* error) {}]; } else if (localScore == nil) { - NSLog(@"%@(%lld,%lld): local score missing. caching gc score", category, gcScore.value, localScore.value); - [scores setObject:gcScore forKey:gcScore.category]; + if (DDGAMEKIT_LOGGING == 1) NSLog(@"%@(%lld,%lld): local score missing. caching gc score", category, gcScore.value, localScore.value); + [_scores setObject:gcScore forKey:gcScore.category]; [self saveScores]; } - else if ([delegate compare:localScore.value to:gcScore.value]) + else if ([_delegate compareScore:localScore.value toScore:gcScore.value]) { - NSLog(@"%@(%lld,%lld): local score more current than gc score. reporting local score", category, gcScore.value, localScore.value); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"%@(%lld,%lld): local score more current than gc score. reporting local score", category, gcScore.value, localScore.value); [toReport reportScoreWithCompletionHandler:^(NSError* error) {}]; } - else if ([delegate compare:gcScore.value to:localScore.value]) + else if ([_delegate compareScore:gcScore.value toScore:localScore.value]) { - NSLog(@"%@(%lld,%lld): gc score is more current than local score. caching gc score", category, gcScore.value, localScore.value); - [scores setObject:gcScore forKey:gcScore.category]; + if (DDGAMEKIT_LOGGING == 1) NSLog(@"%@(%lld,%lld): gc score is more current than local score. caching gc score", category, gcScore.value, localScore.value); + [_scores setObject:gcScore forKey:gcScore.category]; [self saveScores]; } else { - NSLog(@"%@(%lld,%lld): scores are equal. nothing to synch", category, gcScore.value, localScore.value); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"%@(%lld,%lld): scores are equal. nothing to synch", category, gcScore.value, localScore.value); } }]; - [leaderboardRequest release]; } }]; } --(void) synchronizeAchievements +// ----------------------------------------------------------------- + +- (void) synchronizeAchievements { - NSLog(@"synchronizing achievements"); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"synchronizing achievements"); // get the achievements from game center @@ -361,298 +543,196 @@ -(void) synchronizeAchievements { if (error != nil) { - NSLog(@"unable to synchronize achievements"); + if (DDGAMEKIT_LOGGING == 1) NSLog(@"unable to synchronize achievements"); return; } // convert NSArray into NSDictionary for ease of use NSMutableDictionary *gcAchievements = [[NSMutableDictionary alloc] init]; - for (GKAchievement* gcAchievement in gcAchievementsArray) + for (GKAchievement* gcAchievement in gcAchievementsArray) { [gcAchievements setObject:gcAchievement forKey:gcAchievement.identifier]; } // find local achievements not yet reported in game center and report them - for (NSString* identifier in achievements) + for (NSString* identifier in _achievements) { GKAchievement *gcAchievement = [gcAchievements objectForKey:identifier]; if (gcAchievement == nil) { - NSLog(@"achievement %@ not in game center. reporting it", identifier); - [[achievements objectForKey:identifier] reportAchievementWithCompletionHandler:^(NSError* error) {}]; + if (DDGAMEKIT_LOGGING == 1) NSLog(@"achievement %@ not in game center. reporting it", identifier); + [[_achievements objectForKey:identifier] reportAchievementWithCompletionHandler:^(NSError* error) {}]; } } // find game center achievements that are not reported locally and store them for (GKAchievement* gcAchievement in gcAchievementsArray) { - GKAchievement* localAchievement = [achievements objectForKey:gcAchievement.identifier]; + GKAchievement* localAchievement = [_achievements objectForKey:gcAchievement.identifier]; if (localAchievement == nil) { - NSLog(@"achievement %@ not stored locally. storing it", gcAchievement.identifier); - [achievements setObject:gcAchievement forKey:gcAchievement.identifier]; + if (DDGAMEKIT_LOGGING == 1) NSLog(@"achievement %@ not stored locally. storing it", gcAchievement.identifier); + [_achievements setObject:gcAchievement forKey:gcAchievement.identifier]; } } [self saveAchievements]; - [gcAchievements release]; }]; } --(void) submitScore:(int64_t)value category:(NSString*)category +// ----------------------------------------------------------------- +#pragma mark d) Authentication +// ----------------------------------------------------------------- + +- (void) onLocalPlayerAuthenticationChanged { - if (isGameCenterAvailable == NO) + NSString* newPlayerID; + GKLocalPlayer* localPlayer = [GKLocalPlayer localPlayer]; + + // if not authenticating then just return + + if (!localPlayer.isAuthenticated) + { return; + } - // always report the new score - NSLog(@"reporting score of %lld for %@", value, category); - GKScore* newScore = [[GKScore alloc] initWithCategory:category]; - newScore.value = value; - [newScore reportScoreWithCompletionHandler:^(NSError* error) - { - // if it's better than the previous score, then save it and notify the user - GKScore* score = [self getScoreByCategory:category]; - if ([delegate compare:value to:score.value]) - { - NSLog(@"new high score of %lld for %@", score.value, category); - score.value = value; - [self saveScores]; - [delegate onSubmitScore:value]; - } - }]; + if (DDGAMEKIT_LOGGING == 1) NSLog(@"onLocalPlayerAuthenticationChanged. reloading scores and achievements and resynchronzing."); - [newScore release]; -} - --(GKScore*) getScoreByCategory:(NSString*)category -{ - GKScore* score = [scores objectForKey:category]; + if (localPlayer.playerID != nil) + { + newPlayerID = [self returnMD5Hash:localPlayer.playerID]; + } + else + { + newPlayerID = @"unknown"; + } - if (score == nil) + if (_currentPlayerID != nil && [_currentPlayerID compare:newPlayerID] == NSOrderedSame) { - score = [[[GKScore alloc] initWithCategory:category] autorelease]; - score.value = 0; - [scores setObject:score forKey:category]; + if (DDGAMEKIT_LOGGING == 1) NSLog(@"player is the same"); + return; } - return score; + self.currentPlayerID = newPlayerID; + if (DDGAMEKIT_LOGGING == 1) NSLog(@"currentPlayerID=%@", _currentPlayerID); + + [self initScores]; + [self initAchievements]; + + [self synchronizeScores]; + [self synchronizeAchievements]; + [self loadAchievementDescriptions]; } --(void) reportAchievement:(NSString*)identifier percentComplete:(float)percent +// ----------------------------------------------------------------- + +- (void) registerForLocalPlayerAuthChange { - if (isGameCenterAvailable == NO) + if (_isGameCenterAvailable == NO) return; - GKAchievement* achievement = [self getAchievement:identifier]; - if (achievement.percentComplete < percent) - { - NSLog(@"new achievement %@ reported", achievement.identifier); - achievement.percentComplete = percent; - [achievement reportAchievementWithCompletionHandler:^(NSError* error) - { - [delegate onReportAchievement:(GKAchievement*)achievement]; - }]; - - [self saveAchievements]; - } + NSNotificationCenter* nc = [NSNotificationCenter defaultCenter]; + [nc addObserver:self selector:@selector(onLocalPlayerAuthenticationChanged) name:GKPlayerAuthenticationDidChangeNotificationName object:nil]; } --(GKAchievement*) getAchievement:(NSString*)identifier +// ----------------------------------------------------------------- +#pragma mark e) Getters +// ----------------------------------------------------------------- + +- (GKScore*) getScoreByCategory:(NSString*)category { - GKAchievement* achievement = [achievements objectForKey:identifier]; + GKScore* score = [_scores objectForKey:category]; - if (achievement == nil) + if (score == nil) { - achievement = [[[GKAchievement alloc] initWithIdentifier:identifier] autorelease]; - [achievements setObject:achievement forKey:achievement.identifier]; + score = [[GKScore alloc] initWithCategory:category]; + score.value = 0; + [_scores setObject:score forKey:category]; } - return achievement; -} - -- (void)loadAchievementDescriptions -{ - NSLog(@"loading achievement descriptions"); - - [GKAchievementDescription loadAchievementDescriptionsWithCompletionHandler:^(NSArray *achievementDesc, NSError *error) - { - achievementDescriptions = [[NSMutableDictionary alloc] init]; - - if (error != nil) - { - NSLog(@"unable to load achievements"); - return; - } - - for (GKAchievementDescription *description in achievementDesc) - { - [achievementDescriptions setObject:description forKey:description.identifier]; - } - - NSLog(@"achievement descriptions initialized: %d", achievementDescriptions.count); - }]; + return score; } --(GKAchievementDescription*) getAchievementDescription:(NSString*)identifier -{ - GKAchievementDescription* description = [achievementDescriptions objectForKey:identifier]; - return description; -} +// ----------------------------------------------------------------- --(void) resetAchievements +- (GKAchievement*) getAchievement:(NSString*)identifier { - if (isGameCenterAvailable == NO) - return; + GKAchievement* achievement = [_achievements objectForKey:identifier]; - [achievements removeAllObjects]; - [self saveAchievements]; - - [GKAchievement resetAchievementsWithCompletionHandler:^(NSError* error) {}]; + if (achievement == nil) + { + achievement = [[GKAchievement alloc] initWithIdentifier:identifier]; + [_achievements setObject:achievement forKey:achievement.identifier]; + } - NSLog(@"achievements reset"); + return achievement; } --(UIViewController*) getRootViewController +// ----------------------------------------------------------------- + +- (UIViewController*) getRootViewController { return [UIApplication sharedApplication].keyWindow.rootViewController; } --(void) presentViewController:(UIViewController*)vc +// ----------------------------------------------------------------- +#pragma mark f) View Controllers +// ----------------------------------------------------------------- + +- (void) presentViewController:(UIViewController*)vc { UIViewController* rootVC = [self getRootViewController]; [rootVC presentModalViewController:vc animated:YES]; } --(void) dismissModalViewController +// ----------------------------------------------------------------- + +- (void) dismissModalViewController { UIViewController* rootVC = [self getRootViewController]; [rootVC dismissModalViewControllerAnimated:YES]; } --(void) showGameCenter -{ - if (isGameCenterAvailable == NO) - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Game Center" message:@"Game Center is not available" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil, nil]; - [alert show]; - [alert release]; - - return; - } - - if ([GKGameCenterViewController class]) - { - GKGameCenterViewController *gameCenterController = [[[GKGameCenterViewController alloc] init] autorelease]; - if (gameCenterController != nil) - { - gameCenterController.gameCenterDelegate = self; - [self presentViewController:gameCenterController]; - } - } - else - { - [self showLeaderboard]; - } -} +// ----------------------------------------------------------------- -- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController +- (void) gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController { [self dismissModalViewController]; } --(void) showLeaderboard -{ - if (isGameCenterAvailable == NO) - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Game Center" message:@"Game Center is not available" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil, nil]; - [alert show]; - [alert release]; - - return; - } - - GKLeaderboardViewController* leaderboardVC = [[[GKLeaderboardViewController alloc] init] autorelease]; - if (leaderboardVC != nil) - { - leaderboardVC.leaderboardDelegate = self; - [self presentViewController:leaderboardVC]; - } -} +// ----------------------------------------------------------------- --(void) showLeaderboardwithCategory:(NSString*)category timeScope:(int)tscope -{ - if (isGameCenterAvailable == NO) - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Game Center" message:@"Game Center is not available" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil, nil]; - [alert show]; - [alert release]; - - return; - } - - GKLeaderboardViewController* leaderboardVC = [[[GKLeaderboardViewController alloc] init] autorelease]; - if (leaderboardVC != nil) - { - leaderboardVC.leaderboardDelegate = self; - leaderboardVC.category = category; - leaderboardVC.timeScope = tscope; - [self presentViewController:leaderboardVC]; - } -} - --(void) leaderboardViewControllerDidFinish:(GKLeaderboardViewController*)viewController +- (void) leaderboardViewControllerDidFinish:(GKLeaderboardViewController*)viewController { [self dismissModalViewController]; } --(void) showAchievements -{ - if (isGameCenterAvailable == NO) - { - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Game Center" message:@"Game Center is not available" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil, nil]; - [alert show]; - [alert release]; - - return; - } - - GKAchievementViewController* achievementsVC = [[[GKAchievementViewController alloc] init] autorelease]; - if (achievementsVC != nil) - { - achievementsVC.achievementDelegate = self; - [self presentViewController:achievementsVC]; - } -} +// ----------------------------------------------------------------- --(void) achievementViewControllerDidFinish:(GKAchievementViewController*)viewController +- (void) achievementViewControllerDidFinish:(GKAchievementViewController*)viewController { [self dismissModalViewController]; } -- (int) numberOfTotalAchievements -{ - int count = 0; - if (isGameCenterAvailable) - { - count = [achievementDescriptions allValues].count; - } - return count; -} +// ----------------------------------------------------------------- +#pragma mark g) Other +// ----------------------------------------------------------------- -- (int) numberOfCompletedAchievements +- (NSString *) returnMD5Hash:(NSString*)concat { - int count = 0; - if (isGameCenterAvailable) + const char *concat_str = [concat UTF8String]; + unsigned char result[CC_MD5_DIGEST_LENGTH]; + CC_MD5(concat_str, strlen(concat_str), result); + NSMutableString *hash = [NSMutableString string]; + for (int i = 0; i < 16; i++) { - NSArray* gcAchievementsArray = [achievements allValues]; - for (GKAchievement* gcAchievement in gcAchievementsArray) - { - if (gcAchievement.completed) - count++; - } + [hash appendFormat:@"%02X", result[i]]; } - return count; + + return [hash lowercaseString]; } +// ----------------------------------------------------------------- @end +// ----------------------------------------------------------------- diff --git a/DDGameKitHelperDelegate.m b/DDGameKitHelperDelegate.m index 52b1a2f..069e45c 100644 --- a/DDGameKitHelperDelegate.m +++ b/DDGameKitHelperDelegate.m @@ -2,29 +2,48 @@ // DDGameKitHelperDelegate.h // Version 1.0 +// ----------------------------------------------------------------- +#define DDGAMEKIT_USE_NOTIFICATION 1 +// ----------------------------------------------------------------- + #import "DDGameKitHelperDelegate.h" +#if DDGAMEKIT_USE_NOTIFICATION == 1 #import "GKAchievementHandler.h" +#endif +// ----------------------------------------------------------------- @implementation DDGameKitHelperDelegate +// ----------------------------------------------------------------- -// return true if score1 is greater than score2 -// modify this if your scoreboard is reversed (low scores on top) --(bool) compare:(int64_t)score1 to:(int64_t)score2 +// Returns 'true' if score1 is greater than score2 +// Modify this if your scoreboard is reversed (lowest scores first) +// For example - a lap time in a racer game (the lower the better) +- (BOOL) compareScore:(int64_t)score1 toScore:(int64_t)score2 { return score1 > score2; } -// display new high score using GKAchievement class --(void) onSubmitScore:(int64_t)score; +// ----------------------------------------------------------------- + +// If enabled, display new high score notification using GKAchievementHandler +- (void) onSubmitScore:(int64_t)score; { - [[GKAchievementHandler defaultHandler] notifyAchievementTitle:@"New High Score!!!" andMessage:[NSString stringWithFormat:@"%d", score]]; +#if DDGAMEKIT_USE_NOTIFICATION == 1 + [[GKAchievementHandler defaultHandler] notifyAchievementTitle:@"New High Score!" andMessage:[NSString stringWithFormat:@"%d", (int)score]]; +#endif } -// display the achievement using GKAchievement class --(void) onReportAchievement:(GKAchievement*)achievement +// ----------------------------------------------------------------- + +// If enabled, display achievement notification using GKAchievementHandler +- (void) onReportAchievement:(GKAchievement*)achievement { +#if DDGAMEKIT_USE_NOTIFICATION == 1 DDGameKitHelper* gkHelper = [DDGameKitHelper sharedGameKitHelper]; [[GKAchievementHandler defaultHandler] notifyAchievement:[gkHelper getAchievementDescription:achievement.identifier]]; +#endif } +// ----------------------------------------------------------------- @end +// ----------------------------------------------------------------- \ No newline at end of file From ae64d9f39577eeb72b5999b80723ae03feb80da1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20H=C3=A1dl?= Date: Sat, 8 Jun 2013 11:39:56 +0200 Subject: [PATCH 09/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index edc9f87..c0c5176 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ in `DDGameKitHelperDelegate.m` file. ARC Support --------------- -This class doesn't support ARC, however still works well with `-fno-objc-arc` compiler flag in ARC projects. +This class has been converted to ARC, however still works well with `-objc-arc` compiler flag in non-ARC projects. Installation ------------ From 6ba647cadb2669c2d456205c4d46f3b34345226d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20H=C3=A1dl?= Date: Sat, 8 Jun 2013 11:41:52 +0200 Subject: [PATCH 10/13] Fix typo in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c0c5176..de4552a 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ in `DDGameKitHelperDelegate.m` file. ARC Support --------------- -This class has been converted to ARC, however still works well with `-objc-arc` compiler flag in non-ARC projects. +This class has been converted to ARC, however still works well with `-fobjc-arc` compiler flag in non-ARC projects. Installation ------------ From 4ff73b9b208e341fcb2b67cc8d753d4c32ebf715 Mon Sep 17 00:00:00 2001 From: Dominik Hadl Date: Sat, 8 Jun 2013 11:58:16 +0200 Subject: [PATCH 11/13] Fix bug in singleton --- DDGameKitHelper.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/DDGameKitHelper.m b/DDGameKitHelper.m index 9409846..391df8a 100755 --- a/DDGameKitHelper.m +++ b/DDGameKitHelper.m @@ -45,10 +45,10 @@ @implementation DDGameKitHelper + (instancetype) sharedGameKitHelper { - dispatch_once_t pred; - __strong static DDGameKitHelper *sharedGameKitHelper = nil; + static DDGameKitHelper *sharedGameKitHelper = nil; - dispatch_once(&pred, ^{ + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ sharedGameKitHelper = [[self alloc] init]; }); From c7651e08835796fda2a228eaf6b80399daeea3fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20H=C3=A1dl?= Date: Wed, 3 Jul 2013 09:58:43 +0200 Subject: [PATCH 12/13] Create .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..c3f4dc3 --- /dev/null +++ b/.travis.yml @@ -0,0 +1 @@ +language: objective-c From b516c2aca8b767050b7bf5a91dc5bba37fe266b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20H=C3=A1dl?= Date: Fri, 5 Jul 2013 14:01:37 +0200 Subject: [PATCH 13/13] Delete .travis.yml --- .travis.yml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index c3f4dc3..0000000 --- a/.travis.yml +++ /dev/null @@ -1 +0,0 @@ -language: objective-c