├── GameCenterExample ├── .watchmanconfig ├── .gitattributes ├── .babelrc ├── app.json ├── .buckconfig ├── ios │ ├── GameCenterExample │ │ ├── Images.xcassets │ │ │ └── AppIcon.appiconset │ │ │ │ ├── ipad-20x20-1x.png │ │ │ │ ├── ipad-20x20-2x.png │ │ │ │ ├── ipad-29x29-1x.png │ │ │ │ ├── ipad-29x29-2x.png │ │ │ │ ├── ipad-40x40-1x.png │ │ │ │ ├── ipad-40x40-2x.png │ │ │ │ ├── ipad-50x50-1x.png │ │ │ │ ├── ipad-50x50-2x.png │ │ │ │ ├── ipad-72x72-1x.png │ │ │ │ ├── ipad-72x72-2x.png │ │ │ │ ├── ipad-76x76-1x.png │ │ │ │ ├── ipad-76x76-2x.png │ │ │ │ ├── ipad-83.5x83.5-2x.png │ │ │ │ ├── iphone-20x20-2x.png │ │ │ │ ├── iphone-20x20-3x.png │ │ │ │ ├── iphone-29x29-1x.png │ │ │ │ ├── iphone-29x29-2x.png │ │ │ │ ├── iphone-29x29-3x.png │ │ │ │ ├── iphone-40x40-2x.png │ │ │ │ ├── iphone-40x40-3x.png │ │ │ │ ├── iphone-57x57-1x.png │ │ │ │ ├── iphone-57x57-2x.png │ │ │ │ ├── iphone-60x60-2x.png │ │ │ │ ├── iphone-60x60-3x.png │ │ │ │ └── Contents.json │ │ ├── AppDelegate.h │ │ ├── main.m │ │ ├── AppDelegate.m │ │ ├── Info.plist │ │ └── Base.lproj │ │ │ └── LaunchScreen.xib │ ├── GameCenterExampleTests │ │ ├── Info.plist │ │ └── GameCenterExampleTests.m │ ├── GameCenterExample-tvOSTests │ │ └── Info.plist │ ├── GameCenterExample-tvOS │ │ └── Info.plist │ └── GameCenterExample.xcodeproj │ │ └── xcshareddata │ │ └── xcschemes │ │ ├── GameCenterExample.xcscheme │ │ └── GameCenterExample-tvOS.xcscheme ├── package.json ├── .gitignore ├── .flowconfig └── index.ios.js ├── RNGameCenter ├── .gitattributes ├── ios │ ├── RNGameCenter.xcworkspace │ │ └── contents.xcworkspacedata │ ├── RNGameCenter.h │ ├── RNGameCenter.podspec │ ├── RNGameCenter.xcodeproj │ │ └── project.pbxproj │ └── RNGameCenter.m ├── package.json ├── .gitignore ├── README.md └── index.js ├── .babelrc ├── .DS_Store ├── .gitignore ├── snapshots ├── app.png ├── error.png ├── final.png ├── newapp.png ├── xcode.png ├── xcode1.png ├── achievements.png ├── achivements3.png ├── achivements4.png ├── achivements5.png ├── gamecenter.png ├── makenewapp.png ├── ifnotloggedin.png ├── app-achivements.png ├── app-leaderboard.png ├── leaderboardfinal.png ├── leaderboardsave.png ├── resetAchievements.png └── react-native-game-center.jpg ├── Screen Shot 2017-09-24 at 3.59.54 PM.png ├── .npmignore ├── .travis.yml ├── SETUP.md ├── package.json └── README.md /GameCenterExample/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /RNGameCenter/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { "presets": ["react-native"] } 2 | -------------------------------------------------------------------------------- /GameCenterExample/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /GameCenterExample/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["react-native"] 3 | } 4 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | bower_dependancies 3 | .tmp 4 | react-native-game-center/node_modules -------------------------------------------------------------------------------- /snapshots/app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/app.png -------------------------------------------------------------------------------- /GameCenterExample/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GameCenterExample", 3 | "displayName": "GameCenterExample" 4 | } -------------------------------------------------------------------------------- /snapshots/error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/error.png -------------------------------------------------------------------------------- /snapshots/final.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/final.png -------------------------------------------------------------------------------- /snapshots/newapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/newapp.png -------------------------------------------------------------------------------- /snapshots/xcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/xcode.png -------------------------------------------------------------------------------- /snapshots/xcode1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/xcode1.png -------------------------------------------------------------------------------- /snapshots/achievements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/achievements.png -------------------------------------------------------------------------------- /snapshots/achivements3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/achivements3.png -------------------------------------------------------------------------------- /snapshots/achivements4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/achivements4.png -------------------------------------------------------------------------------- /snapshots/achivements5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/achivements5.png -------------------------------------------------------------------------------- /snapshots/gamecenter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/gamecenter.png -------------------------------------------------------------------------------- /snapshots/makenewapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/makenewapp.png -------------------------------------------------------------------------------- /snapshots/ifnotloggedin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/ifnotloggedin.png -------------------------------------------------------------------------------- /snapshots/app-achivements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/app-achivements.png -------------------------------------------------------------------------------- /snapshots/app-leaderboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/app-leaderboard.png -------------------------------------------------------------------------------- /snapshots/leaderboardfinal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/leaderboardfinal.png -------------------------------------------------------------------------------- /snapshots/leaderboardsave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/leaderboardsave.png -------------------------------------------------------------------------------- /snapshots/resetAchievements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/resetAchievements.png -------------------------------------------------------------------------------- /snapshots/react-native-game-center.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/snapshots/react-native-game-center.jpg -------------------------------------------------------------------------------- /Screen Shot 2017-09-24 at 3.59.54 PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/Screen Shot 2017-09-24 at 3.59.54 PM.png -------------------------------------------------------------------------------- /GameCenterExample/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-20x20-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-20x20-1x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-20x20-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-20x20-2x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-29x29-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-29x29-1x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-29x29-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-29x29-2x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-40x40-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-40x40-1x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-40x40-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-40x40-2x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-50x50-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-50x50-1x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-50x50-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-50x50-2x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-72x72-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-72x72-1x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-72x72-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-72x72-2x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-76x76-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-76x76-1x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-76x76-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-76x76-2x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-83.5x83.5-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/ipad-83.5x83.5-2x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-20x20-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-20x20-2x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-20x20-3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-20x20-3x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-29x29-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-29x29-1x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-29x29-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-29x29-2x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-29x29-3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-29x29-3x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-40x40-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-40x40-2x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-40x40-3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-40x40-3x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-57x57-1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-57x57-1x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-57x57-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-57x57-2x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-60x60-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-60x60-2x.png -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-60x60-3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/garrettmac/react-native-game-center/HEAD/GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/iphone-60x60-3x.png -------------------------------------------------------------------------------- /RNGameCenter/ios/RNGameCenter.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | 3 | 5 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | GameCenterExample/* 2 | .DS_Store 3 | snapshots/* 4 | 5 | 6 | logs 7 | *.log 8 | pids 9 | *.pid 10 | *.seed 11 | lib-cov 12 | coverage 13 | .lock-wscript 14 | node_modules 15 | res 16 | dist/test/ 17 | coverage/ 18 | 19 | #build tools 20 | # .travis.yml 21 | 22 | 23 | #linters 24 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | cache: 3 | directories: 4 | - node_modules 5 | notifications: 6 | email: 7 | recipients: 8 | - garrett@vyga.io 9 | on_failure: change 10 | on_success: change 11 | node_js: 12 | - '7' 13 | - '6' 14 | - '4' 15 | before_script: 16 | - npm prune 17 | after_success: 18 | - npm run semantic-release 19 | branches: 20 | except: 21 | - /^v\d+\.\d+\.\d+$/ 22 | -------------------------------------------------------------------------------- /RNGameCenter/package.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "name": "react-native-game-center", 4 | "version": "1.0.0", 5 | "description": "", 6 | "main": "index.js", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "keywords": [ 11 | "react-native" 12 | ], 13 | "author": "", 14 | "license": "", 15 | "peerDependencies": { 16 | "react-native": "^0.41.2", 17 | "react-native-windows": "0.41.0-rc.1" 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /RNGameCenter/ios/RNGameCenter.h: -------------------------------------------------------------------------------- 1 | // 2 | // RNGameCenter.h 3 | // StockShot 4 | // 5 | // Created by vyga on 9/18/17. 6 | // Copyright © 2017 Facebook. All rights reserved. 7 | // 8 | 9 | //#import 10 | 11 | #import 12 | 13 | #if __has_include("RCTBridgeModule.h") 14 | #import "RCTBridgeModule.h" 15 | #else 16 | #import 17 | #endif 18 | 19 | 20 | 21 | 22 | @interface RNGameCenter : NSObject 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (nonatomic, strong) UIWindow *window; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "AppDelegate.h" 13 | 14 | int main(int argc, char * argv[]) { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /RNGameCenter/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # OSX 3 | # 4 | .DS_Store 5 | 6 | # node.js 7 | # 8 | node_modules/ 9 | npm-debug.log 10 | yarn-error.log 11 | 12 | 13 | # Xcode 14 | # 15 | build/ 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | xcuserdata 25 | *.xccheckout 26 | *.moved-aside 27 | DerivedData 28 | *.hmap 29 | *.ipa 30 | *.xcuserstate 31 | project.xcworkspace 32 | 33 | 34 | # Android/IntelliJ 35 | # 36 | build/ 37 | .idea 38 | .gradle 39 | local.properties 40 | *.iml 41 | 42 | # BUCK 43 | buck-out/ 44 | \.buckd/ 45 | *.keystore 46 | -------------------------------------------------------------------------------- /GameCenterExample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "GameCenterExample", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "start": "node node_modules/react-native/local-cli/cli.js start", 7 | "test": "jest" 8 | }, 9 | "dependencies": { 10 | "react": "16.0.0-alpha.12", 11 | "react-native": "0.48.4", 12 | "react-native-game-center": "^1.2.3", 13 | "react-native-vector-icons": "^4.4.0" 14 | }, 15 | "devDependencies": { 16 | "jest": "20.0.4", 17 | "react": "16.0.0-alpha.12", 18 | "react-native": "0.45.1", 19 | "react-test-renderer": "^16.0.0-alpha.12" 20 | }, 21 | "jest": { 22 | "preset": "react-native" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /RNGameCenter/ios/RNGameCenter.podspec: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | package = JSON.parse(File.read('../../package.json')) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = 'RNGameCenter' 7 | s.version = package['version'] 8 | s.summary = package['description'] 9 | s.description = package['description'] 10 | s.homepage = package['homepage'] 11 | s.license = package['license'] 12 | s.author = package['author'] 13 | s.source = { :git => "https://github.com/garrettmac/RNGameCenter.git" } 14 | s.platform = :ios, "7.0" 15 | s.source_files = "*.{h,m}" 16 | s.requires_arc = true 17 | s.dependency 'React' 18 | end 19 | -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExampleTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /GameCenterExample/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | project.xcworkspace 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | 33 | # node.js 34 | # 35 | node_modules/ 36 | npm-debug.log 37 | yarn-error.log 38 | 39 | # BUCK 40 | buck-out/ 41 | \.buckd/ 42 | *.keystore 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 50 | 51 | fastlane/report.xml 52 | fastlane/Preview.html 53 | fastlane/screenshots 54 | -------------------------------------------------------------------------------- /SETUP.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | 4 | 5 | First create an app id for your app 6 | https://developer.apple.com/account/ios/identifier/bundle 7 | 8 | https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app 9 | New App 10 | 11 | 12 | 13 |

14 | makenewapp 15 | newapp 16 | 17 |

18 | 19 | 20 | ### Create New Leaderboard 21 | 22 | 23 |

24 | gamecenter 25 | leaderboardsave 26 | leaderboardfinal 27 |

28 | ### Create New Achievements 29 | 30 |

31 | achivements3 32 | achivements4 33 | achivements5 34 | final 35 |

36 | 37 | 38 | ### In Xcode 39 | 40 | 41 | 42 |

43 | xcode 44 | xcode1 45 |

46 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-game-center", 3 | "version": "1.2.3", 4 | "description": "Apple's Game Center integration with React Native", 5 | "main": "RNGameCenter/index.js", 6 | "directories": { 7 | "lib": "lib" 8 | }, 9 | "scripts": { 10 | "commit": "git-cz", 11 | "test": "jest", 12 | "semantic-release": "semantic-release pre && npm publish && semantic-release post" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/garrettmac/react-native-game-center.git" 17 | }, 18 | "keywords": [ 19 | "react", 20 | "react-native", 21 | "react-native-component", 22 | "game-center", 23 | "game", 24 | "center", 25 | "native-module", 26 | "ios", 27 | "apple", 28 | "gamecenter" 29 | ], 30 | 31 | "author": "garrettmac (http://vyga.io)", 32 | "license": "MIT", 33 | "bugs": { 34 | "url": "https://github.com/garrettmac/react-native-game-center/issues" 35 | }, 36 | "config": { 37 | "commitizen": { 38 | "path": "node_modules/cz-conventional-changelog" 39 | } 40 | }, 41 | "homepage": "https://github.com/garrettmac/react-native-game-center#readme", 42 | "devDependencies": { 43 | "commitizen": "^2.9.6", 44 | "cz-conventional-changelog": "^2.0.0", 45 | "semantic-release": "^8.0.3", 46 | "react-native": "0.45.1", 47 | "react": "16.0.0-alpha.12", 48 | "jest": "20.0.4", 49 | "react-test-renderer": "^16.0.0-alpha.12" 50 | }, 51 | "jest": { 52 | "preset": "react-native" 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "AppDelegate.h" 11 | 12 | #import 13 | #import 14 | 15 | @implementation AppDelegate 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 18 | { 19 | NSURL *jsCodeLocation; 20 | 21 | jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil]; 22 | 23 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation 24 | moduleName:@"GameCenterExample" 25 | initialProperties:nil 26 | launchOptions:launchOptions]; 27 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 28 | 29 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 30 | UIViewController *rootViewController = [UIViewController new]; 31 | rootViewController.view = rootView; 32 | self.window.rootViewController = rootViewController; 33 | [self.window makeKeyAndVisible]; 34 | return YES; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /GameCenterExample/.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore unexpected extra "@providesModule" 9 | .*/node_modules/.*/node_modules/fbjs/.* 10 | 11 | ; Ignore duplicate module providers 12 | ; For RN Apps installed via npm, "Libraries" folder is inside 13 | ; "node_modules/react-native" but in the source repo it is in the root 14 | .*/Libraries/react-native/React.js 15 | .*/Libraries/react-native/ReactNative.js 16 | 17 | [include] 18 | 19 | [libs] 20 | node_modules/react-native/Libraries/react-native/react-native-interface.js 21 | node_modules/react-native/flow 22 | flow/ 23 | 24 | [options] 25 | emoji=true 26 | 27 | module.system=haste 28 | 29 | munge_underscores=true 30 | 31 | module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> 'RelativeImageStub' 32 | 33 | suppress_type=$FlowIssue 34 | suppress_type=$FlowFixMe 35 | suppress_type=$FixMe 36 | 37 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\) 38 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(>=0\\.\\(4[0-9]\\|[1-3][0-9]\\|[0-9]\\).[0-9]\\)? *\\(site=[a-z,_]*react_native[a-z,_]*\\)?)\\)?:? #[0-9]+ 39 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixedInNextDeploy 40 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 41 | 42 | unsafe.enable_getters_and_setters=true 43 | 44 | [version] 45 | ^0.49.1 46 | -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UIViewControllerBasedStatusBarAppearance 38 | 39 | NSLocationWhenInUseUsageDescription 40 | 41 | NSAppTransportSecurity 42 | 43 | 44 | NSExceptionDomains 45 | 46 | localhost 47 | 48 | NSExceptionAllowsInsecureHTTPLoads 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /RNGameCenter/README.md: -------------------------------------------------------------------------------- 1 | 2 | # react-native-game-center 3 | 4 | ## Getting started 5 | 6 | `$ npm install react-native-game-center --save` 7 | 8 | ### Mostly automatic installation 9 | 10 | `$ react-native link react-native-game-center` 11 | 12 | ### Manual installation 13 | 14 | 15 | #### iOS 16 | 17 | 1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]` 18 | 2. Go to `node_modules` ➜ `react-native-game-center` and add `RNGameCenter.xcodeproj` 19 | 3. In XCode, in the project navigator, select your project. Add `libRNGameCenter.a` to your project's `Build Phases` ➜ `Link Binary With Libraries` 20 | 4. Run your project (`Cmd+R`)< 21 | 22 | #### Android 23 | 24 | 1. Open up `android/app/src/main/java/[...]/MainActivity.java` 25 | - Add `import com.reactlibrary.RNGameCenterPackage;` to the imports at the top of the file 26 | - Add `new RNGameCenterPackage()` to the list returned by the `getPackages()` method 27 | 2. Append the following lines to `android/settings.gradle`: 28 | ``` 29 | include ':react-native-game-center' 30 | project(':react-native-game-center').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-game-center/android') 31 | ``` 32 | 3. Insert the following lines inside the dependencies block in `android/app/build.gradle`: 33 | ``` 34 | compile project(':react-native-game-center') 35 | ``` 36 | 37 | #### Windows 38 | [Read it! :D](https://github.com/ReactWindows/react-native) 39 | 40 | 1. In Visual Studio add the `RNGameCenter.sln` in `node_modules/react-native-game-center/windows/RNGameCenter.sln` folder to their solution, reference from their app. 41 | 2. Open up your `MainPage.cs` app 42 | - Add `using Game.Center.RNGameCenter;` to the usings at the top of the file 43 | - Add `new RNGameCenterPackage()` to the `List` returned by the `Packages` method 44 | 45 | 46 | ## Usage 47 | ```javascript 48 | import RNGameCenter from 'react-native-game-center'; 49 | 50 | // TODO: What to do with the module? 51 | RNGameCenter; 52 | ``` 53 | -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | GameCenterExample 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSExceptionDomains 30 | 31 | localhost 32 | 33 | NSExceptionAllowsInsecureHTTPLoads 34 | 35 | 36 | 37 | 38 | NSLocationWhenInUseUsageDescription 39 | 40 | UIAppFonts 41 | 42 | Entypo.ttf 43 | EvilIcons.ttf 44 | Feather.ttf 45 | FontAwesome.ttf 46 | Foundation.ttf 47 | Ionicons.ttf 48 | MaterialCommunityIcons.ttf 49 | MaterialIcons.ttf 50 | Octicons.ttf 51 | SimpleLineIcons.ttf 52 | Zocial.ttf 53 | 54 | UILaunchStoryboardName 55 | LaunchScreen 56 | UIRequiredDeviceCapabilities 57 | 58 | armv7 59 | gamekit 60 | 61 | UISupportedInterfaceOrientations 62 | 63 | UIInterfaceOrientationPortrait 64 | UIInterfaceOrientationLandscapeLeft 65 | UIInterfaceOrientationLandscapeRight 66 | 67 | UIViewControllerBasedStatusBarAppearance 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExampleTests/GameCenterExampleTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | #import 12 | 13 | #import 14 | #import 15 | 16 | #define TIMEOUT_SECONDS 600 17 | #define TEXT_TO_LOOK_FOR @"Welcome to React Native!" 18 | 19 | @interface GameCenterExampleTests : XCTestCase 20 | 21 | @end 22 | 23 | @implementation GameCenterExampleTests 24 | 25 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 26 | { 27 | if (test(view)) { 28 | return YES; 29 | } 30 | for (UIView *subview in [view subviews]) { 31 | if ([self findSubviewInView:subview matching:test]) { 32 | return YES; 33 | } 34 | } 35 | return NO; 36 | } 37 | 38 | - (void)testRendersWelcomeScreen 39 | { 40 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 41 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 42 | BOOL foundElement = NO; 43 | 44 | __block NSString *redboxError = nil; 45 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 46 | if (level >= RCTLogLevelError) { 47 | redboxError = message; 48 | } 49 | }); 50 | 51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 54 | 55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 57 | return YES; 58 | } 59 | return NO; 60 | }]; 61 | } 62 | 63 | RCTSetLogFunction(RCTDefaultLogFunction); 64 | 65 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 66 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 67 | } 68 | 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "iphone-20x20-2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "iphone-20x20-3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "iphone-29x29-1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "iphone-29x29-2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "iphone-29x29-3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "iphone-40x40-2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "iphone-40x40-3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "57x57", 47 | "idiom" : "iphone", 48 | "filename" : "iphone-57x57-1x.png", 49 | "scale" : "1x" 50 | }, 51 | { 52 | "size" : "57x57", 53 | "idiom" : "iphone", 54 | "filename" : "iphone-57x57-2x.png", 55 | "scale" : "2x" 56 | }, 57 | { 58 | "size" : "60x60", 59 | "idiom" : "iphone", 60 | "filename" : "iphone-60x60-2x.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "60x60", 65 | "idiom" : "iphone", 66 | "filename" : "iphone-60x60-3x.png", 67 | "scale" : "3x" 68 | }, 69 | { 70 | "size" : "20x20", 71 | "idiom" : "ipad", 72 | "filename" : "ipad-20x20-1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "20x20", 77 | "idiom" : "ipad", 78 | "filename" : "ipad-20x20-2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "29x29", 83 | "idiom" : "ipad", 84 | "filename" : "ipad-29x29-1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "29x29", 89 | "idiom" : "ipad", 90 | "filename" : "ipad-29x29-2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "40x40", 95 | "idiom" : "ipad", 96 | "filename" : "ipad-40x40-1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "40x40", 101 | "idiom" : "ipad", 102 | "filename" : "ipad-40x40-2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "50x50", 107 | "idiom" : "ipad", 108 | "filename" : "ipad-50x50-1x.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "50x50", 113 | "idiom" : "ipad", 114 | "filename" : "ipad-50x50-2x.png", 115 | "scale" : "2x" 116 | }, 117 | { 118 | "size" : "72x72", 119 | "idiom" : "ipad", 120 | "filename" : "ipad-72x72-1x.png", 121 | "scale" : "1x" 122 | }, 123 | { 124 | "size" : "72x72", 125 | "idiom" : "ipad", 126 | "filename" : "ipad-72x72-2x.png", 127 | "scale" : "2x" 128 | }, 129 | { 130 | "size" : "76x76", 131 | "idiom" : "ipad", 132 | "filename" : "ipad-76x76-1x.png", 133 | "scale" : "1x" 134 | }, 135 | { 136 | "size" : "76x76", 137 | "idiom" : "ipad", 138 | "filename" : "ipad-76x76-2x.png", 139 | "scale" : "2x" 140 | }, 141 | { 142 | "size" : "83.5x83.5", 143 | "idiom" : "ipad", 144 | "filename" : "ipad-83.5x83.5-2x.png", 145 | "scale" : "2x" 146 | }, 147 | { 148 | "idiom" : "ios-marketing", 149 | "size" : "1024x1024", 150 | "scale" : "1x" 151 | } 152 | ], 153 | "info" : { 154 | "version" : 1, 155 | "author" : "xcode" 156 | } 157 | } -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample.xcodeproj/xcshareddata/xcschemes/GameCenterExample.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /GameCenterExample/ios/GameCenterExample.xcodeproj/xcshareddata/xcschemes/GameCenterExample-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 43 | 49 | 50 | 51 | 52 | 53 | 58 | 59 | 61 | 67 | 68 | 69 | 70 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 92 | 94 | 100 | 101 | 102 | 103 | 104 | 105 | 111 | 113 | 119 | 120 | 121 | 122 | 124 | 125 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /RNGameCenter/index.js: -------------------------------------------------------------------------------- 1 | import { NativeModules } from 'react-native'; 2 | 3 | // const { RNGameCenter as ReactNativeGameCenter } = NativeModules; 4 | //standardizes the way options are validated 5 | const validateOptions = (options, requiredFields) => { 6 | requiredFields.forEach(field => { 7 | if (!options[field]) { 8 | throw new Error(`Missing '${field}' from options object`); 9 | } 10 | }); 11 | }; 12 | const RNGameCenter = { 13 | init: async (options) => { 14 | try { 15 | return await NativeModules.RNGameCenter.init(options); 16 | } catch (error) { 17 | console.error('Error initializing Game Center:', error); 18 | throw error; 19 | } 20 | }, 21 | 22 | userLogged:async () => { 23 | try { 24 | return await NativeModules.RNGameCenter.userLogged(); 25 | } catch (error) { 26 | console.error('Error checking user logged status:', error); 27 | throw error; 28 | } 29 | }, 30 | 31 | getPlayer:async () => { 32 | try { 33 | return await NativeModules.RNGameCenter.getPlayer(); 34 | } catch (error) { 35 | console.error('Error getting player:', error); 36 | throw error; 37 | } 38 | }, 39 | 40 | getPlayerFriends:async () => { 41 | try { 42 | return await NativeModules.RNGameCenter.getPlayerFriends(); 43 | } catch (error) { 44 | console.error('Error getting player friends:', error); 45 | throw error; 46 | } 47 | }, 48 | 49 | getPlayerImage:async () => { 50 | try { 51 | return await NativeModules.RNGameCenter.getPlayerImage(); 52 | } catch (error) { 53 | console.error('Error getting player image:', error); 54 | throw error; 55 | } 56 | }, 57 | 58 | // challengeWithScore:(options)=>{ 59 | // if(!options.score)throw "Missing 'score' from challengeWithScore object"; 60 | // return NativeModules.RNGameCenter.challengeWithScore(options.score,options) 61 | // }, 62 | // findScoresOfFriendsToChallenge:()=>{ 63 | // return NativeModules.RNGameCenter.findScoresOfFriendsToChallenge({}) 64 | // }, 65 | 66 | // https://developer.apple.com/documentation/gamekit/gkscore 67 | openLeaderboardModal:async (options) => { 68 | try { 69 | return await NativeModules.RNGameCenter.openLeaderboardModal(options); 70 | } catch (error) { 71 | console.error('Error opening leaderboard modal:', error); 72 | throw error; 73 | } 74 | }, 75 | submitLeaderboardScore: async (options) => { 76 | try { 77 | validateOptions(options, ['score']); 78 | return await NativeModules.RNGameCenter.submitLeaderboardScore(options.score, options); 79 | } catch (error) { 80 | console.error('Error submitting leaderboard score:', error); 81 | throw error; 82 | } 83 | }, 84 | 85 | // getLeaderboardPlayers:(options)=>{ 86 | // 87 | // //playerIds (Array) 88 | // if(!options.playerIds)throw "Missing 'playerIds' from getLeaderboardPlayers object"; 89 | // if(!Array.isArray(options.playerIds))throw "getLeaderboardPlayers's 'playerIds' paramenter should be an array"; 90 | // return NativeModules.RNGameCenter.getLeaderboardPlayers(options) 91 | // }, 92 | 93 | // https://developer.apple.com/documentation/gamekit/gkachievement 94 | openAchievementModal:async (options = {}) => { 95 | try { 96 | return await NativeModules.RNGameCenter.openAchievementModal(options); 97 | } catch (error) { 98 | console.error('Error opening achievement modal:', error); 99 | throw error; 100 | } 101 | }, 102 | 103 | getAchievements:async () => { 104 | try { 105 | return await NativeModules.RNGameCenter.getAchievements(); 106 | } catch (error) { 107 | console.error('Error getting achievements:', error); 108 | throw error; 109 | } 110 | }, 111 | 112 | resetAchievements:async (options = {}) => { 113 | try { 114 | return await NativeModules.RNGameCenter.resetAchievements(options); 115 | } catch (error) { 116 | console.error('Error resetting achievements:', error); 117 | throw error; 118 | } 119 | }, 120 | 121 | // entry[@"playerID"] = achievement.playerID; 122 | // [earntAchievements addObject:entry]; 123 | submitAchievementScore:async (options) => { 124 | try { 125 | validateOptions(options, ['percentComplete']); 126 | return await NativeModules.RNGameCenter.submitAchievementScore(options); 127 | } catch (error) { 128 | console.error('Error submitting achievement score:', error); 129 | throw error; 130 | } 131 | }, 132 | 133 | uploadSavedGameData:async (options) => { 134 | try { 135 | return await NativeModules.RNGameCenter.uploadSavedGameData(options); 136 | } catch (error) { 137 | console.error('Error uploading saved game data:', error); 138 | throw error; 139 | } 140 | }, 141 | 142 | loadSavedGameData: async (options) => { 143 | try { 144 | return await NativeModules.RNGameCenter.loadSavedGameData(options); 145 | } catch (error) { 146 | console.error('Error loading saved game data:', error); 147 | throw error; 148 | } 149 | }, 150 | }; 151 | 152 | 153 | export default RNGameCenter 154 | 155 | /* 156 | 157 | Reason behind not just returning 158 | _____________________ 159 | _____________________ 160 | ERROR OR BUG: 161 | where you have to pass the `int64_t` score value in the method header 162 | or it declares the score as the same -5,XXX,XXX,XXX,XXX,XXX,XXX value. 163 | 164 | NOTE: int64_t range is (-9,223,372,036,854,775,808 to +9,223,372,036,854,775,807) 165 | Example: 166 | _____________________ 167 | RCT_EXPORT_METHOD(submitLeaderboardScore:(int64_t)score 168 | _____________________ 169 | and connot declare inside like 170 | _____________________ 171 | int64_t scoreInt = (int64_t)options[@"score"]; 172 | _____________________ 173 | also tried all the following: 174 | _____________________ 175 | int score = [userScore intValue]; 176 | NSNumber *nsNum = options[@"score"]; 177 | int intValueNum = [options[@"score"] intValue]; 178 | int i = 1; 179 | int64_t scoreValue =(int64_t)i; 180 | int scoreValue =[options[@"score"] intValue]; 181 | float floatNum = options[@"score"]; 182 | int64 *sscore =[RCTConvert int64:options[@"score"]]; 183 | NSInteger i = 34; 184 | NSNumber* numpre = [options valueForKey:@"score"]; 185 | int scoreIn = (int)options[@"score"]; 186 | */ 187 | 188 | /* 189 | //TODO coming soon 190 | getLeaderboardPlayers(){ 191 | 192 | let options = {playerIds:[]}; 193 | 194 | _GameCenter.getLeaderboardPlayers(options) 195 | } 196 | 197 | invite(){ 198 | let options = {playerIds:[]}; 199 | _GameCenter.invite(options) 200 | } 201 | 202 | challengeComposer(){ 203 | 204 | let options = {score:this.state.score, 205 | message:"my message", 206 | players:["G:8135064222"], 207 | achievementIdentifier:"novice_award" 208 | }; 209 | 210 | _GameCenter.challengeComposer(options) 211 | .then(console.log) 212 | .catch(console.warn) 213 | } 214 | 215 | findScoresOfFriendsToChallenge(){ 216 | _GameCenter.findScoresOfFriendsToChallenge() 217 | .then(console.log) 218 | .catch(console.warn) 219 | } 220 | 221 | loadLeaderboardPlayers(){ 222 | _GameCenter.loadLeaderboardPlayers() 223 | .then(console.log) 224 | .catch(console.warn) 225 | } 226 | 227 | */ 228 | -------------------------------------------------------------------------------- /RNGameCenter/ios/RNGameCenter.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0E69341B1F78A02C00C9C9B8 /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E69341A1F78A02C00C9C9B8 /* GameKit.framework */; }; 11 | B3E7B58A1CC2AC0600A0062D /* RNGameCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNGameCenter.m */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | 58B511D91A9E6C8500147676 /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = "include/$(PRODUCT_NAME)"; 19 | dstSubfolderSpec = 16; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 0; 23 | }; 24 | /* End PBXCopyFilesBuildPhase section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 0E69341A1F78A02C00C9C9B8 /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; }; 28 | 134814201AA4EA6300B7C361 /* libRNGameCenter.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNGameCenter.a; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | B3E7B5881CC2AC0600A0062D /* RNGameCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNGameCenter.h; sourceTree = ""; }; 30 | B3E7B5891CC2AC0600A0062D /* RNGameCenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNGameCenter.m; sourceTree = ""; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | 58B511D81A9E6C8500147676 /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | 0E69341B1F78A02C00C9C9B8 /* GameKit.framework in Frameworks */, 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | 0E6934191F78A02C00C9C9B8 /* Frameworks */ = { 46 | isa = PBXGroup; 47 | children = ( 48 | 0E69341A1F78A02C00C9C9B8 /* GameKit.framework */, 49 | ); 50 | name = Frameworks; 51 | sourceTree = ""; 52 | }; 53 | 134814211AA4EA7D00B7C361 /* Products */ = { 54 | isa = PBXGroup; 55 | children = ( 56 | 134814201AA4EA6300B7C361 /* libRNGameCenter.a */, 57 | ); 58 | name = Products; 59 | sourceTree = ""; 60 | }; 61 | 58B511D21A9E6C8500147676 = { 62 | isa = PBXGroup; 63 | children = ( 64 | B3E7B5881CC2AC0600A0062D /* RNGameCenter.h */, 65 | B3E7B5891CC2AC0600A0062D /* RNGameCenter.m */, 66 | 134814211AA4EA7D00B7C361 /* Products */, 67 | 0E6934191F78A02C00C9C9B8 /* Frameworks */, 68 | ); 69 | sourceTree = ""; 70 | }; 71 | /* End PBXGroup section */ 72 | 73 | /* Begin PBXNativeTarget section */ 74 | 58B511DA1A9E6C8500147676 /* RNGameCenter */ = { 75 | isa = PBXNativeTarget; 76 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNGameCenter" */; 77 | buildPhases = ( 78 | 58B511D71A9E6C8500147676 /* Sources */, 79 | 58B511D81A9E6C8500147676 /* Frameworks */, 80 | 58B511D91A9E6C8500147676 /* CopyFiles */, 81 | ); 82 | buildRules = ( 83 | ); 84 | dependencies = ( 85 | ); 86 | name = RNGameCenter; 87 | productName = RCTDataManager; 88 | productReference = 134814201AA4EA6300B7C361 /* libRNGameCenter.a */; 89 | productType = "com.apple.product-type.library.static"; 90 | }; 91 | /* End PBXNativeTarget section */ 92 | 93 | /* Begin PBXProject section */ 94 | 58B511D31A9E6C8500147676 /* Project object */ = { 95 | isa = PBXProject; 96 | attributes = { 97 | LastUpgradeCheck = 0830; 98 | ORGANIZATIONNAME = Facebook; 99 | TargetAttributes = { 100 | 58B511DA1A9E6C8500147676 = { 101 | CreatedOnToolsVersion = 6.1.1; 102 | }; 103 | }; 104 | }; 105 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNGameCenter" */; 106 | compatibilityVersion = "Xcode 3.2"; 107 | developmentRegion = English; 108 | hasScannedForEncodings = 0; 109 | knownRegions = ( 110 | en, 111 | ); 112 | mainGroup = 58B511D21A9E6C8500147676; 113 | productRefGroup = 58B511D21A9E6C8500147676; 114 | projectDirPath = ""; 115 | projectRoot = ""; 116 | targets = ( 117 | 58B511DA1A9E6C8500147676 /* RNGameCenter */, 118 | ); 119 | }; 120 | /* End PBXProject section */ 121 | 122 | /* Begin PBXSourcesBuildPhase section */ 123 | 58B511D71A9E6C8500147676 /* Sources */ = { 124 | isa = PBXSourcesBuildPhase; 125 | buildActionMask = 2147483647; 126 | files = ( 127 | B3E7B58A1CC2AC0600A0062D /* RNGameCenter.m in Sources */, 128 | ); 129 | runOnlyForDeploymentPostprocessing = 0; 130 | }; 131 | /* End PBXSourcesBuildPhase section */ 132 | 133 | /* Begin XCBuildConfiguration section */ 134 | 58B511ED1A9E6C8500147676 /* Debug */ = { 135 | isa = XCBuildConfiguration; 136 | buildSettings = { 137 | ALWAYS_SEARCH_USER_PATHS = NO; 138 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 139 | CLANG_CXX_LIBRARY = "libc++"; 140 | CLANG_ENABLE_MODULES = YES; 141 | CLANG_ENABLE_OBJC_ARC = YES; 142 | CLANG_WARN_BOOL_CONVERSION = YES; 143 | CLANG_WARN_CONSTANT_CONVERSION = YES; 144 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 145 | CLANG_WARN_EMPTY_BODY = YES; 146 | CLANG_WARN_ENUM_CONVERSION = YES; 147 | CLANG_WARN_INFINITE_RECURSION = YES; 148 | CLANG_WARN_INT_CONVERSION = YES; 149 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 150 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 151 | CLANG_WARN_UNREACHABLE_CODE = YES; 152 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 153 | COPY_PHASE_STRIP = NO; 154 | ENABLE_STRICT_OBJC_MSGSEND = YES; 155 | ENABLE_TESTABILITY = YES; 156 | GCC_C_LANGUAGE_STANDARD = gnu99; 157 | GCC_DYNAMIC_NO_PIC = NO; 158 | GCC_NO_COMMON_BLOCKS = YES; 159 | GCC_OPTIMIZATION_LEVEL = 0; 160 | GCC_PREPROCESSOR_DEFINITIONS = ( 161 | "DEBUG=1", 162 | "$(inherited)", 163 | ); 164 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 165 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 166 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 167 | GCC_WARN_UNDECLARED_SELECTOR = YES; 168 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 169 | GCC_WARN_UNUSED_FUNCTION = YES; 170 | GCC_WARN_UNUSED_VARIABLE = YES; 171 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 172 | MTL_ENABLE_DEBUG_INFO = YES; 173 | ONLY_ACTIVE_ARCH = YES; 174 | SDKROOT = iphoneos; 175 | }; 176 | name = Debug; 177 | }; 178 | 58B511EE1A9E6C8500147676 /* Release */ = { 179 | isa = XCBuildConfiguration; 180 | buildSettings = { 181 | ALWAYS_SEARCH_USER_PATHS = NO; 182 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 183 | CLANG_CXX_LIBRARY = "libc++"; 184 | CLANG_ENABLE_MODULES = YES; 185 | CLANG_ENABLE_OBJC_ARC = YES; 186 | CLANG_WARN_BOOL_CONVERSION = YES; 187 | CLANG_WARN_CONSTANT_CONVERSION = YES; 188 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 189 | CLANG_WARN_EMPTY_BODY = YES; 190 | CLANG_WARN_ENUM_CONVERSION = YES; 191 | CLANG_WARN_INFINITE_RECURSION = YES; 192 | CLANG_WARN_INT_CONVERSION = YES; 193 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 194 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 195 | CLANG_WARN_UNREACHABLE_CODE = YES; 196 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 197 | COPY_PHASE_STRIP = YES; 198 | ENABLE_NS_ASSERTIONS = NO; 199 | ENABLE_STRICT_OBJC_MSGSEND = YES; 200 | GCC_C_LANGUAGE_STANDARD = gnu99; 201 | GCC_NO_COMMON_BLOCKS = YES; 202 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 203 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 204 | GCC_WARN_UNDECLARED_SELECTOR = YES; 205 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 206 | GCC_WARN_UNUSED_FUNCTION = YES; 207 | GCC_WARN_UNUSED_VARIABLE = YES; 208 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 209 | MTL_ENABLE_DEBUG_INFO = NO; 210 | SDKROOT = iphoneos; 211 | VALIDATE_PRODUCT = YES; 212 | }; 213 | name = Release; 214 | }; 215 | 58B511F01A9E6C8500147676 /* Debug */ = { 216 | isa = XCBuildConfiguration; 217 | buildSettings = { 218 | HEADER_SEARCH_PATHS = ( 219 | "$(inherited)", 220 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 221 | "$(SRCROOT)/../../../React/**", 222 | "$(SRCROOT)/../../react-native/React/**", 223 | ); 224 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 225 | OTHER_LDFLAGS = "-ObjC"; 226 | PRODUCT_NAME = RNGameCenter; 227 | SKIP_INSTALL = YES; 228 | }; 229 | name = Debug; 230 | }; 231 | 58B511F11A9E6C8500147676 /* Release */ = { 232 | isa = XCBuildConfiguration; 233 | buildSettings = { 234 | HEADER_SEARCH_PATHS = ( 235 | "$(inherited)", 236 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 237 | "$(SRCROOT)/../../../React/**", 238 | "$(SRCROOT)/../../react-native/React/**", 239 | ); 240 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 241 | OTHER_LDFLAGS = "-ObjC"; 242 | PRODUCT_NAME = RNGameCenter; 243 | SKIP_INSTALL = YES; 244 | }; 245 | name = Release; 246 | }; 247 | /* End XCBuildConfiguration section */ 248 | 249 | /* Begin XCConfigurationList section */ 250 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNGameCenter" */ = { 251 | isa = XCConfigurationList; 252 | buildConfigurations = ( 253 | 58B511ED1A9E6C8500147676 /* Debug */, 254 | 58B511EE1A9E6C8500147676 /* Release */, 255 | ); 256 | defaultConfigurationIsVisible = 0; 257 | defaultConfigurationName = Release; 258 | }; 259 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNGameCenter" */ = { 260 | isa = XCConfigurationList; 261 | buildConfigurations = ( 262 | 58B511F01A9E6C8500147676 /* Debug */, 263 | 58B511F11A9E6C8500147676 /* Release */, 264 | ); 265 | defaultConfigurationIsVisible = 0; 266 | defaultConfigurationName = Release; 267 | }; 268 | /* End XCConfigurationList section */ 269 | }; 270 | rootObject = 58B511D31A9E6C8500147676 /* Project object */; 271 | } 272 | -------------------------------------------------------------------------------- /GameCenterExample/index.ios.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample React Native App 3 | * https://github.com/facebook/react-native 4 | * @flow 5 | */ 6 | 7 | import React, { Component } from 'react'; 8 | import { 9 | AppRegistry, 10 | StyleSheet, 11 | NativeModules, 12 | TouchableOpacity,Dimensions, 13 | Text, 14 | View 15 | } from 'react-native'; 16 | 17 | 18 | import RNGameCenter from 'react-native-game-center'; 19 | const leaderboardIdentifier="high_scores" 20 | // const achievementIdentifier="pro_award" 21 | const achievementIdentifier="novice_award" 22 | 23 | // 24 | import Icon from 'react-native-vector-icons/MaterialCommunityIcons' 25 | const {width, height} = Dimensions.get('window'); 26 | 27 | 28 | 29 | 30 | export default class GameCenterExample extends Component { 31 | constructor(props) { 32 | super(props); 33 | this.state = { 34 | score: 5 35 | }; 36 | this.getPlayer = this.getPlayer.bind(this) 37 | this.getPlayerFriends = this.getPlayerFriends.bind(this) 38 | 39 | this.openLeaderboardModal = this.openLeaderboardModal.bind(this) 40 | this.submitLeaderboardScore = this.submitLeaderboardScore.bind(this) 41 | 42 | this.openAchievementModal = this.openAchievementModal.bind(this) 43 | this.getAchievements = this.getAchievements.bind(this) 44 | this.resetAchievements = this.resetAchievements.bind(this) 45 | this.submitAchievementScore = this.submitAchievementScore.bind(this) 46 | 47 | this.incrementScore = this.incrementScore.bind(this) 48 | this.decrementScore = this.decrementScore.bind(this) 49 | } 50 | componentDidMount() { 51 | 52 | //sets default leaderboardIdentifier 53 | RNGameCenter.init({leaderboardIdentifier}) 54 | .then(console.log) 55 | .catch(console.warn) 56 | 57 | RNGameCenter.submitAchievementScore({percentComplete:50,achievementIdentifier:"novice_award"}) 58 | //RNGameCenter.submitAchievementScore({percentComplete:"10",achievementIdentifier:"pro_award",hideCompletionBanner:true}) 59 | 60 | } 61 | incrementScore() { 62 | this.setState({ 63 | score: this.state.score + 1 64 | }) 65 | } 66 | decrementScore() { 67 | this.setState({ 68 | score: this.state.score + 1 69 | }) 70 | } 71 | 72 | 73 | getPlayer() { 74 | RNGameCenter.getPlayer() 75 | .then(console.log) 76 | .catch(console.warn) 77 | 78 | } 79 | getPlayerFriends() { 80 | RNGameCenter.getPlayerFriends() 81 | .then(console.log) 82 | .catch(console.warn) 83 | 84 | } 85 | 86 | // NOT SET UP 87 | getPlayerImage() { 88 | RNGameCenter.getPlayerImage() 89 | .then(console.log) 90 | .catch(console.warn) 91 | 92 | } 93 | 94 | openLeaderboardModal() { 95 | RNGameCenter.openLeaderboardModal({ 96 | leaderboardIdentifier 97 | }) 98 | .then(console.log) 99 | .catch(console.warn) 100 | } 101 | 102 | submitLeaderboardScore(score =30) { 103 | RNGameCenter.submitLeaderboardScore({ 104 | score, 105 | leaderboardIdentifier 106 | }) 107 | .then(console.log) 108 | .catch(console.warn) 109 | } 110 | 111 | 112 | 113 | 114 | openAchievementModal() { 115 | 116 | let options = { 117 | showsCompletionBanner: true, 118 | percentComplete: 100, 119 | achievementIdentifier 120 | }; 121 | 122 | RNGameCenter.openAchievementModal(options) 123 | .then(console.log) 124 | .catch(console.warn) 125 | } 126 | 127 | 128 | getAchievements() { 129 | RNGameCenter.getAchievements() 130 | .then(JSON.stringify(console.log)) 131 | .catch(console.warn) 132 | 133 | } 134 | 135 | submitAchievementScore(percentComplete=100,showsCompletionBanner=true) { 136 | // NativeModules.RNGameCenter.reportAchievement({ 137 | 138 | RNGameCenter.submitAchievementScore({ 139 | // percentComplete, 140 | percentComplete:100, 141 | achievementIdentifier, 142 | // hideCompletionBanner:true, 143 | }) 144 | .then(console.log) 145 | .catch(console.warn) 146 | } 147 | 148 | 149 | resetAchievements() { 150 | RNGameCenter.resetAchievements() 151 | .then(console.log) 152 | .catch(console.warn) 153 | } 154 | 155 | 156 | 157 | render() { 158 | const { 159 | score 160 | } = this.state 161 | RNGameCenter.getPlayerFriends().then((o)=>{ 162 | console.log("getPlayerFriends",o) 163 | }) 164 | RNGameCenter.getPlayerImage().then((o)=>{ 165 | console.log("getPlayerImage",o) 166 | }) 167 | return( 168 | 169 | 170 | React Native Game Center 171 | 172 | 173 | 174 | {/* Heading Title */} 175 | 176 | Leaderboard 177 | Leaderboard Buttons 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | Score: {score} 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | open Leaderboard Modal 210 | 211 | this.submitLeaderboardScore(this.state.score)} style={[s.columnItem,s.center,s.button,{backgroundColor:"#32db64"}]}> 212 | submit Leaderboard Score 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | {/* Heading Title */} 221 | 222 | Player 223 | Player Buttons 224 | 225 | 226 | 227 | 228 | 229 | 230 | get player 231 | 232 | 233 | 234 | get Player Friends 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | {/* Heading Title */} 246 | 247 | Achievements 248 | Achievements Buttons 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | open AchievementModal 259 | 260 | 261 | 262 | get Achievements 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | submit Achievement Score 273 | 274 | 275 | 276 | reset Achievements 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | ); 288 | } 289 | } 290 | 291 | 292 | 293 | 294 | 295 | // RNGameCenter.init({leaderboardIdentifier}) 296 | AppRegistry.registerComponent('GameCenterExample', () => GameCenterExample); 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | let BUTTON_ROW_NUM_OF_BUTTONS = 3 306 | let BUTTON_ROW_HEIGHT = 50 307 | let BUTTON_HEIGHT = 50 308 | const s = StyleSheet.create({ 309 | container: { 310 | flex: 1, 311 | // justifyContent: 'center', 312 | // alignItems: 'center', 313 | backgroundColor: '#F5FCFF', 314 | }, 315 | headingText: { 316 | fontSize: 25, 317 | marginBottom:40, 318 | fontWeight: "900", 319 | textAlign: 'center', 320 | 321 | }, 322 | scoreText: { 323 | fontSize: 20, 324 | fontWeight: "900", 325 | textAlign: 'center', 326 | 327 | }, 328 | rowTitleContainer: { 329 | flexDirection: 'row', 330 | }, 331 | titleText: { 332 | fontWeight: "800" 333 | }, 334 | instructions: { 335 | textAlign: 'center', 336 | color: '#333333', 337 | marginBottom: 5, 338 | }, 339 | button: { 340 | borderWidth: 1, 341 | margin: 5, 342 | // padding: 15, 343 | paddingLeft: 5, 344 | paddingRight: 5, 345 | borderColor: "white", 346 | backgroundColor:"#488aff", 347 | borderRadius: 5, 348 | }, 349 | centerItem: { 350 | borderRadius:25, 351 | borderWidth:4, 352 | borderColor:"rgba(0,0,0,0.2)", 353 | justifyContent: "center", 354 | alignItems: "center", 355 | borderRadius:25, 356 | height:50, 357 | width:50, 358 | backgroundColor:"red", 359 | }, 360 | margin10: { 361 | margin: 10, 362 | }, 363 | rowContainer: { 364 | flexDirection: 'row', 365 | height: BUTTON_ROW_HEIGHT, 366 | }, 367 | spaceAround: { 368 | justifyContent: 'space-around', 369 | alignItems: 'center', 370 | }, 371 | 372 | center:{justifyContent:"center",alignItems:"center",}, 373 | spaceBetween: { 374 | justifyContent: 'space-between', 375 | alignItems: 'center', 376 | }, 377 | rowItem: { 378 | backgroundColor: "transparent", 379 | width: width / BUTTON_ROW_NUM_OF_BUTTONS - 20, 380 | height: BUTTON_HEIGHT, 381 | borderRadius: 5, 382 | }, 383 | rowItemBorder: { 384 | borderWidth: 0.8, 385 | borderColor: "rgba(0,0,0,0.1)" 386 | }, 387 | textStyle:{color:"rgba(255,255,255,1)", textAlignVertical: "center", fontWeight:"700",textAlign: "center"}, 388 | 389 | viewShadow: { 390 | shadowOpacity: 1, 391 | shadowOffset: { 392 | width: 0, 393 | height: 5 394 | }, 395 | shadowRadius: 4, 396 | shadowColor: "rgba(0,0,0,0.6)", 397 | }, 398 | 399 | headerComponentTouchableIcon:{margin: 5,}, 400 | headerComponentSubheading:{fontSize: 17,color: '#444',margin: 5,fontWeight: '400'}, 401 | headerComponentTitleContainer:{}, 402 | headerComponentTitleTextStyle:{fontSize: 35,color: '#444',margin: 5,fontWeight: '700'}, 403 | lineDivider:{width: 50,borderBottomWidth: 1,borderColor: '#e3e3e3',margin: 5}, 404 | columnContainer:{flex: 1,flexDirection: 'row', 405 | justifyContent: 'center', 406 | justifyContent: 'space-between', 407 | justifyContent: 'space-around', 408 | maxHeight:50, 409 | alignItems: 'center',}, 410 | columnItem:{width:width/2-20, height: 50}, 411 | 412 | }); 413 | 414 | /* 415 | //TODO coming soon 416 | getLeaderboardPlayers(){ 417 | 418 | let options = {playerIds:[]}; 419 | 420 | _GameCenter.getLeaderboardPlayers(options) 421 | } 422 | 423 | 424 | 425 | invite(){ 426 | let options = {playerIds:[]}; 427 | _GameCenter.invite(options) 428 | } 429 | 430 | challengeComposer(){ 431 | 432 | let options = {score:this.state.score, 433 | message:"my message", 434 | players:["G:8135064222"], 435 | achievementIdentifier:"novice_award" 436 | }; 437 | 438 | _GameCenter.challengeComposer(options) 439 | .then(console.log) 440 | .catch(console.warn) 441 | } 442 | 443 | 444 | 445 | findScoresOfFriendsToChallenge(){ 446 | _GameCenter.findScoresOfFriendsToChallenge() 447 | .then(console.log) 448 | .catch(console.warn) 449 | } 450 | 451 | loadLeaderboardPlayers(){ 452 | _GameCenter.loadLeaderboardPlayers() 453 | .then(console.log) 454 | .catch(console.warn) 455 | } 456 | 457 | 458 | 459 | */ 460 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

react-native-game-center

Meet react-native-game-center

npm versionnpm versionPR StatsIssue Stats Join the chat

2 | 3 | # React Native Game Center 4 | hire me! 5 |

6 | app 7 | achivements 8 | leaderboard 9 | ifnotloggedin 10 | 11 |

12 | 13 | # Contents 14 | 15 | - [React Native Game Center](#react-native-game-center) 16 | * [Contents](#contents) 17 | * [Getting Started](#getting-started) 18 | * [Basic Usage](#basic-usage) 19 | * [Installation](#installation) 20 | * [Set Up](#set-up) 21 | - [Example](#example) 22 | - [Methods](#methods) 23 | - [Init Method](#init-method) 24 | * [init()](#init----promise--) 25 | - [Player Methods](#player-methods) 26 | * [getPlayer()](#getplayer--promise--) 27 | * [getPlayerImage()](#getplayerimage--promise--) 28 | * [getPlayerFriends()](#getplayerfriends--promise--) 29 | - [Leaderboard Methods](#leaderboard-methods) 30 | * [openLeaderboardModal()](#openleaderboardmodal--promise--) 31 | * [submitLeaderboardScore()](#submitleaderboardscore--promise--) 32 | - [Achievements Methods](#achievements-methods) 33 | * [openAchievementModal()](#openachievementmodal--promise--) 34 | * [getAchievements()](#getachievements--promise--) 35 | * [resetAchievements()](#resetachievements--promise--) 36 | * [submitAchievementScore()](#submitachievementscore--promise--) 37 | 38 | - [TODO](#todo) 39 | 40 | # Getting Started 41 | 42 | - Install `react-native` first 43 | 44 | ```bash 45 | npm i react-native -g 46 | react-native init myApp 47 | cd myApp 48 | yarn add react-native-game-center 49 | react-native link 50 | react-native run-ios 51 | ``` 52 | 53 | # Basic Usage 54 | 55 | - In your `index.js`, use: 56 | ```bash 57 | import RNGameCenter from "react-native-game-center" 58 | 59 | RNGameCenter.getPlayer().then(player=>console.log("player: ",player)) 60 | ``` 61 | 62 | 63 | # Installation 64 | 65 | - From project root 66 | 67 | ```bash 68 | yarn add react-native-game-center 69 | react-native link 70 | react-native run-ios 71 | ``` 72 | then **Follow setup Instructions** 73 | 74 | # Set Up 75 | > See [SETUP.md](SETUP.md) 76 | 77 | 78 | # Example 79 | 80 | or clone the repo and play with the example project 81 | 82 | ```bash 83 | $ git clone https://github.com/garrettmac/react-native-game-center 84 | $ cd react-native-game-center/GameCenterExample 85 | $ yarn install 86 | $ npm start 87 | ``` 88 | 89 | 90 | 91 | 92 | 93 | # Init Method 94 | 95 | * [init() ](#init----promise--) 96 | - [Details](#details) 97 | - [Parameters](#parameters) 98 | - [Usage](#usage) 99 | 100 | ## init() 101 | 102 | #### Details 103 | 104 | Initiates your app with Game Center. 105 | Add this to the top of your app before your `AppRegister`. 106 | 107 | 108 | **ITUNES CONNECT APP DASHBOARD** 109 | > https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/ra/ng/app 110 | 111 | **Then** 112 | > SELECT APP > Feature > Game Center 113 | 114 | #### Parameters 115 | 116 | | Name | Required | Default | Description | 117 | |--------------|--------------|--------------|--------------| 118 | | leaderboardIdentifier | Yes | `undefined` | Your apps default leaderboard Identifier. You can can several of these but at least one is required. | 119 | | achievementIdentifier | No | `undefined` | Your apps default achievement Identifier. Not required. Set this to avoid having to keep passing it in. | 120 | 121 | 122 | #### Usage 123 | 124 | **Basic** 125 | 126 | ```jsx 127 | const leaderboardIdentifier="high_scores" 128 | 129 | GameCenter.init({leaderboardIdentifier}) 130 | ``` 131 | 132 | **Advanced** 133 | 134 | ```jsx 135 | const leaderboardIdentifier="high_scores" 136 | const achievementIdentifier="novice_award" 137 | 138 | 139 | //init app 140 | GameCenter.init({leaderboardIdentifier,achievementIdentifier}) 141 | .then(console.log) 142 | .catch(console.warn) 143 | 144 | ``` 145 | 146 | 147 | 148 | 149 | 150 | 151 | # Player Methods 152 | 153 | [Player Methods](#player-methods) 154 | * [getPlayer ](#getplayer--promise--) 155 | - [Details](#details-1) 156 | - [Parameters](#parameters-1) 157 | - [Basic Usage](#basic-usage-1) 158 | - [Response](#response) 159 | * [getPlayerImage ](#getplayerimage--promise--) 160 | - [Details](#details-2) 161 | - [Parameters](#parameters-2) 162 | - [Usage](#usage-1) 163 | - [Success Response](#success-response) 164 | - [Failed Response](#failed-response) 165 | + [getPlayerFriends](#getplayerfriends) 166 | - [Details](#details-3) 167 | - [Parameters](#parameters-3) 168 | - [Usage](#usage-2) 169 | - [Response](#response-1) 170 | 171 | ## getPlayer 172 | 173 | #### Details 174 | 175 | Gets logged in user. 176 | 177 | #### Parameters 178 | 179 | No Parameters 180 | 181 | #### Basic Usage 182 | 183 | ```jsx 184 | GameCenter.getPlayer().then(player=>{ 185 | console.log("player: ", player); 186 | }) 187 | ``` 188 | 189 | #### Response 190 | 191 | ```json 192 | {alias: "Garrettmacmac", displayName: "Me", playerID: "G:8135064222"} 193 | ``` 194 | 195 | 196 | 197 | 198 | ## getPlayerImage 199 | 200 | 201 | #### Details 202 | 203 | Gets logged player image if available. 204 | Most players don't have one. 205 | 206 | #### Parameters 207 | 208 | No Parameters 209 | 210 | #### Usage 211 | 212 | ```jsx 213 | GameCenter.getPlayerImage().then(image=>{ 214 | console.log("image: ", image); 215 | }) 216 | ``` 217 | #### Success Response 218 | 219 | ```json 220 | {image: "/path/to/image.png"} 221 | ``` 222 | #### Failed Response 223 | 224 | ```json 225 | Error fetching player image 226 | ``` 227 | 228 | 229 | ### getPlayerFriends 230 | 231 | #### Details 232 | 233 | Gets a list of players. 234 | Most games don't have this anymore as Apple took away the game center App. 235 | Now you see lots of users connect via Facebook, SMS and by geolocation. 236 | 237 | #### Parameters 238 | 239 | No Parameters 240 | 241 | #### Usage 242 | 243 | ```jsx 244 | GameCenter.getPlayerFriends().then(friends=>{ 245 | console.log("friends: ", friends); 246 | }) 247 | ``` 248 | 249 | #### Response 250 | I don't know what this looks like, as I don't have friends 😫 and Apple said they are depreciating support for this is new versions. 251 | 252 | **Success** 253 | ```json 254 | [...array of friends] 255 | ``` 256 | or 257 | 258 | ```json 259 | undefined 260 | ``` 261 | 262 | **Failed** 263 | 264 | ```json 265 | Error fetching player friends 266 | ``` 267 | 268 | 269 | 270 | 271 | 272 | # Leaderboard Methods 273 | 274 | 275 | - [Leaderboard Methods](#leaderboard-methods) 276 | * [openLeaderboardModal ](#openleaderboardmodal--promise--) 277 | - [Details](#details-4) 278 | - [Parameters](#parameters-4) 279 | - [Usage](#usage-3) 280 | - [Success Response](#success-response-1) 281 | - [Failed Response](#failed-response-1) 282 | * [submitLeaderboardScore ](#submitleaderboardscore--promise--) 283 | - [Details](#details-5) 284 | - [Parameters](#parameters-5) 285 | - [Usage](#usage-4) 286 | - [Response](#response-2) 287 | 288 | 289 | 290 | ## openLeaderboardModal 291 | 292 | #### Details 293 | 294 | Opens Game Center Modal on Leaderboard Page 295 | 296 | #### Parameters 297 | 298 | No Parameters 299 | 300 | #### Usage 301 | 302 | ```jsx 303 | GameCenter.openLeaderboardModal() 304 | .then(success=>{})//is open 305 | .catch(error=>{})//could not open 306 | 307 | ``` 308 | 309 | #### Success Response 310 | 311 | ```json 312 | opened leaderboard modal 313 | ``` 314 | #### Failed Response 315 | 316 | ```json 317 | opened leaderboard modal 318 | ``` 319 | 320 | 321 | 322 | ## submitLeaderboardScore 323 | 324 | #### Details 325 | Submit progress of users leaderboard 326 | 327 | #### Parameters 328 | 329 | | Name | Required | Default | Description | 330 | |--------------|--------------|--------------|--------------| 331 | | score | Yes | n/a | some number to track for leaderboard | 332 | | leaderboarIdentifier | No* (see Response) | `leaderboarIdentifier` set up in Itunes Connect | 333 | 334 | 335 | #### Usage 336 | 337 | 338 | 339 | 340 | **Basic** 341 | 342 | ```jsx 343 | let options={score:50}; 344 | 345 | //reverts to default leaderboarIdentifier set up in init() 346 | GameCenter.submitLeaderboardScore(options) 347 | //now update state 348 | this.setState(options) 349 | ``` 350 | 351 | **Advanced** 352 | ```jsx 353 | let options={ 354 | score:50, 355 | leaderboarIdentifier:"some_other_leaderboard" 356 | }; 357 | 358 | GameCenter.submitLeaderboardScore(options) 359 | .then(res=>{ 360 | if(res==="Successfully submitted score") 361 | this.setState({score:50}) 362 | }) 363 | .catch(console.warn("Users progress is not being tracked due to error.")) 364 | 365 | ``` 366 | 367 | 368 | #### Response 369 | 370 | **Success** 371 | 372 | ```json 373 | "Successfully submitted score" 374 | ``` 375 | 376 | 377 | **Failed** 378 | 379 | ```json 380 | "Error submitting score." 381 | ``` 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | # Achievements Methods 390 | 391 | - [Achievements Methods](#achievements-methods) 392 | * [openAchievementModal ](#openachievementmodal--promise--) 393 | - [Details](#details-6) 394 | - [Parameters](#parameters-6) 395 | - [Usage](#usage-5) 396 | - [Response](#response-3) 397 | * [getAchievements ](#getachievements--promise--) 398 | - [Details](#details-7) 399 | - [Parameters](#parameters-7) 400 | - [Usage](#usage-6) 401 | - [Response](#response-4) 402 | * [resetAchievements ](#resetachievements--promise--) 403 | - [Details](#details-8) 404 | - [Parameters](#parameters-8) 405 | - [Usage](#usage-7) 406 | - [Response](#response-5) 407 | * [submitAchievementScore ](#submitachievementscore--promise--) 408 | - [Details](#details-9) 409 | - [Parameters](#parameters-9) 410 | - [Usage](#usage-8) 411 | - [Response](#response-6) 412 | 413 | ## openAchievementModal 414 | 415 | #### Details 416 | 417 | Opens Game Center Modal on Leaderboard Page 418 | 419 | #### Parameters 420 | 421 | No Parameters 422 | 423 | #### Usage 424 | 425 | ```jsx 426 | GameCenter.openAchievementModal() 427 | .then(success=>{})//is open 428 | .catch(error=>{})//could not open 429 | 430 | ``` 431 | 432 | #### Response 433 | 434 | **Success** 435 | 436 | ```json 437 | opened achievement modal 438 | ``` 439 | 440 | **Failed** 441 | 442 | ```json 443 | opened achievement modal 444 | ``` 445 | 446 | 447 | 448 | ## getAchievements 449 | 450 | #### Details 451 | 452 | Gets players achievements if completed more than 0%. 453 | You must declare `submitAchievementScore` at least once before calling this. 454 | 455 | #### Parameters 456 | 457 | No Parameters 458 | 459 | #### Usage 460 | 461 | ```jsx 462 | GameCenter.getAchievements() 463 | .then(achievements=>{ 464 | console.log(achievements) 465 | }) 466 | .catch(error=>{})//failed 467 | 468 | ``` 469 | 470 | #### Response 471 | 472 | ```json 473 | [{"showsCompletionBanner":false,"lastReportedDate":1506301241432,"completed":true,"percentComplete":100,"identifier":"novice_award"},{"showsCompletionBanner":false,"lastReportedDate":1506301211362,"completed":false,"percentComplete":5,"identifier":"pro_award"}] 474 | ``` 475 | 476 | or 477 | 478 | ```json 479 | [] 480 | ``` 481 | 482 | 483 | 484 | ## resetAchievements 485 | 486 | > [![Reset Achievements](snapshots/resetAchievements.png)] 487 | 488 | #### Details 489 | 490 | Resets the players achievements. 491 | 492 | #### Parameters 493 | 494 | 495 | | Name | Required | Default | Description | 496 | |--------------|--------------|--------------|--------------| 497 | | hideAlert | No | `{hideAlert:false}` | Hide reset confirmation prompt | 498 | 499 | 500 | #### Usage 501 | 502 | **Basic** 503 | 504 | ```jsx 505 | //Triggers confirmation prompt 506 | GameCenter.resetAchievements() 507 | 508 | // hides confirmation prompt 509 | GameCenter.resetAchievements({hideAlert:true}) 510 | ``` 511 | **Advanced** 512 | ```jsx 513 | GameCenter.resetAchievements(res=>{ 514 | if(res.resetAchievements){ 515 | do something if user reset achievements 516 | } 517 | }) 518 | .catch(alert("Could not reset achievements at this time. Try again later.")) 519 | ``` 520 | 521 | #### Response 522 | 523 | If you pass in `{hideAlert:true}` into `GameCenter.resetAchievements()` Method **OR** the you don't pass in the `hideAlert` parameter and player presses "Reset" 524 | 525 | ```json 526 | {"resetAchievements":true,"message":"User achievements reset"} 527 | ``` 528 | 529 | If you don't pass in the `hideAlert` parameter and player presses "No!" 530 | 531 | ```json 532 | {"resetAchievements":false,"message":"User achievements not reset"} 533 | ``` 534 | 535 | 536 | 537 | 538 | ## submitAchievementScore 539 | 540 | 541 | #### Details 542 | Submit progress of users achievements 543 | 544 | #### Parameters 545 | 546 | | Name | Required | Default | Description | 547 | |--------------|--------------|--------------|--------------| 548 | | percentComplete | Yes | n/a | number, float, or string of the percent achievement is complete. **Range 1-100** | 549 | | achievementIdentifier | No* (see Response) | `achievementIdentifier` set up in Itunes Connect | 550 | | hideCompletionBanner | No | `false` | Hides Game center banner when complete | 551 | 552 | 553 | #### Usage 554 | 555 | 556 | 557 | ```jsx 558 | let options={ 559 | percentComplete:50, 560 | achievementIdentifier:"novice_award" 561 | }; 562 | 563 | GameCenter.submitAchievementScore(options).then(res=>{ 564 | if(res){ 565 | //success 566 | } 567 | }) 568 | .catch(alert("Could not update your achievements at this time. Try again later.")) 569 | ``` 570 | 571 | 572 | #### Response 573 | 574 | **Success** 575 | 576 | ```json 577 | [null] 578 | ``` 579 | 580 | Not required if `achievementIdentifier` set as default in `init()`. `achievementIdentifier` always reverts to default unless defended. However, will reject promise if not passed in `init()` or `submitAchievementScore()` function 581 | 582 | **Failed** 583 | 584 | ```json 585 | No Game Center `achievementIdentifier` passed and no default set 586 | ``` 587 | 588 | 589 | 590 | # TODO 591 | 592 | 593 | ADD METHODS 594 | 595 | [ ] getLeaderboardPlayers() 596 | [ ] invite() 597 | [ ] challengeComposer() 598 | [ ] findScoresOfFriendsToChallenge() 599 | -------------------------------------------------------------------------------- /RNGameCenter/ios/RNGameCenter.m: -------------------------------------------------------------------------------- 1 | // 2 | // RNGameCenter.m 3 | // StockShot 4 | // 5 | // Created by vyga on 9/18/17. 6 | // Copyright © 2017 Facebook. All rights reserved. 7 | // 8 | 9 | #import "RNGameCenter.h" 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import 15 | 16 | 17 | //Global Defaults 18 | NSString *_leaderboardIdentifier; 19 | NSString *_achievementIdentifier; 20 | NSString *_playerId; 21 | BOOL _isGameCenterAvailable=NO; 22 | 23 | static RNGameCenter *SharedInstance = nil; 24 | //static NSString *scoresArchiveKey = @"Scores"; 25 | //static NSString *achievementsArchiveKey = @"Achievements"; 26 | //static BOOL isGameCenterAvailable() 27 | //{ 28 | // // Check for presence of GKLocalPlayer API. 29 | // Class gcClass = (NSClassFromString(@"GKLocalPlayer")); 30 | // 31 | // // The device must be running running iOS 4.1 or later. 32 | // NSString *reqSysVer = @"4.1"; 33 | // NSString *currSysVer = [[UIDevice currentDevice] systemVersion]; 34 | // BOOL osVersionSupported = ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending); 35 | // 36 | // return (gcClass && osVersionSupported); 37 | //} 38 | 39 | @interface RNGameCenter () 40 | 41 | @property (nonatomic, strong) GKGameCenterViewController *gkView; 42 | @property (nonatomic, strong) UIViewController *reactNativeViewController; 43 | @property (nonatomic, strong) NSNumber *_currentAdditionCounter; 44 | @end 45 | 46 | @interface MobSvcSavedGameData : NSObject 47 | @property (readwrite, retain) NSString *data; 48 | +(instancetype)sharedGameData; 49 | -(void)reset; 50 | @end 51 | 52 | 53 | @implementation RNGameCenter 54 | 55 | - (dispatch_queue_t)methodQueue{ 56 | return dispatch_get_main_queue(); 57 | } 58 | 59 | 60 | RCT_EXPORT_MODULE() 61 | 62 | 63 | 64 | /* ----------------------------------------------------------------------------------------------------------------------------------------- 65 | Init Game Center 66 | -----------------------------------------------------------------------------------------------------------------------------------------*/ 67 | 68 | 69 | RCT_EXPORT_METHOD(init:(NSDictionary *)options 70 | resolve:(RCTPromiseResolveBlock)resolve 71 | rejecter:(RCTPromiseRejectBlock)reject){ 72 | //GKGameCenterViewController* gcViewController = [[GKGameCenterViewController alloc]init]; 73 | if(options[@"leaderboardIdentifier"])_leaderboardIdentifier=options[@"leaderboardIdentifier"]; 74 | else reject(@"Error", @"Error please pass your leaderboardIdentifier into init function",nil); 75 | 76 | 77 | if(options[@"achievementIdentifier"])_achievementIdentifier=options[@"achievementIdentifier"]; 78 | 79 | 80 | UIViewController *rnView = [UIApplication sharedApplication].keyWindow.rootViewController; 81 | 82 | GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer]; 83 | localPlayer.authenticateHandler = ^(UIViewController *gcViewController, NSError *error){ 84 | if (gcViewController != nil) { 85 | [rnView presentViewController:gcViewController animated:YES completion:nil]; 86 | }else{ 87 | if ([GKLocalPlayer localPlayer].authenticated) { 88 | // Get the default leaderboard identifier. 89 | [[GKLocalPlayer localPlayer] loadDefaultLeaderboardIdentifierWithCompletionHandler:^(NSString *leaderboardIdentifier, NSError *error) { 90 | 91 | if (error != nil) { 92 | NSLog(@"%@",[error localizedDescription]); 93 | reject(@"Error", @"Error initiating Game Center make sure you are enrolled in the apple program, you set up a game center in itunes connect, and you registed it to the correct and matching app bundle id",error); 94 | }else{ 95 | //set to global 96 | _isGameCenterAvailable=YES; 97 | _leaderboardIdentifier=leaderboardIdentifier; 98 | resolve(@"init success"); 99 | } 100 | }]; 101 | }else{ 102 | reject(@"Error", @"Error initiating Game Center Player",error); 103 | } 104 | } 105 | }; 106 | }; 107 | 108 | RCT_EXPORT_METHOD(userLogged:(RCTPromiseResolveBlock)resolve 109 | rejecter:(RCTPromiseRejectBlock)reject){ 110 | resolve(_isGameCenterAvailable!=NO?@true:@false); 111 | } 112 | 113 | /* ----------------------------------------------------------------------------------------------------------------------------------------- 114 | Player 115 | -----------------------------------------------------------------------------------------------------------------------------------------*/ 116 | 117 | /* --------------getPlayer--------------*/ 118 | 119 | RCT_EXPORT_METHOD(getPlayer:(RCTPromiseResolveBlock)resolve 120 | rejecter:(RCTPromiseRejectBlock)reject){ 121 | if(_isGameCenterAvailable==NO){ 122 | reject(@"Error",@"Game Center is Unavailable", nil); 123 | return; 124 | } 125 | 126 | @try { 127 | GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer]; 128 | NSDictionary* user = @{ 129 | @"alias":localPlayer.alias, 130 | @"displayName":localPlayer.displayName, 131 | @"playerID":localPlayer.playerID, 132 | @"alias":localPlayer.alias 133 | }; 134 | resolve(user); 135 | }@catch (NSError * e) { 136 | reject(@"Error",@"Error getting user.", e); 137 | } 138 | } 139 | 140 | /* --------------loadLeaderboardPlayers-------------- 141 | //let leaderboardIdentifier="high_scores" 142 | // let achievementIdentifier="pro_award" 143 | //let achievementIdentifier="novice_award" 144 | RCT_EXPORT_METHOD(loadLeaderboardPlayers:(RCTPromiseResolveBlock)resolve 145 | rejecter:(RCTPromiseRejectBlock)reject){ 146 | NSArray *playersForIdentifiers=@[@"high_scores"]; 147 | 148 | // GKLocalPlayer *localPlayer = 149 | [GKLocalPlayer loadPlayersForIdentifiers:playersForIdentifiers withCompletionHandler:^(NSArray * _Nullable players, NSError * _Nullable error) { 150 | NSLog(@"PLAYERRRS %@",players); 151 | if(error)return reject(@"Error",@"no users.", error); 152 | resolve(players); 153 | }]; 154 | 155 | } 156 | 157 | */ 158 | 159 | 160 | /* --------------getPlayerImage--------------*/ 161 | // 162 | 163 | RCT_EXPORT_METHOD(getPlayerImage:(RCTPromiseResolveBlock)resolve 164 | rejecter:(RCTPromiseRejectBlock)reject){ 165 | if(_isGameCenterAvailable==NO){ 166 | reject(@"Error",@"Game Center is Unavailable", nil); 167 | return; 168 | } 169 | 170 | @try{ 171 | GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer]; 172 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, 173 | NSUserDomainMask, YES); 174 | NSString *documentsDirectory = [paths objectAtIndex:0]; 175 | NSString *path = [documentsDirectory stringByAppendingPathComponent: 176 | @"user.jpg" ]; 177 | 178 | // Check if the user photo is cached 179 | BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:path]; 180 | 181 | if(fileExists){ 182 | // Return it if it does 183 | NSDictionary *json = @{@"image":path}; 184 | resolve(json); 185 | }else{ 186 | // Else load it from the game center 187 | [localPlayer loadPhotoForSize:GKPhotoSizeSmall withCompletionHandler:^(UIImage *photo, NSError *error) { 188 | if (error!=nil)return reject(@"Error", @"Error fetching player image",error); 189 | 190 | if (photo != nil){ 191 | NSData* data = UIImageJPEGRepresentation(photo, 0.8); 192 | [data writeToFile:path atomically:YES]; 193 | NSDictionary *json = @{@"image":path}; 194 | resolve(json); 195 | }else{ 196 | NSMutableDictionary *json = [NSMutableDictionary dictionary]; 197 | json[@"image"] = nil; 198 | resolve(json); 199 | } 200 | 201 | 202 | }]; 203 | } 204 | }@catch (NSError * e) { 205 | reject(@"Error",@"Error fetching player image", e); 206 | } 207 | } 208 | 209 | // 210 | // 211 | //RCT_EXPORT_METHOD(challengePlayers:(NSDictionary *)options 212 | // resolve:(RCTPromiseResolveBlock)resolve 213 | // rejecter:(RCTPromiseRejectBlock)reject){ 214 | ////- (void) challengeViewController:(MyAchievementChallengeViewController*)controller wasDismissedWithChallenge:(BOOL)issued 215 | // @try { 216 | // NSArray *challengePlayerArray=options[@"players"]; 217 | // resolve(@"Successfully opened achievements"); 218 | // } 219 | // @catch (NSError * e) { 220 | // reject(@"Error",@"Error opening achievements.", e); 221 | // } 222 | //// 223 | //// [self dismissViewControllerAnimated:YES completion:NULL]; 224 | //// if (issued) 225 | //// { 226 | //// 227 | //// } 228 | //} 229 | // 230 | // 231 | //RCT_EXPORT_METHOD(challengeWithScore:(int64_t)playerScore 232 | // options:(NSDictionary *)options 233 | // resolve:(RCTPromiseResolveBlock)resolve 234 | // rejecter:(RCTPromiseRejectBlock)reject){ 235 | //// -(void) sendScoreChallengeToPlayers:(NSArray*)players withScore:(int64_t)score message:(NSString*)message { 236 | // NSString *message = options[@"message"]; 237 | // //NSArray *players = options[@"players"]; 238 | // NSMutableArray *players=@[@"G:8135064222"]; 239 | // 240 | // NSString *achievementId; 241 | // if(options[@"achievementIdentifier"])achievementId=options[@"achievementIdentifier"]; 242 | // //1 243 | // GKScore *gkScore = [[GKScore alloc] initWithLeaderboardIdentifier:achievementId]; 244 | // gkScore.value = playerScore; 245 | // 246 | // //2 247 | // UIViewController *rnView = [UIApplication sharedApplication].keyWindow.rootViewController; 248 | // [gkScore issueChallengeToPlayers:players message:message]; 249 | // GKGameCenterViewController *leaderboardController = [[GKGameCenterViewController alloc] init]; 250 | //// [rnView presentViewController: leaderboardController animated: YES completion:nil]; 251 | // 252 | // [rnView presentViewController:gkScore animated:YES completion:nil]; 253 | // 254 | // //challengeComposeControllerWithMessage 255 | //// } 256 | // 257 | //} 258 | // 259 | // 260 | ////-(void) findScoresOfFriendsToChallenge { 261 | // RCT_EXPORT_METHOD(findScoresOfFriendsToChallenge:(NSDictionary *)options 262 | // resolve:(RCTPromiseResolveBlock)resolve 263 | // rejecter:(RCTPromiseRejectBlock)reject){ 264 | // 265 | // // Get leaderboardIdentifier or use default leaderboardIdentifier 266 | // NSString *achievementId; 267 | // if(options[@"achievementIdentifier"])achievementId=options[@"achievementIdentifier"]; 268 | // else achievementId=_achievementIdentifier; 269 | // GKLeaderboard *leaderboard = [[GKLeaderboard alloc] init]; 270 | // leaderboard.identifier = achievementId; 271 | // leaderboard.playerScope = GKLeaderboardPlayerScopeFriendsOnly; 272 | // leaderboard.range = NSMakeRange(1, 100); 273 | // [leaderboard loadScoresWithCompletionHandler:^(NSArray *scores, NSError *error) { 274 | // BOOL success = (error == nil); 275 | // 276 | // if (success) { 277 | //// if (!_includeLocalPlayerScore) { 278 | //// NSMutableArray *friendsScores = [NSMutableArray array]; 279 | //// for (GKScore *score in scores) { 280 | //// if (![score.playerID isEqualToString:[GKLocalPlayer localPlayer].playerID]) { 281 | //// [friendsScores addObject:score]; 282 | //// } 283 | //// } 284 | //// scores = friendsScores; 285 | // resolve(scores); 286 | // 287 | // }else{ 288 | // reject(@"Error", @"Error scores",error); 289 | // } 290 | // }]; 291 | //} 292 | // 293 | 294 | 295 | 296 | /* ----------------------------------------------------------------------------------------------------------------------------------------- 297 | Leaderboard 298 | -----------------------------------------------------------------------------------------------------------------------------------------*/ 299 | 300 | /* --------------openLeaderboardModal--------------*/ 301 | //RCT_EXPORT_METHOD(openLeaderboardModal:(NSString *)leaderboardIdentifier 302 | RCT_EXPORT_METHOD(openLeaderboardModal:(NSDictionary *)options 303 | resolve:(RCTPromiseResolveBlock)resolve 304 | //RCT_EXPORT_METHOD(openLeaderboardModal:(RCTPromiseResolveBlock)resolve 305 | rejecter:(RCTPromiseRejectBlock)reject){ 306 | 307 | if(_isGameCenterAvailable==NO){ 308 | reject(@"Error",@"Game Center is Unavailable", nil); 309 | return; 310 | } 311 | 312 | UIViewController *rnView = [UIApplication sharedApplication].keyWindow.rootViewController; 313 | GKGameCenterViewController *leaderboardController = [[GKGameCenterViewController alloc] init]; 314 | NSString *leaderboardId; 315 | if(options[@"leaderboardIdentifier"])leaderboardId=options[@"leaderboardIdentifier"]; 316 | else leaderboardId=_leaderboardIdentifier; 317 | if (leaderboardController != NULL){ 318 | leaderboardController.leaderboardIdentifier = leaderboardId; 319 | leaderboardController.viewState = GKGameCenterViewControllerStateLeaderboards; 320 | leaderboardController.gameCenterDelegate = self; 321 | [rnView presentViewController: leaderboardController animated: YES completion:nil]; 322 | resolve(@"opened Leaderboard"); 323 | } 324 | } 325 | 326 | 327 | /* --------------submitLeaderboardScore--------------*/ 328 | 329 | 330 | RCT_EXPORT_METHOD(submitLeaderboardScore:(int64_t)score 331 | options:(NSDictionary *)options 332 | resolve:(RCTPromiseResolveBlock)resolve 333 | rejecter:(RCTPromiseRejectBlock)reject){ 334 | 335 | if(_isGameCenterAvailable==NO){ 336 | reject(@"Error",@"Game Center is Unavailable", nil); 337 | return; 338 | } 339 | 340 | @try{ 341 | // Get leaderboardIdentifier or use default leaderboardIdentifier 342 | NSString *leaderboardId; 343 | if(options[@"leaderboardIdentifier"])leaderboardId=options[@"leaderboardIdentifier"]; 344 | else leaderboardId=_leaderboardIdentifier; 345 | 346 | GKScore *scoreSubmitter = [[GKScore alloc] initWithLeaderboardIdentifier: leaderboardId]; 347 | scoreSubmitter.value = score; 348 | scoreSubmitter.context = 0; 349 | 350 | [GKScore reportScores:@[scoreSubmitter] withCompletionHandler:^(NSError *error) { 351 | if (error) 352 | { 353 | reject(@"Error", @"Error submitting score",error); 354 | }else{ 355 | resolve(@"Successfully submitted score"); 356 | } 357 | }]; 358 | }@catch (NSError * e) { 359 | reject(@"Error",@"Error submitting score.", e); 360 | } 361 | } 362 | 363 | 364 | 365 | /* --------------getLeaderboardPlayers--------------*/ 366 | 367 | RCT_EXPORT_METHOD(getLeaderboardPlayers:(NSDictionary *)options 368 | resolve:(RCTPromiseResolveBlock)resolve 369 | rejecter:(RCTPromiseRejectBlock)reject){ 370 | if(_isGameCenterAvailable==NO){ 371 | reject(@"Error",@"Game Center is Unavailable", nil); 372 | return; 373 | } 374 | 375 | @try{ 376 | //Get Player Ids 377 | NSArray *playerIds=options[@"playerIds"]; 378 | //create Query with Player Ids 379 | GKLeaderboard *query = [[GKLeaderboard alloc] initWithPlayers:[NSArray arrayWithObject:playerIds]]; 380 | 381 | if (query != nil){ 382 | [query loadScoresWithCompletionHandler: ^(NSArray *scores, NSError *error) { 383 | if (error != nil)reject(@"Error", @"Error getting players leaderboards",error); 384 | else resolve(scores); 385 | }]; 386 | }else{ 387 | reject(@"Error", @"Error creating Leaderboard query",nil); 388 | } 389 | }@catch (NSError * e) { 390 | reject(@"Error",@"Error getting leaderboard players.", e); 391 | } 392 | } 393 | 394 | 395 | 396 | /* 397 | ----------------------------------------------------------------------------------------------------------------------------------------- 398 | Achievements 399 | ----------------------------------------------------------------------------------------------------------------------------------------- 400 | */ 401 | 402 | /* --------------openAchievementModal--------------*/ 403 | 404 | RCT_EXPORT_METHOD(openAchievementModal: (NSDictionary *)options 405 | resolve:(RCTPromiseResolveBlock)resolve 406 | rejecter:(RCTPromiseRejectBlock)reject){ 407 | 408 | if(_isGameCenterAvailable==NO){ 409 | reject(@"Error",@"Game Center is Unavailable", nil); 410 | return; 411 | } 412 | 413 | @try { 414 | GKGameCenterViewController* gcViewController = [[GKGameCenterViewController alloc]init]; 415 | UIViewController *rnView = [UIApplication sharedApplication].keyWindow.rootViewController; 416 | gcViewController.viewState = GKGameCenterViewControllerStateAchievements; 417 | // Get achievementIdentifier or use default achievementIdentifier 418 | NSString *achievementId; 419 | if(options[@"achievementIdentifier"])achievementId=options[@"achievementIdentifier"]; 420 | else achievementId=_achievementIdentifier; 421 | gcViewController.leaderboardIdentifier = achievementId; 422 | //attaches to class to allow dismissal 423 | gcViewController.gameCenterDelegate = self; 424 | [rnView presentViewController:gcViewController animated:YES completion:nil]; 425 | resolve(@"Successfully opened achievements"); 426 | } 427 | @catch (NSError * e) { 428 | reject(@"Error",@"Error opening achievements.", e); 429 | } 430 | }; 431 | 432 | 433 | /* --------------getAchievements--------------*/ 434 | 435 | RCT_EXPORT_METHOD(getAchievements: (RCTPromiseResolveBlock)resolve 436 | rejecter:(RCTPromiseRejectBlock)reject){ 437 | 438 | if(_isGameCenterAvailable==NO){ 439 | reject(@"Error",@"Game Center is Unavailable", nil); 440 | return; 441 | } 442 | 443 | NSMutableArray *earntAchievements = [NSMutableArray array]; 444 | [GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *achievements, NSError *error){ 445 | if (error == nil) { 446 | for (GKAchievement* achievement in achievements) { 447 | NSMutableDictionary *entry = [NSMutableDictionary dictionary]; 448 | entry[@"identifier"] = achievement.identifier; 449 | entry[@"percentComplete"] = [NSNumber numberWithDouble: achievement.percentComplete]; 450 | entry[@"completed"] = [NSNumber numberWithBool:achievement.completed]; 451 | entry[@"lastReportedDate"] = [NSNumber numberWithDouble:[achievement.lastReportedDate timeIntervalSince1970] * 1000]; 452 | entry[@"showsCompletionBanner"] = [NSNumber numberWithBool:achievement.showsCompletionBanner]; 453 | // entry[@"playerID"] = achievement.playerID; 454 | [earntAchievements addObject:entry]; 455 | } 456 | resolve(earntAchievements); 457 | }else{ 458 | reject(@"Error", @"Error getting achievements",error); 459 | } 460 | }]; 461 | } 462 | 463 | 464 | 465 | /* --------------resetAchievements--------------*/ 466 | RCT_EXPORT_METHOD(resetAchievements:(NSDictionary *)options 467 | resolve:(RCTPromiseResolveBlock)resolve 468 | rejecter:(RCTPromiseRejectBlock)reject){ 469 | if(_isGameCenterAvailable==NO){ 470 | reject(@"Error",@"Game Center is Unavailable", nil); 471 | return; 472 | } 473 | 474 | // Clear all progress saved on Game Center. 475 | if(!options[@"hideAlert"]){ 476 | UIViewController *rnView = [UIApplication sharedApplication].keyWindow.rootViewController; 477 | UIAlertController * alert = [UIAlertController 478 | alertControllerWithTitle:@"Reset Achievements?" 479 | message:@"Are you sure you want to reset your achievements. This can not be undone." 480 | preferredStyle:UIAlertControllerStyleAlert]; 481 | 482 | UIAlertController *yesAlert = [UIAlertController alertControllerWithTitle:@"Success!" 483 | message:@"You successfully reset your achievements!" 484 | preferredStyle:UIAlertControllerStyleActionSheet]; 485 | 486 | [yesAlert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { 487 | [yesAlert dismissViewControllerAnimated:YES completion:nil]; 488 | }]]; 489 | 490 | UIAlertAction* yesButton = [UIAlertAction 491 | actionWithTitle:@"Reset" 492 | style:UIAlertActionStyleDefault 493 | 494 | handler:^(UIAlertAction * action) { 495 | //Handle your yes please button action here 496 | [GKAchievement resetAchievementsWithCompletionHandler: ^ (NSError * error){ 497 | if(error != nil) { 498 | reject(@ "Error", @ "Error resetting achievements", error);} 499 | else { 500 | [rnView presentViewController:yesAlert animated:YES completion:nil]; 501 | NSDictionary *json = @{ 502 | @"message":@"User achievements not reset", 503 | @"resetAchievements":@true 504 | }; 505 | resolve(json); 506 | } 507 | }]; 508 | }]; 509 | 510 | UIAlertAction* noButton = [UIAlertAction 511 | actionWithTitle:@"No!" 512 | style:UIAlertActionStyleDefault 513 | handler:^(UIAlertAction * action) { 514 | //Handle no, thanks button 515 | NSDictionary *json = @{ 516 | @"message":@"User achievements not reset", 517 | @"resetAchievements":@false 518 | }; 519 | resolve(json); 520 | }]; 521 | 522 | [alert addAction:yesButton]; 523 | [alert addAction:noButton]; 524 | 525 | [rnView presentViewController:alert animated:YES completion:nil]; 526 | 527 | }else{ 528 | NSDictionary *json = @{ 529 | @"message":@"User achievements reset", 530 | @"resetAchievements":@true 531 | }; 532 | resolve(json); 533 | } 534 | 535 | } 536 | 537 | 538 | /* --------------submitAchievement--------------*/ 539 | 540 | RCT_EXPORT_METHOD(submitAchievementScore:(NSDictionary *)options 541 | resolve:(RCTPromiseResolveBlock)resolve 542 | rejecter:(RCTPromiseRejectBlock)reject){ 543 | if(_isGameCenterAvailable==NO) { 544 | reject(@"Error",@"Game Center is Unavailable", nil); 545 | return; 546 | } 547 | @try{ 548 | NSString *percent = options[@"percentComplete"]; 549 | 550 | float percentFloat = [percent floatValue]; 551 | NSString *achievementId; 552 | if(options[@"achievementIdentifier"])achievementId=options[@"achievementIdentifier"]; 553 | else achievementId=_achievementIdentifier; 554 | 555 | RCTLog(@"Will store: %@ (%f) on '%@'", percent, percentFloat, achievementId); 556 | 557 | if(!achievementId)return reject(@"Error",@"No Game Center `achievementIdentifier` passed and no default set", nil); 558 | BOOL showsCompletionBanner=YES; 559 | if(options[@"hideCompletionBanner"])showsCompletionBanner=NO; 560 | NSLog(@"showsCompletionBanner %d",showsCompletionBanner); 561 | GKAchievement *achievement = [[GKAchievement alloc] initWithIdentifier: achievementId]; 562 | if (achievement){ 563 | achievement.percentComplete = percentFloat; 564 | achievement.showsCompletionBanner = showsCompletionBanner; 565 | 566 | NSArray *achievements = [NSArray arrayWithObjects:achievement, nil]; 567 | 568 | [GKAchievement reportAchievements:achievements withCompletionHandler:^(NSError *error) { 569 | if (error != nil){ 570 | reject(@"Error",@"Game Center setting Achievement", error); 571 | }else{ 572 | // Achievement notification banners are broken on iOS 7 so we do it manually here if 100%: 573 | if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0 && 574 | [[[UIDevice currentDevice] systemVersion] floatValue] < 8.0 && 575 | floorf(percentFloat) >= 100) 576 | { 577 | [GKNotificationBanner showBannerWithTitle:@"Achievement" message:@"Completed!" completionHandler:^{}]; 578 | } 579 | resolve(achievements); 580 | } 581 | }]; 582 | } 583 | } @catch (NSError * e) { 584 | reject(@"Error",@"Error setting achievement.", e); 585 | } 586 | } 587 | 588 | 589 | RCT_EXPORT_METHOD(invite:(NSDictionary *)options 590 | resolve:(RCTPromiseResolveBlock)resolve 591 | rejecter:(RCTPromiseRejectBlock)reject){ 592 | if(_isGameCenterAvailable==NO){ 593 | reject(@"Error",@"Game Center is Unavailable", nil); 594 | return; 595 | } 596 | 597 | GKMatchRequest *request = [[GKMatchRequest alloc] init]; 598 | request.minPlayers = 2; 599 | request.maxPlayers = 4; 600 | request.recipients =@[@"G:8135064222"]; 601 | request.inviteMessage = @"Your Custom Invitation Message Here"; 602 | request.recipientResponseHandler = ^(GKPlayer *player, GKInviteeResponse response) { 603 | resolve(player); 604 | }; 605 | } 606 | 607 | RCT_EXPORT_METHOD(getPlayerFriends:(RCTPromiseResolveBlock)resolve 608 | rejecter:(RCTPromiseRejectBlock)reject){ 609 | if(_isGameCenterAvailable==NO){ 610 | reject(@"Error",@"Game Center is Unavailable", nil); 611 | return; 612 | } 613 | resolve([GKLocalPlayer localPlayer].friends); 614 | } 615 | 616 | /* 617 | RCT_EXPORT_METHOD(challengeComposer:(int64_t) playerScore 618 | options:(NSDictionary *)options 619 | resolve:(RCTPromiseResolveBlock)resolve 620 | rejecter:(RCTPromiseRejectBlock)reject){ 621 | 622 | GKLeaderboard *query = [[GKLeaderboard alloc] init]; 623 | // Get achievementIdentifier or use default achievementIdentifier 624 | NSString *leaderboardId; 625 | if(options[@"leaderboardIdentifier"])leaderboardId=options[@"leaderboardIdentifier"]; 626 | else leaderboardId=_leaderboardIdentifier; 627 | 628 | query.identifier = leaderboardId; 629 | query.playerScope = GKLeaderboardPlayerScopeFriendsOnly; 630 | query.range = NSMakeRange(1,100); 631 | [query loadScoresWithCompletionHandler:^(NSArray *scores, NSError *error) { 632 | NSPredicate *filter = [NSPredicate predicateWithFormat:@"value < %qi",playerScore]; 633 | NSArray *lesserScores = [scores filteredArrayUsingPredicate:filter]; 634 | // UIViewController *rnView = [UIApplication sharedApplication].keyWindow.rootViewController; 635 | // *rnView = [UIApplication sharedApplication].keyWindow.rootViewController; 636 | // [self presentChallengeWithPreselectedScores: lesserScores]; 637 | GKScore *gkScore = [[GKScore alloc] initWithLeaderboardIdentifier:leaderboardId]; 638 | gkScore.value = playerScore; 639 | NSString *message=@"hey fag, face off?"; 640 | //NSArray *players=@[@"high_scores"]; 641 | NSMutableArray *players=@[@"G:8135064222"]; 642 | 643 | // [gkScore issueChallengeToPlayers:players message:message]; 644 | // GKScore *gkScore = [[GKInvite alloc] initWithLeaderboardIdentifier:leaderboardId]; 645 | 646 | [gkScore challengeComposeControllerWithMessage:message 647 | players:players 648 | //players:[GKLocalPlayer localPlayer].friends 649 | completionHandler:^(UIViewController * _Nonnull composeController, BOOL didIssueChallenge, NSArray * _Nullable sentPlayerIDs) { 650 | if (error) reject(@"Error", @"Error reporting achievement",error); 651 | else resolve(sentPlayerIDs); 652 | }]; 653 | }]; 654 | }*/ 655 | // Get achievementIdentifier or use default achievementIdentifier 656 | // NSString *achievementId; 657 | // 658 | // if(options[@"achievementIdentifier"])achievementId=options[@"achievementIdentifier"]; 659 | // else achievementId=_achievementIdentifier; 660 | // 661 | // NSString *message=@"hey fag, face off?"; 662 | // NSArray *players=@[@"high_scores"]; 663 | // [self abc:@"Yoop"] 664 | 665 | // GKAchievement *achievement = [[GKAchievement alloc] initWithIdentifier:@"MyGame.bossDefeated"]; 666 | // achievement.percentComplete = 100.0; 667 | // achievement.showsCompletionBanner = NO; 668 | // 669 | // [achievement reportAchievements: [NSArray arrayWithObjects:achievement, nil] WithCompletionHandler:NULL]; 670 | // [self performSegueWithIdentifier:@"achievementChallenge" sender:achievement]; 671 | // 672 | 673 | // [GKChallenge loadReceivedChallengesWithCompletionHandler:^(NSArray * _Nullable challenges, NSError * _Nullable error) { 674 | // <#code#> 675 | // }]; 676 | // UIViewController *rnView = [UIApplication sharedApplication].keyWindow.rootViewController; 677 | // *rnView = [UIApplication sharedApplication].keyWindow.rootViewController; 678 | // [UIViewController challengeComposeControllerWithMessage:message players:players 679 | //completionHandler:^(NSError *error) { 680 | // if (error) reject(@"Error", @"Error reporting achievement",error); 681 | // else resolve(@"opened challengeComposer!"); 682 | //}]; 683 | // 684 | 685 | 686 | // 687 | //- (void )prepareForSegue:(UIStoryboardSegue *)segue sender:(id)dsender 688 | //{ 689 | // if ([segue.identifier isEqualToString:@"achievementChallenge"]) 690 | // { 691 | //// MyAchievementChallengeViewController* challengeVC = (MyAchievementChallengeViewController*) segue.destinationViewController; 692 | //// UIViewController *rnView = [UIApplication sharedApplication].keyWindow.rootViewController; 693 | //// [challengeVC performSegueWithIdentifier:@"startPlaying" sender:self]; 694 | // //challengeVC.delegate = self; 695 | // //challengeVC.achievement = (GKAchievement*) sender; 696 | // } 697 | //} 698 | // 699 | //- (void) challengeViewController:(MyAchievementChallengeViewController*)controller wasDismissedWithChallenge:(BOOL)issued 700 | //{ 701 | // [self dismissViewControllerAnimated:YES completion:NULL]; 702 | // if (issued) 703 | // { 704 | // [controller.achievement issueChallengeToPlayers:controller.players message:controller.message]; 705 | // } 706 | //} 707 | 708 | RCT_EXPORT_METHOD(challengePlayersToCompleteAchievement:(NSDictionary *)options 709 | resolve:(RCTPromiseResolveBlock)resolve 710 | rejecter:(RCTPromiseRejectBlock)reject){ 711 | if(_isGameCenterAvailable==NO) { 712 | reject(@"Error",@"Game Center is Unavailable", nil); 713 | return; 714 | } 715 | 716 | GKAchievement *achievement; 717 | [achievement selectChallengeablePlayers:[GKLocalPlayer localPlayer].friends withCompletionHandler:^(NSArray *challengeablePlayers, NSError *error) { 718 | if (challengeablePlayers){ 719 | resolve(challengeablePlayers); 720 | } 721 | }]; 722 | } 723 | 724 | 725 | /* issued when the player completed a challenge sent by a friend 726 | 727 | - (void)player:(GKPlayer *)player didCompleteChallenge:(GKChallenge *)challenge issuedByFriend:(GKPlayer *)friendPlayer{ 728 | NSLog(@"Challenge %@ sent by %@ completed", challenge.description , friendPlayer.displayName); 729 | } 730 | // issued when a friend of the player completed a challenge sent by the player 731 | 732 | - (void)player:(GKPlayer *)player issuedChallengeWasCompleted:(GKChallenge *)challenge byFriend:(GKPlayer *)friendPlayer{ 733 | NSLog(@"Your friend %@ has successfully completed the %@ challenge", friendPlayer.displayName, challenge.description); 734 | } 735 | 736 | // issued when a player wants to play the challenge and has just started the game (from a notification) 737 | 738 | - (void)player:(GKPlayer *)player wantsToPlayChallenge:(GKChallenge *)challenge{ 739 | //[self performSegueWithIdentifier:@"startPlaying" sender:self]; 740 | 741 | UIViewController *rnView = [UIApplication sharedApplication].keyWindow.rootViewController; 742 | [rnView performSegueWithIdentifier:@"startPlaying" sender:self]; 743 | } 744 | 745 | // issued when a player wants to play the challenge and is in the game (the game was running while the challenge was sent) 746 | 747 | 748 | - (void)player:(GKPlayer *)player didReceiveChallenge:(GKChallenge *)challenge{ 749 | 750 | NSString *friendMsg = [[NSString alloc] initWithFormat:@"Your friend %@ has invited you to a challenge: %@", player.displayName, challenge.message]; 751 | UIAlertView *theChallenge = [[UIAlertView alloc] initWithTitle:@"Want to take the challenge?" message:friendMsg delegate:self cancelButtonTitle:@"Challenge accepted" otherButtonTitles:@"No", nil]; 752 | 753 | [theChallenge show]; 754 | } 755 | 756 | 757 | 758 | 759 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{ 760 | //if (buttonIndex == 0) [self performSegueWithIdentifier:@"startPlaying"sender:self]; 761 | if (buttonIndex == 0) { 762 | UIViewController *rnView = [UIApplication sharedApplication].keyWindow.rootViewController; 763 | [rnView performSegueWithIdentifier:@"startPlaying" sender:self]; 764 | } 765 | } 766 | */ 767 | //-(void) submitAchievementScore:(NSString*)identifier percentComplete:(float)percent 768 | //{ 769 | // if (isGameCenterAvailable == NO) 770 | // return; 771 | // 772 | // GKAchievement* achievement = [self getAchievement:identifier]; 773 | // if (percent > achievement.percentComplete) 774 | // { 775 | // NSLog(@"new achievement %@ reported", achievement.identifier); 776 | // achievement.percentComplete = percent; 777 | // [achievement reportAchievementWithCompletionHandler:^(NSError* error) { 778 | // if (achievement.isCompleted) { 779 | // [delegate onReportAchievement:(GKAchievement*)achievement]; 780 | // } 781 | // }]; 782 | // 783 | // [self saveAchievements]; 784 | // } 785 | //} 786 | //- (NSString*)getGameCenterSavePath{ 787 | // NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 788 | // return [NSString stringWithFormat:@"%@/GameCenterSave.txt",[paths objectAtIndex:0]]; 789 | //} 790 | // 791 | // 792 | //- (void)saveAchievements:(GKAchievement *)achievement 793 | //{ 794 | // NSString *savePath = [self getGameCenterSavePath]; 795 | // 796 | // // If achievements already exist, append the new achievement. 797 | // NSMutableArray *achievements = [[NSMutableArray alloc] init];// autorelease]; 798 | // NSMutableDictionary *dict; 799 | // if([[NSFileManager defaultManager] fileExistsAtPath:savePath]){ 800 | // dict = [[NSMutableDictionary alloc] initWithContentsOfFile:savePath];// autorelease]; 801 | // 802 | // NSData *data = [dict objectForKey:achievementsArchiveKey]; 803 | // if(data) { 804 | // NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data]; 805 | // achievements = [unarchiver decodeObjectForKey:achievementsArchiveKey]; 806 | // [unarchiver finishDecoding]; 807 | // //[unarchiver release]; 808 | // [dict removeObjectForKey:achievementsArchiveKey]; // remove it so we can add it back again later 809 | // } 810 | // }else{ 811 | // dict = [[NSMutableDictionary alloc] init];// autorelease]; 812 | // 813 | // } 814 | // NSLog(@"saveeee%@",dict); 815 | // 816 | // [achievements addObject:achievement]; 817 | // 818 | // // The achievement has been added, now save the file again 819 | // NSMutableData *data = [NSMutableData data]; 820 | // NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; 821 | // [archiver encodeObject:achievements forKey:achievementsArchiveKey]; 822 | // [archiver finishEncoding]; 823 | // [dict setObject:data forKey:achievementsArchiveKey]; 824 | // [dict writeToFile:savePath atomically:YES]; 825 | // //[archiver release]; 826 | //} 827 | // 828 | 829 | 830 | //Enable the ability to close Achivments/Leaderboard Game Center Popup from React Native App 831 | - (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)viewController{ 832 | [viewController dismissViewControllerAnimated:YES completion:nil]; 833 | } 834 | //Enable the ability to close Achivments/Leaderboard Game Center Popup from React Native App 835 | - (void)gameCenterViewControllerDidCancel:(GKGameCenterViewController *)gameCenterViewController{ 836 | //- (void)gameCenterViewControllerDidCancel:(GKGameCenterViewController *)viewController{ 837 | [gameCenterViewController dismissViewControllerAnimated:YES completion:nil]; 838 | } 839 | 840 | 841 | //-(void)updateAchievements{ 842 | // NSString *achievementIdentifier; 843 | // float progressPercentage = 0.0; 844 | // BOOL progressInLevelAchievement = NO; 845 | // 846 | // GKAchievement *levelAchievement = nil; 847 | // GKAchievement *scoreAchievement = nil; 848 | // 849 | // if (_currentAdditionCounter == 0) { 850 | // if (_level <= 3) { 851 | // progressPercentage = _level * 100 / 3; 852 | // achievementIdentifier = @"Achievement_Level3"; 853 | // progressInLevelAchievement = YES; 854 | // } 855 | // else if (_level < 6){ 856 | // progressPercentage = _level * 100 / 5; 857 | // achievementIdentifier = @"Achievement_Level5Complete"; 858 | // progressInLevelAchievement = YES; 859 | // } 860 | // } 861 | // 862 | // if (progressInLevelAchievement) { 863 | // levelAchievement = [[GKAchievement alloc] initWithIdentifier:achievementIdentifier]; 864 | // levelAchievement.percentComplete = progressPercentage; 865 | // } 866 | // 867 | // 868 | // if (_score <= 50) { 869 | // progressPercentage = _score * 100 / 50; 870 | // achievementIdentifier = @"Achievement_50Points"; 871 | // } 872 | // else if (_score <= 120){ 873 | // progressPercentage = _score * 100 / 120; 874 | // achievementIdentifier = @"Achievement_120Points"; 875 | // } 876 | // else{ 877 | // progressPercentage = _score * 100 / 180; 878 | // achievementIdentifier = @"Achievement_180Points"; 879 | // } 880 | // 881 | // scoreAchievement = [[GKAchievement alloc] initWithIdentifier:achievementIdentifier]; 882 | // scoreAchievement.percentComplete = progressPercentage; 883 | // 884 | // NSArray *achievements = (progressInLevelAchievement) ? @[levelAchievement, scoreAchievement] : @[scoreAchievement]; 885 | // 886 | // [GKAchievement reportAchievements:achievements withCompletionHandler:^(NSError *error) { 887 | // if (error != nil) { 888 | // NSLog(@"%@", [error localizedDescription]); 889 | // } 890 | // }]; 891 | //} 892 | 893 | // 894 | //- (void)authenticateLocalPlayer 895 | //{ 896 | 897 | // [[GKLocalPlayer localPlayer] setAuthenticateHandler:^(UIViewController *viewController, NSError *error) { 898 | // 899 | // GKScore *score = [[GKScore alloc] initWithLeaderboardIdentifier:@"scoreLeaderboard"]; 900 | // [score setValue:[[NSUserDefaults standardUserDefaults] integerForKey:@"highScore"]]; 901 | // 902 | // [GKScore reportScores:@[score] withCompletionHandler:^(NSError *error) { 903 | // NSLog(@"Reporting Error: %@",error); 904 | // }]; 905 | // 906 | // }]; 907 | //} 908 | 909 | RCT_EXPORT_METHOD(loadSavedGameData:(NSDictionary *)options 910 | resolve:(RCTPromiseResolveBlock)resolve 911 | rejecter:(RCTPromiseRejectBlock)reject){ 912 | GKLocalPlayer *mobSvcAccount = [GKLocalPlayer localPlayer]; 913 | 914 | if(!mobSvcAccount.isAuthenticated){ 915 | reject(@"Error",@"Can't load game: Game center is not initalized...", nil); 916 | return; 917 | } 918 | 919 | [mobSvcAccount fetchSavedGamesWithCompletionHandler:^(NSArray * _Nullable savedGames, NSError * _Nullable error) { 920 | 921 | if(error != nil) { 922 | NSLog(@"Failed to prepare saved game data: %@", error.description); 923 | reject(@"Error",@"Can't load game", nil); 924 | } 925 | 926 | GKSavedGame *savedGameToLoad = nil; 927 | for(GKSavedGame *savedGame in savedGames) { NSLog(@"Successfully downloaded saved game data"); 928 | if([savedGame.name isEqualToString:options[@"name"]]) { 929 | if (savedGameToLoad == nil || savedGameToLoad.modificationDate < savedGame.modificationDate) { 930 | savedGameToLoad = savedGame; 931 | } 932 | } 933 | } 934 | if(savedGameToLoad == nil) { 935 | resolve(@{ 936 | @"isConflict": @false, 937 | @"data": @"" 938 | }); 939 | return; 940 | } 941 | [savedGameToLoad loadDataWithCompletionHandler:^(NSData * _Nullable data, NSError * _Nullable error) { 942 | if(error == nil) { 943 | MobSvcSavedGameData *savedGameData = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 944 | NSLog(@"Successfully downloaded saved game data"); 945 | resolve(@{ 946 | @"isConflict": @false, 947 | @"data": savedGameData.data 948 | }); 949 | } else { 950 | NSLog(@"Failed to download saved game data: %@", error.description); 951 | reject(@"Error",@"Can't load game", nil); 952 | } 953 | }]; 954 | }]; 955 | } 956 | 957 | 958 | RCT_EXPORT_METHOD(uploadSavedGameData:(NSDictionary *)options 959 | resolve:(RCTPromiseResolveBlock)resolve 960 | rejecter:(RCTPromiseRejectBlock)reject){ 961 | GKLocalPlayer *mobSvcAccount = [GKLocalPlayer localPlayer]; 962 | 963 | if(!mobSvcAccount.isAuthenticated) { 964 | reject(@"Error",@"Can't save game: Game center is not initalized...", nil); 965 | return; 966 | } 967 | MobSvcSavedGameData *savedGameData = [[MobSvcSavedGameData alloc] init]; 968 | savedGameData.data = options[@"data"]; 969 | [mobSvcAccount saveGameData:[NSKeyedArchiver archivedDataWithRootObject:savedGameData] withName:options[@"name"] completionHandler:^(GKSavedGame * _Nullable savedGame __unused, NSError * _Nullable error) { 970 | if(error == nil) { 971 | NSLog(@"Successfully uploaded saved game data"); 972 | resolve(@"Saved game data"); 973 | } else { 974 | NSLog(@"Failed to upload saved game data: %@", error.description); 975 | reject(@"Error",@"Can't save game", nil); 976 | } 977 | }]; 978 | } 979 | 980 | 981 | 982 | 983 | /* 984 | https://github.com/garrettmac/react-native-tweet/blob/master/Tweet/ios/RNTweet.m 985 | */ 986 | 987 | 988 | /* 989 | //NSError *jsonError; 990 | // NSDictionary *json = [NSJSONSerialization 991 | // JSONObjectWithData:localPlayer 992 | // options:0 993 | // error:&jsonError]; 994 | //NSDictionary *json = @{@"localPlayer":localPlayer}; 995 | 996 | 997 | 998 | NSString *leaderboardIdentifier = @"StockShotLeaderboard";*/ 999 | /* 1000 | GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer]; 1001 | localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error){ 1002 | if (viewController != nil) { 1003 | [self presentViewController:viewController animated:YES completion:nil]; 1004 | } 1005 | else{ 1006 | if ([GKLocalPlayer localPlayer].authenticated) { 1007 | _gameCenterEnabled = YES; 1008 | 1009 | // Get the default leaderboard identifier. 1010 | [[GKLocalPlayer localPlayer] loadDefaultLeaderboardIdentifierWithCompletionHandler:^(NSString *leaderboardIdentifier, NSError *error) { 1011 | 1012 | if (error != nil) { 1013 | NSLog(@"%@", [error localizedDescription]); 1014 | } 1015 | else{ 1016 | _leaderboardIdentifier = leaderboardIdentifier; 1017 | } 1018 | }]; 1019 | } 1020 | 1021 | else{ 1022 | _gameCenterEnabled = NO; 1023 | } 1024 | } 1025 | };*/ 1026 | 1027 | 1028 | 1029 | 1030 | 1031 | 1032 | 1033 | /* 1034 | 1035 | 1036 | 1037 | -(void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController 1038 | { 1039 | [gameCenterViewController dismissViewControllerAnimated:YES completion:nil]; 1040 | } 1041 | */ 1042 | 1043 | 1044 | /* 1045 | 1046 | -(void)updateAchievements{ 1047 | NSString *achievementIdentifier; 1048 | float progressPercentage = 0.0; 1049 | BOOL progressInLevelAchievement = NO; 1050 | 1051 | GKAchievement *levelAchievement = nil; 1052 | GKAchievement *scoreAchievement = nil; 1053 | 1054 | if (_currentAdditionCounter == 0) { 1055 | if (_level <= 3) { 1056 | progressPercentage = _level * 100 / 3; 1057 | achievementIdentifier = @"Achievement_Level3"; 1058 | progressInLevelAchievement = YES; 1059 | } 1060 | else if (_level < 6){ 1061 | progressPercentage = _level * 100 / 5; 1062 | achievementIdentifier = @"Achievement_Level5Complete"; 1063 | progressInLevelAchievement = YES; 1064 | } 1065 | } 1066 | 1067 | if (progressInLevelAchievement) { 1068 | levelAchievement = [[GKAchievement alloc] initWithIdentifier:achievementIdentifier]; 1069 | levelAchievement.percentComplete = progressPercentage; 1070 | } 1071 | 1072 | 1073 | if (_score <= 50) { 1074 | progressPercentage = _score * 100 / 50; 1075 | achievementIdentifier = @"Achievement_50Points"; 1076 | } 1077 | else if (_score <= 120){ 1078 | progressPercentage = _score * 100 / 120; 1079 | achievementIdentifier = @"Achievement_120Points"; 1080 | } 1081 | else{ 1082 | progressPercentage = _score * 100 / 180; 1083 | achievementIdentifier = @"Achievement_180Points"; 1084 | } 1085 | 1086 | scoreAchievement = [[GKAchievement alloc] initWithIdentifier:achievementIdentifier]; 1087 | scoreAchievement.percentComplete = progressPercentage; 1088 | 1089 | NSArray *achievements = (progressInLevelAchievement) ? @[levelAchievement, scoreAchievement] : @[scoreAchievement]; 1090 | 1091 | [GKAchievement reportAchievements:achievements withCompletionHandler:^(NSError *error) { 1092 | if (error != nil) { 1093 | NSLog(@"%@", [error localizedDescription]); 1094 | } 1095 | }]; 1096 | } 1097 | */ 1098 | 1099 | 1100 | /* 1101 | 1102 | -(void)updateAchievements{ 1103 | NSString *achievementIdentifier; 1104 | float progressPercentage = 0.0; 1105 | BOOL progressInLevelAchievement = NO; 1106 | 1107 | GKAchievement *levelAchievement = nil; 1108 | GKAchievement *scoreAchievement = nil; 1109 | 1110 | if (_currentAdditionCounter == 0) { 1111 | if (_level <= 3) { 1112 | progressPercentage = _level * 100 / 3; 1113 | achievementIdentifier = @"Achievement_Level3"; 1114 | progressInLevelAchievement = YES; 1115 | } 1116 | else if (_level < 6){ 1117 | progressPercentage = _level * 100 / 5; 1118 | achievementIdentifier = @"Achievement_Level5Complete"; 1119 | progressInLevelAchievement = YES; 1120 | } 1121 | } 1122 | 1123 | if (progressInLevelAchievement) { 1124 | levelAchievement = [[GKAchievement alloc] initWithIdentifier:achievementIdentifier]; 1125 | levelAchievement.percentComplete = progressPercentage; 1126 | } 1127 | 1128 | 1129 | if (_score <= 50) { 1130 | progressPercentage = _score * 100 / 50; 1131 | achievementIdentifier = @"Achievement_50Points"; 1132 | } 1133 | else if (_score <= 120){ 1134 | progressPercentage = _score * 100 / 120; 1135 | achievementIdentifier = @"Achievement_120Points"; 1136 | } 1137 | else{ 1138 | progressPercentage = _score * 100 / 180; 1139 | achievementIdentifier = @"Achievement_180Points"; 1140 | } 1141 | 1142 | scoreAchievement = [[GKAchievement alloc] initWithIdentifier:achievementIdentifier]; 1143 | scoreAchievement.percentComplete = progressPercentage; 1144 | 1145 | NSArray *achievements = (progressInLevelAchievement) ? @[levelAchievement, scoreAchievement] : @[scoreAchievement]; 1146 | 1147 | [GKAchievement reportAchievements:achievements withCompletionHandler:^(NSError *error) { 1148 | if (error != nil) { 1149 | NSLog(@"%@", [error localizedDescription]); 1150 | } 1151 | }]; 1152 | } 1153 | */ 1154 | 1155 | /* 1156 | 1157 | -(void)resetAchievements{ 1158 | [GKAchievement resetAchievementsWithCompletionHandler:^(NSError *error) { 1159 | if (error != nil) { 1160 | NSLog(@"%@", [error localizedDescription]); 1161 | } 1162 | }]; 1163 | } 1164 | 1165 | */ 1166 | 1167 | /* 1168 | - (IBAction)showGCOptions:(id)sender { 1169 | ... 1170 | 1171 | [_customActionSheet showInView:self.view 1172 | withCompletionHandler:^(NSString *buttonTitle, NSInteger buttonIndex) { 1173 | if ([buttonTitle isEqualToString:@"View Leaderboard"]) { 1174 | ... 1175 | } 1176 | else if ([buttonTitle isEqualToString:@"View Achievements"]) { 1177 | ... 1178 | } 1179 | else{ 1180 | [self resetAchievements]; 1181 | } 1182 | }]; 1183 | .... 1184 | } 1185 | */ 1186 | 1187 | 1188 | /* 1189 | - (IBAction)showGCOptions:(id)sender { 1190 | ... 1191 | [_customActionSheet showInView:self.view 1192 | withCompletionHandler:^(NSString *buttonTitle, NSInteger buttonIndex) { 1193 | 1194 | if ([buttonTitle isEqualToString:@"View Leaderboard"]) { 1195 | [self showLeaderboardAndAchievements:YES]; 1196 | } 1197 | else if ([buttonTitle isEqualToString:@"View Achievements"]) { 1198 | [self showLeaderboardAndAchievements:NO]; 1199 | } 1200 | else{ 1201 | 1202 | } 1203 | }]; 1204 | ... 1205 | }*/ 1206 | @end 1207 | 1208 | 1209 | @implementation MobSvcSavedGameData 1210 | 1211 | #pragma mark MobSvcSavedGameData implementation 1212 | 1213 | static NSString * const sgDataKey = @"data"; 1214 | 1215 | + (instancetype)sharedGameData { 1216 | static id sharedInstance = nil; 1217 | 1218 | static dispatch_once_t onceToken; 1219 | dispatch_once(&onceToken, ^{ 1220 | sharedInstance = [[self alloc] init]; 1221 | }); 1222 | 1223 | return sharedInstance; 1224 | } 1225 | 1226 | - (void)reset 1227 | { 1228 | self.data = nil; 1229 | } 1230 | 1231 | - (void)encodeWithCoder:(NSCoder *)encoder 1232 | { 1233 | [encoder encodeObject:self.data forKey: sgDataKey]; 1234 | } 1235 | 1236 | - (nullable instancetype)initWithCoder:(nonnull NSCoder *)decoder { 1237 | self = [self init]; 1238 | if (self) { 1239 | self.data = [decoder decodeObjectForKey:sgDataKey]; 1240 | } 1241 | return self; 1242 | } 1243 | 1244 | @end 1245 | 1246 | 1247 | 1248 | /* 1249 | 1250 | 1251 | 1252 | #import "GameCenterPlugin.h" 1253 | #import 1254 | 1255 | #define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending) 1256 | 1257 | @interface GameCenterPlugin () 1258 | @property (nonatomic, retain) GKLeaderboardViewController *leaderboardController; 1259 | @property (nonatomic, retain) GKAchievementViewController *achievementsController; 1260 | @end 1261 | 1262 | @implementation GameCenterPlugin 1263 | 1264 | - (void)dealloc { 1265 | self.leaderboardController = nil; 1266 | self.achievementsController = nil; 1267 | 1268 | [super dealloc]; 1269 | } 1270 | 1271 | - (void)authenticateLocalPlayer:(CDVInvokedUrlCommand *)command { 1272 | 1273 | [self.commandDelegate runInBackground:^{ 1274 | 1275 | if (SYSTEM_VERSION_LESS_THAN(@"7.0")) { 1276 | [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) { 1277 | if (error == nil) { 1278 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; 1279 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 1280 | } else { 1281 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[error localizedDescription]]; 1282 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 1283 | } 1284 | }]; 1285 | } else { 1286 | [[GKLocalPlayer localPlayer] setAuthenticateHandler:^(UIViewController *viewcontroller, NSError *error) { 1287 | CDVPluginResult *pluginResult; 1288 | 1289 | if ([GKLocalPlayer localPlayer].authenticated) { 1290 | // Already authenticated 1291 | pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; 1292 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 1293 | } else if (viewcontroller) { 1294 | // Present the login view 1295 | 1296 | CDVViewController *cont = (CDVViewController *)[super viewController]; 1297 | [cont presentViewController:viewcontroller animated:YES completion:^{ 1298 | [self.webView stringByEvaluatingJavaScriptFromString:@"window.gameCenter._viewDidShow()"]; 1299 | }]; 1300 | 1301 | } else { 1302 | // Called the second time with result 1303 | if (error == nil) { 1304 | pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; 1305 | } else { 1306 | pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[error localizedDescription]]; 1307 | } 1308 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 1309 | 1310 | } 1311 | 1312 | }]; 1313 | } 1314 | }]; 1315 | } 1316 | 1317 | - (void)reportScore:(CDVInvokedUrlCommand *)command { 1318 | 1319 | [self.commandDelegate runInBackground:^{ 1320 | NSString *category = (NSString *) [command.arguments objectAtIndex:0]; 1321 | int64_t score = [[command.arguments objectAtIndex:1] integerValue]; 1322 | 1323 | GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:category] autorelease]; 1324 | scoreReporter.value = score; 1325 | 1326 | [scoreReporter reportScoreWithCompletionHandler:^(NSError *error) { 1327 | CDVPluginResult *pluginResult; 1328 | if (!error) { 1329 | pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; 1330 | } else { 1331 | pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[error localizedDescription]]; 1332 | } 1333 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 1334 | }]; 1335 | }]; 1336 | } 1337 | 1338 | - (void)openLeaderboardModal:(CDVInvokedUrlCommand *)command { 1339 | [self.commandDelegate runInBackground:^{ 1340 | if ( self.leaderboardController == nil ) { 1341 | self.leaderboardController = [[GKLeaderboardViewController alloc] init]; 1342 | self.leaderboardController.leaderboardDelegate = self; 1343 | } 1344 | 1345 | self.leaderboardController.category = (NSString *) [command.arguments objectAtIndex:0]; 1346 | CDVViewController *cont = (CDVViewController *)[super viewController]; 1347 | [cont presentViewController:self.leaderboardController animated:YES completion:^{ 1348 | [self.webView stringByEvaluatingJavaScriptFromString:@"window.gameCenter._viewDidShow()"]; 1349 | }]; 1350 | }]; 1351 | } 1352 | 1353 | - (void)openAchievementModal:(CDVInvokedUrlCommand *)command { 1354 | [self.commandDelegate runInBackground:^{ 1355 | if ( self.achievementsController == nil ) { 1356 | self.achievementsController = [[GKAchievementViewController alloc] init]; 1357 | self.achievementsController.achievementDelegate = self; 1358 | } 1359 | 1360 | CDVViewController *cont = (CDVViewController *)[super viewController]; 1361 | [cont presentViewController:self.achievementsController animated:YES completion:^{ 1362 | [self.webView stringByEvaluatingJavaScriptFromString:@"window.gameCenter._viewDidShow()"]; 1363 | }]; 1364 | }]; 1365 | } 1366 | 1367 | - (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController { 1368 | CDVViewController *cont = (CDVViewController *)[super viewController]; 1369 | [cont dismissViewControllerAnimated:YES completion:nil]; 1370 | [self.webView stringByEvaluatingJavaScriptFromString:@"window.gameCenter._viewDidHide()"]; 1371 | } 1372 | 1373 | - (void)achievementViewControllerDidFinish:(GKAchievementViewController *)viewController { 1374 | CDVViewController* cont = (CDVViewController *)[super viewController]; 1375 | [cont dismissViewControllerAnimated:YES completion:nil]; 1376 | [self.webView stringByEvaluatingJavaScriptFromString:@"window.gameCenter._viewDidHide()"]; 1377 | } 1378 | 1379 | - (void)reportAchievementIdentifier:(CDVInvokedUrlCommand *)command { 1380 | [self.commandDelegate runInBackground:^{ 1381 | NSString *identifier = (NSString *) [command.arguments objectAtIndex:0]; 1382 | float percent = [[command.arguments objectAtIndex:1] floatValue]; 1383 | 1384 | GKAchievement *achievement = [[[GKAchievement alloc] initWithIdentifier: identifier] autorelease]; 1385 | if (achievement) { 1386 | achievement.percentComplete = percent; 1387 | [achievement reportAchievementWithCompletionHandler:^(NSError *error) { 1388 | CDVPluginResult *pluginResult; 1389 | if (!error) { 1390 | pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; 1391 | } else { 1392 | pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:[error localizedDescription]]; 1393 | } 1394 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 1395 | }]; 1396 | } else { 1397 | CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Failed to alloc GKAchievement"]; 1398 | [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; 1399 | } 1400 | }]; 1401 | } 1402 | 1403 | @end 1404 | 1405 | 1406 | */ 1407 | --------------------------------------------------------------------------------