PlayGamesPlatform.cs 56 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441
  1. // <copyright file="PlayGamesPlatform.cs" company="Google Inc.">
  2. // Copyright (C) 2014 Google Inc. All Rights Reserved.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. // </copyright>
  16. #if (UNITY_ANDROID || (UNITY_IPHONE && !NO_GPGS))
  17. namespace GooglePlayGames
  18. {
  19. using System;
  20. using System.Collections.Generic;
  21. using GooglePlayGames.BasicApi;
  22. using GooglePlayGames.BasicApi.Events;
  23. using GooglePlayGames.BasicApi.Multiplayer;
  24. using GooglePlayGames.BasicApi.Nearby;
  25. using GooglePlayGames.BasicApi.SavedGame;
  26. using GooglePlayGames.BasicApi.Video;
  27. using GooglePlayGames.OurUtils;
  28. using UnityEngine;
  29. using UnityEngine.SocialPlatforms;
  30. /// <summary>
  31. /// Provides access to the Google Play Games platform. This is an implementation of
  32. /// UnityEngine.SocialPlatforms.ISocialPlatform. Activate this platform by calling
  33. /// the <see cref="Activate" /> method, then authenticate by calling
  34. /// the <see cref="Authenticate" /> method. After authentication
  35. /// completes, you may call the other methods of this class. This is not a complete
  36. /// implementation of the ISocialPlatform interface. Methods lacking an implementation
  37. /// or whose behavior is at variance with the standard are noted as such.
  38. /// </summary>
  39. public class PlayGamesPlatform : ISocialPlatform
  40. {
  41. /// <summary>Singleton instance</summary>
  42. private static volatile PlayGamesPlatform sInstance = null;
  43. /// <summary>status of nearby connection initialization.</summary>
  44. private static volatile bool sNearbyInitializePending;
  45. /// <summary>Reference to the nearby client.</summary>
  46. /// <remarks>This is static since it can be used without using play game services.</remarks>
  47. private static volatile INearbyConnectionClient sNearbyConnectionClient;
  48. /// <summary>Configuration used to create this instance.</summary>
  49. private readonly PlayGamesClientConfiguration mConfiguration;
  50. /// <summary>The local user.</summary>
  51. private PlayGamesLocalUser mLocalUser = null;
  52. /// <summary>Reference to the platform specific implementation.</summary>
  53. private IPlayGamesClient mClient = null;
  54. /// <summary>the default leaderboard we show on ShowLeaderboardUI</summary>
  55. private string mDefaultLbUi = null;
  56. /// <summary>the mapping table from alias to leaderboard/achievement id.</summary>
  57. private Dictionary<string, string> mIdMap = new Dictionary<string, string>();
  58. /// <summary>
  59. /// Initializes a new instance of the <see cref="GooglePlayGames.PlayGamesPlatform"/> class.
  60. /// </summary>
  61. /// <param name="client">Implementation client to use for this instance.</param>
  62. internal PlayGamesPlatform(IPlayGamesClient client)
  63. {
  64. this.mClient = Misc.CheckNotNull(client);
  65. this.mLocalUser = new PlayGamesLocalUser(this);
  66. this.mConfiguration = PlayGamesClientConfiguration.DefaultConfiguration;
  67. }
  68. /// <summary>
  69. /// Initializes a new instance of the <see cref="GooglePlayGames.PlayGamesPlatform"/> class.
  70. /// </summary>
  71. /// <param name="configuration">Configuration object to use.</param>
  72. private PlayGamesPlatform(PlayGamesClientConfiguration configuration)
  73. {
  74. GooglePlayGames.OurUtils.Logger.w("Creating new PlayGamesPlatform");
  75. this.mLocalUser = new PlayGamesLocalUser(this);
  76. this.mConfiguration = configuration;
  77. }
  78. /// <summary>
  79. /// Gets or sets a value indicating whether debug logs are enabled. This property
  80. /// may be set before calling <see cref="Activate" /> method.
  81. /// </summary>
  82. /// <returns>
  83. /// <c>true</c> if debug log enabled; otherwise, <c>false</c>.
  84. /// </returns>
  85. public static bool DebugLogEnabled
  86. {
  87. get
  88. {
  89. return GooglePlayGames.OurUtils.Logger.DebugLogEnabled;
  90. }
  91. set
  92. {
  93. GooglePlayGames.OurUtils.Logger.DebugLogEnabled = value;
  94. }
  95. }
  96. /// <summary>
  97. /// Gets the singleton instance of the Play Games platform.
  98. /// </summary>
  99. /// <returns>
  100. /// The instance.
  101. /// </returns>
  102. public static PlayGamesPlatform Instance
  103. {
  104. get
  105. {
  106. if (sInstance == null)
  107. {
  108. GooglePlayGames.OurUtils.Logger.d(
  109. "Instance was not initialized, using default configuration.");
  110. InitializeInstance(PlayGamesClientConfiguration.DefaultConfiguration);
  111. }
  112. return sInstance;
  113. }
  114. }
  115. /// <summary>
  116. /// Gets the nearby connection client. NOTE: Can be null until the nearby client
  117. /// is initialized. Call InitializeNearby to use callback to be notified when initialization
  118. /// is complete.
  119. /// </summary>
  120. /// <value>The nearby.</value>
  121. public static INearbyConnectionClient Nearby
  122. {
  123. get
  124. {
  125. if (sNearbyConnectionClient == null && !sNearbyInitializePending)
  126. {
  127. sNearbyInitializePending = true;
  128. InitializeNearby(null);
  129. }
  130. return sNearbyConnectionClient;
  131. }
  132. }
  133. /// <summary> Gets the real time multiplayer API object</summary>
  134. public IRealTimeMultiplayerClient RealTime
  135. {
  136. get
  137. {
  138. return mClient.GetRtmpClient();
  139. }
  140. }
  141. /// <summary> Gets the turn based multiplayer API object</summary>
  142. public ITurnBasedMultiplayerClient TurnBased
  143. {
  144. get
  145. {
  146. return mClient.GetTbmpClient();
  147. }
  148. }
  149. /// <summary>Gets the saved game client object.</summary>
  150. /// <value>The saved game client.</value>
  151. public ISavedGameClient SavedGame
  152. {
  153. get
  154. {
  155. return mClient.GetSavedGameClient();
  156. }
  157. }
  158. /// <summary>Gets the events client object.</summary>
  159. /// <value>The events client.</value>
  160. public IEventsClient Events
  161. {
  162. get
  163. {
  164. return mClient.GetEventsClient();
  165. }
  166. }
  167. /// <summary>Gets the video client object.</summary>
  168. /// <value>The video client.</value>
  169. public IVideoClient Video
  170. {
  171. get
  172. {
  173. return mClient.GetVideoClient();
  174. }
  175. }
  176. /// <summary>
  177. /// Gets the local user.
  178. /// </summary>
  179. /// <returns>
  180. /// The local user.
  181. /// </returns>
  182. public ILocalUser localUser
  183. {
  184. get
  185. {
  186. return mLocalUser;
  187. }
  188. }
  189. /// <summary>
  190. /// Initializes the instance of Play Game Services platform.
  191. /// </summary>
  192. /// <remarks>This creates the singleton instance of the platform.
  193. /// Multiple calls to this method are ignored.
  194. /// </remarks>
  195. /// <param name="configuration">Configuration to use when initializing.</param>
  196. public static void InitializeInstance(PlayGamesClientConfiguration configuration)
  197. {
  198. if (sInstance != null)
  199. {
  200. GooglePlayGames.OurUtils.Logger.w(
  201. "PlayGamesPlatform already initialized. Ignoring this call.");
  202. return;
  203. }
  204. sInstance = new PlayGamesPlatform(configuration);
  205. }
  206. /// <summary>
  207. /// Initializes the nearby connection platform.
  208. /// </summary>
  209. /// <remarks>This call initializes the nearby connection platform. This
  210. /// is independent of the Play Game Services initialization. Multiple
  211. /// calls to this method are ignored.
  212. /// </remarks>
  213. /// <param name="callback">Callback invoked when complete.</param>
  214. public static void InitializeNearby(Action<INearbyConnectionClient> callback)
  215. {
  216. Debug.Log("Calling InitializeNearby!");
  217. if (sNearbyConnectionClient == null)
  218. {
  219. #if UNITY_ANDROID && !UNITY_EDITOR
  220. NearbyConnectionClientFactory.Create(client => {
  221. Debug.Log("Nearby Client Created!!");
  222. sNearbyConnectionClient = client;
  223. if (callback != null) {
  224. callback.Invoke(client);
  225. }
  226. else {
  227. Debug.Log("Initialize Nearby callback is null");
  228. }
  229. });
  230. #else
  231. sNearbyConnectionClient = new DummyNearbyConnectionClient();
  232. if (callback != null)
  233. {
  234. callback.Invoke(sNearbyConnectionClient);
  235. }
  236. #endif
  237. }
  238. else if (callback != null)
  239. {
  240. Debug.Log("Nearby Already initialized: calling callback directly");
  241. callback.Invoke(sNearbyConnectionClient);
  242. }
  243. else
  244. {
  245. Debug.Log("Nearby Already initialized");
  246. }
  247. }
  248. /// <summary>
  249. /// Activates the Play Games platform as the implementation of Social.Active.
  250. /// After calling this method, you can call methods on Social.Active. For
  251. /// example, <c>Social.Active.Authenticate()</c>.
  252. /// </summary>
  253. /// <returns>The singleton <see cref="PlayGamesPlatform" /> instance.</returns>
  254. public static PlayGamesPlatform Activate()
  255. {
  256. GooglePlayGames.OurUtils.Logger.d("Activating PlayGamesPlatform.");
  257. Social.Active = PlayGamesPlatform.Instance;
  258. GooglePlayGames.OurUtils.Logger.d(
  259. "PlayGamesPlatform activated: " + Social.Active);
  260. return PlayGamesPlatform.Instance;
  261. }
  262. /// <summary>Gets pointer to the Google API client.</summary>
  263. /// <remarks>This is provided as a helper to making additional JNI calls.
  264. /// This connection is initialized and controlled by the underlying SDK.
  265. /// </remarks>
  266. /// <returns>The pointer of the client. Zero on non-android platforms.</returns>
  267. public IntPtr GetApiClient()
  268. {
  269. return mClient.GetApiClient();
  270. }
  271. /// <summary>
  272. /// Sets the gravity for popups (Android only).
  273. /// </summary>
  274. /// <remarks>This can only be called after authentication. It affects
  275. /// popups for achievements and other game services elements.</remarks>
  276. /// <param name="gravity">Gravity for the popup.</param>
  277. public void SetGravityForPopups(Gravity gravity) {
  278. mClient.SetGravityForPopups(gravity);
  279. }
  280. /// <summary>
  281. /// Specifies that the ID <c>fromId</c> should be implicitly replaced by <c>toId</c>
  282. /// on any calls that take a leaderboard or achievement ID.
  283. /// </summary>
  284. /// <remarks> After a mapping is
  285. /// registered, you can use <c>fromId</c> instead of <c>toId</c> when making a call.
  286. /// For example, the following two snippets are equivalent:
  287. /// <code>
  288. /// ReportProgress("Cfiwjew894_AQ", 100.0, callback);
  289. /// </code>
  290. /// ...is equivalent to:
  291. /// <code>
  292. /// AddIdMapping("super-combo", "Cfiwjew894_AQ");
  293. /// ReportProgress("super-combo", 100.0, callback);
  294. /// </code>
  295. /// </remarks>
  296. /// <param name='fromId'>
  297. /// The identifier to map.
  298. /// </param>
  299. /// <param name='toId'>
  300. /// The identifier that <c>fromId</c> will be mapped to.
  301. /// </param>
  302. public void AddIdMapping(string fromId, string toId)
  303. {
  304. mIdMap[fromId] = toId;
  305. }
  306. /// <summary>
  307. /// Authenticate the local user with the Google Play Games service.
  308. /// </summary>
  309. /// <param name='callback'>
  310. /// The callback to call when authentication finishes. It will be called
  311. /// with <c>true</c> if authentication was successful, <c>false</c>
  312. /// otherwise.
  313. /// </param>
  314. public void Authenticate(Action<bool> callback)
  315. {
  316. Authenticate(callback, false);
  317. }
  318. /// <summary>
  319. /// Authenticate the local user with the Google Play Games service.
  320. /// </summary>
  321. /// <param name='callback'>
  322. /// The callback to call when authentication finishes. It will be called
  323. /// with <c>true</c> if authentication was successful, <c>false</c>
  324. /// otherwise.
  325. /// </param>
  326. public void Authenticate(Action<bool, string> callback)
  327. {
  328. Authenticate(callback, false);
  329. }
  330. /// <summary>
  331. /// Authenticate the local user with the Google Play Games service.
  332. /// </summary>
  333. /// <param name='callback'>
  334. /// The callback to call when authentication finishes. It will be called
  335. /// with <c>true</c> if authentication was successful, <c>false</c>
  336. /// otherwise.
  337. /// </param>
  338. /// <param name='silent'>
  339. /// Indicates whether authentication should be silent. If <c>false</c>,
  340. /// authentication may show popups and interact with the user to obtain
  341. /// authorization. If <c>true</c>, there will be no popups or interaction with
  342. /// the user, and the authentication will fail instead if such interaction
  343. /// is required. A typical pattern is to try silent authentication on startup
  344. /// and, if that fails, present the user with a "Sign in" button that then
  345. /// triggers normal (not silent) authentication.
  346. /// </param>
  347. public void Authenticate(Action<bool> callback, bool silent)
  348. {
  349. Authenticate((bool success, string msg) => callback(success), silent);
  350. }
  351. /// <summary>
  352. /// Authenticate the local user with the Google Play Games service.
  353. /// </summary>
  354. /// <param name='callback'>
  355. /// The callback to call when authentication finishes. It will be called
  356. /// with <c>true</c> if authentication was successful, <c>false</c>
  357. /// otherwise.
  358. /// </param>
  359. /// <param name='silent'>
  360. /// Indicates whether authentication should be silent. If <c>false</c>,
  361. /// authentication may show popups and interact with the user to obtain
  362. /// authorization. If <c>true</c>, there will be no popups or interaction with
  363. /// the user, and the authentication will fail instead if such interaction
  364. /// is required. A typical pattern is to try silent authentication on startup
  365. /// and, if that fails, present the user with a "Sign in" button that then
  366. /// triggers normal (not silent) authentication.
  367. /// </param>
  368. public void Authenticate(Action<bool, string> callback, bool silent)
  369. {
  370. // make a platform-specific Play Games client
  371. if (mClient == null)
  372. {
  373. GooglePlayGames.OurUtils.Logger.d(
  374. "Creating platform-specific Play Games client.");
  375. mClient = PlayGamesClientFactory.GetPlatformPlayGamesClient(mConfiguration);
  376. }
  377. // authenticate!
  378. mClient.Authenticate(callback, silent);
  379. }
  380. /// <summary>
  381. /// Provided for compatibility with ISocialPlatform.
  382. /// </summary>
  383. /// <seealso cref="Authenticate(Action&lt;bool&gt;,bool)"/>
  384. /// <param name="unused">Unused parameter for this implementation.</param>
  385. /// <param name="callback">Callback invoked when complete.</param>
  386. public void Authenticate(ILocalUser unused, Action<bool> callback)
  387. {
  388. Authenticate(callback, false);
  389. }
  390. /// <summary>
  391. /// Provided for compatibility with ISocialPlatform.
  392. /// </summary>
  393. /// <seealso cref="Authenticate(Action&lt;bool&gt;,bool)"/>
  394. /// <param name="unused">Unused parameter for this implementation.</param>
  395. /// <param name="callback">Callback invoked when complete.</param>
  396. public void Authenticate(ILocalUser unused, Action<bool, string> callback)
  397. {
  398. Authenticate(callback, false);
  399. }
  400. /// <summary>
  401. /// Determines whether the user is authenticated.
  402. /// </summary>
  403. /// <returns>
  404. /// <c>true</c> if the user is authenticated; otherwise, <c>false</c>.
  405. /// </returns>
  406. public bool IsAuthenticated()
  407. {
  408. return mClient != null && mClient.IsAuthenticated();
  409. }
  410. /// <summary>Sign out. After signing out,
  411. /// Authenticate must be called again to sign back in.
  412. /// </summary>
  413. public void SignOut()
  414. {
  415. if (mClient != null)
  416. {
  417. mClient.SignOut();
  418. }
  419. mLocalUser = new PlayGamesLocalUser(this);
  420. }
  421. /// <summary>
  422. /// Loads the users.
  423. /// </summary>
  424. /// <param name="userIds">User identifiers.</param>
  425. /// <param name="callback">Callback invoked when complete.</param>
  426. public void LoadUsers(string[] userIds, Action<IUserProfile[]> callback)
  427. {
  428. if (!IsAuthenticated())
  429. {
  430. GooglePlayGames.OurUtils.Logger.e(
  431. "GetUserId() can only be called after authentication.");
  432. callback(new IUserProfile[0]);
  433. return;
  434. }
  435. mClient.LoadUsers(userIds, callback);
  436. }
  437. /// <summary>
  438. /// Returns the user's Google ID.
  439. /// </summary>
  440. /// <returns>
  441. /// The user's Google ID. No guarantees are made as to the meaning or format of
  442. /// this identifier except that it is unique to the user who is signed in.
  443. /// </returns>
  444. public string GetUserId()
  445. {
  446. if (!IsAuthenticated())
  447. {
  448. GooglePlayGames.OurUtils.Logger.e(
  449. "GetUserId() can only be called after authentication.");
  450. return "0";
  451. }
  452. return mClient.GetUserId();
  453. }
  454. /// <summary>
  455. /// Get an id token for the user.
  456. /// </summary>
  457. public string GetIdToken()
  458. {
  459. if (mClient != null)
  460. {
  461. return mClient.GetIdToken();
  462. }
  463. OurUtils.Logger.e("No client available, returning null.");
  464. return null;
  465. }
  466. /// <summary>
  467. /// Gets the server auth code.
  468. /// </summary>
  469. /// <remarks>This code is used by the server application in order to get
  470. /// an oauth token. For how to use this acccess token please see:
  471. /// https://developers.google.com/drive/v2/web/auth/web-server.
  472. /// To get another server auth code after the initial one returned, call
  473. /// GetAnotherServerAuthCode().
  474. /// </remarks>
  475. public string GetServerAuthCode()
  476. {
  477. if (mClient != null && mClient.IsAuthenticated())
  478. {
  479. return mClient.GetServerAuthCode();
  480. }
  481. return null;
  482. }
  483. /// <summary>
  484. /// Gets another server auth code.
  485. /// </summary>
  486. /// <remarks>This method should be called after authenticating, and exchanging
  487. /// the initial server auth code for a token. This is implemented by signing in
  488. /// silently, which if successful returns almost immediately and with a new
  489. /// server auth code.
  490. /// </remarks>
  491. /// <param name="reAuthenticateIfNeeded">Calls Authenticate if needed when
  492. /// retrieving another auth code. </param>
  493. /// <param name="callback">Callback returning the auth code or null
  494. /// if there was an error. NOTE: This callback can return immediately.</param>
  495. public void GetAnotherServerAuthCode(bool reAuthenticateIfNeeded,
  496. Action<string> callback)
  497. {
  498. if(mClient != null && mClient.IsAuthenticated()) {
  499. mClient.GetAnotherServerAuthCode(reAuthenticateIfNeeded, callback);
  500. }
  501. else if (mClient != null && reAuthenticateIfNeeded)
  502. {
  503. mClient.Authenticate((success, msg) => {
  504. if (success) {
  505. callback(mClient.GetServerAuthCode());
  506. } else {
  507. OurUtils.Logger.e("Re-authentication failed: " + msg);
  508. callback(null);
  509. }
  510. }, false);
  511. }
  512. else
  513. {
  514. OurUtils.Logger.e("Cannot call GetAnotherServerAuthCode: not authenticated");
  515. callback(null);
  516. }
  517. }
  518. /// <summary>
  519. /// Gets the user's email.
  520. /// </summary>
  521. public string GetUserEmail()
  522. {
  523. return mClient.GetUserEmail();
  524. }
  525. /// <summary>
  526. /// Gets the player stats.
  527. /// </summary>
  528. /// <param name="callback">Callback invoked when completed.</param>
  529. public void GetPlayerStats(Action<CommonStatusCodes, PlayerStats> callback)
  530. {
  531. if (mClient != null && mClient.IsAuthenticated())
  532. {
  533. mClient.GetPlayerStats(callback);
  534. }
  535. else
  536. {
  537. GooglePlayGames.OurUtils.Logger.e(
  538. "GetPlayerStats can only be called after authentication.");
  539. callback(CommonStatusCodes.SignInRequired, new PlayerStats());
  540. }
  541. }
  542. /// <summary>
  543. /// Returns the achievement corresponding to the passed achievement identifier.
  544. /// </summary>
  545. /// <returns>
  546. /// The achievement corresponding to the identifer. <code>null</code> if no such
  547. /// achievement is found or if the user is not authenticated.
  548. /// </returns>
  549. /// <param name="achievementId">
  550. /// The identifier of the achievement.
  551. /// </param>
  552. public Achievement GetAchievement(string achievementId)
  553. {
  554. if (!IsAuthenticated())
  555. {
  556. GooglePlayGames.OurUtils.Logger.e(
  557. "GetAchievement can only be called after authentication.");
  558. return null;
  559. }
  560. return mClient.GetAchievement(achievementId);
  561. }
  562. /// <summary>
  563. /// Returns the user's display name.
  564. /// </summary>
  565. /// <returns>
  566. /// The user display name (e.g. "Bruno Oliveira")
  567. /// </returns>
  568. public string GetUserDisplayName()
  569. {
  570. if (!IsAuthenticated())
  571. {
  572. GooglePlayGames.OurUtils.Logger.e(
  573. "GetUserDisplayName can only be called after authentication.");
  574. return string.Empty;
  575. }
  576. return mClient.GetUserDisplayName();
  577. }
  578. /// <summary>
  579. /// Returns the user's avatar URL if they have one.
  580. /// </summary>
  581. /// <returns>
  582. /// The URL, or <code>null</code> if the user is not authenticated or does not have
  583. /// an avatar.
  584. /// </returns>
  585. public string GetUserImageUrl()
  586. {
  587. if (!IsAuthenticated())
  588. {
  589. GooglePlayGames.OurUtils.Logger.e(
  590. "GetUserImageUrl can only be called after authentication.");
  591. return null;
  592. }
  593. return mClient.GetUserImageUrl();
  594. }
  595. /// <summary>
  596. /// Reports the progress of an achievement (reveal, unlock or increment). This method attempts
  597. /// to implement the expected behavior of ISocialPlatform.ReportProgress as closely as possible,
  598. /// as described below. Although this method works with incremental achievements for compatibility
  599. /// purposes, calling this method for incremental achievements is not recommended,
  600. /// since the Play Games API exposes incremental achievements in a very different way
  601. /// than the interface presented by ISocialPlatform.ReportProgress. The implementation of this
  602. /// method for incremental achievements attempts to produce the correct result, but may be
  603. /// imprecise. If possible, call <see cref="IncrementAchievement" /> instead.
  604. /// </summary>
  605. /// <param name='achievementID'>
  606. /// The ID of the achievement to unlock, reveal or increment. This can be a raw Google Play
  607. /// Games achievement ID (alphanumeric string), or an alias that was previously configured
  608. /// by a call to <see cref="AddIdMapping" />.
  609. /// </param>
  610. /// <param name='progress'>
  611. /// Progress of the achievement. If the achievement is standard (not incremental), then
  612. /// a progress of 0.0 will reveal the achievement and 100.0 will unlock it. Behavior of other
  613. /// values is undefined. If the achievement is incremental, then this value is interpreted
  614. /// as the total percentage of the achievement's progress that the player should have
  615. /// as a result of this call (regardless of the progress they had before). So if the
  616. /// player's previous progress was 30% and this call specifies 50.0, the new progress will
  617. /// be 50% (not 80%).
  618. /// </param>
  619. /// <param name='callback'>
  620. /// Callback that will be called to report the result of the operation: <c>true</c> on
  621. /// success, <c>false</c> otherwise.
  622. /// </param>
  623. public void ReportProgress(string achievementID, double progress, Action<bool> callback)
  624. {
  625. if (!IsAuthenticated())
  626. {
  627. GooglePlayGames.OurUtils.Logger.e(
  628. "ReportProgress can only be called after authentication.");
  629. if (callback != null)
  630. {
  631. callback.Invoke(false);
  632. }
  633. return;
  634. }
  635. // map ID, if it's in the dictionary
  636. GooglePlayGames.OurUtils.Logger.d(
  637. "ReportProgress, " + achievementID + ", " + progress);
  638. achievementID = MapId(achievementID);
  639. // if progress is 0.0, we just want to reveal it
  640. if (progress < 0.000001)
  641. {
  642. GooglePlayGames.OurUtils.Logger.d(
  643. "Progress 0.00 interpreted as request to reveal.");
  644. mClient.RevealAchievement(achievementID, callback);
  645. return;
  646. }
  647. // figure out if it's a standard or incremental achievement
  648. bool isIncremental = false;
  649. int curSteps = 0, totalSteps = 0;
  650. Achievement ach = mClient.GetAchievement(achievementID);
  651. if (ach == null)
  652. {
  653. GooglePlayGames.OurUtils.Logger.w(
  654. "Unable to locate achievement " + achievementID);
  655. GooglePlayGames.OurUtils.Logger.w(
  656. "As a quick fix, assuming it's standard.");
  657. isIncremental = false;
  658. }
  659. else
  660. {
  661. isIncremental = ach.IsIncremental;
  662. curSteps = ach.CurrentSteps;
  663. totalSteps = ach.TotalSteps;
  664. GooglePlayGames.OurUtils.Logger.d(
  665. "Achievement is " + (isIncremental ? "INCREMENTAL" : "STANDARD"));
  666. if (isIncremental)
  667. {
  668. GooglePlayGames.OurUtils.Logger.d(
  669. "Current steps: " + curSteps + "/" + totalSteps);
  670. }
  671. }
  672. // do the right thing depending on the achievement type
  673. if (isIncremental)
  674. {
  675. // increment it to the target percentage (approximate)
  676. GooglePlayGames.OurUtils.Logger.d("Progress " + progress +
  677. " interpreted as incremental target (approximate).");
  678. if (progress >= 0.0 && progress <= 1.0)
  679. {
  680. // in a previous version, incremental progress was reported by using the range [0-1]
  681. GooglePlayGames.OurUtils.Logger.w(
  682. "Progress " + progress +
  683. " is less than or equal to 1. You might be trying to use values in the range of [0,1], while values are expected to be within the range [0,100]. If you are using the latter, you can safely ignore this message.");
  684. }
  685. int targetSteps = (int)Math.Round((progress / 100f) * totalSteps);
  686. int numSteps = targetSteps - curSteps;
  687. GooglePlayGames.OurUtils.Logger.d("Target steps: " +
  688. targetSteps + ", cur steps:" + curSteps);
  689. GooglePlayGames.OurUtils.Logger.d("Steps to increment: " +
  690. numSteps);
  691. // handle incremental achievements with 0 steps
  692. if (numSteps >= 0)
  693. {
  694. mClient.IncrementAchievement(achievementID, numSteps, callback);
  695. }
  696. }
  697. else if (progress >= 100)
  698. {
  699. // unlock it!
  700. GooglePlayGames.OurUtils.Logger.d(
  701. "Progress " + progress + " interpreted as UNLOCK.");
  702. mClient.UnlockAchievement(achievementID, callback);
  703. }
  704. else
  705. {
  706. // not enough to unlock
  707. GooglePlayGames.OurUtils.Logger.d("Progress " + progress +
  708. " not enough to unlock non-incremental achievement.");
  709. }
  710. }
  711. /// <summary>
  712. /// Reveals the achievement with the passed identifier. This is a Play Games extension of the ISocialPlatform API.
  713. /// </summary>
  714. /// <remarks>If the operation succeeds, the callback
  715. /// will be invoked on the game thread with <code>true</code>. If the operation fails, the
  716. /// callback will be invoked with <code>false</code>. This operation will immediately fail if
  717. /// the user is not authenticated (i.e. the callback will immediately be invoked with
  718. /// <code>false</code>). If the achievement is already in a revealed state, this call will
  719. /// succeed immediately.
  720. /// </remarks>
  721. /// <param name='achievementID'>
  722. /// The ID of the achievement to increment. This can be a raw Google Play
  723. /// Games achievement ID (alphanumeric string), or an alias that was previously configured
  724. /// by a call to <see cref="AddIdMapping" />.
  725. /// </param>
  726. /// <param name='callback'>
  727. /// The callback to call to report the success or failure of the operation. The callback
  728. /// will be called with <c>true</c> to indicate success or <c>false</c> for failure.
  729. /// </param>
  730. public void RevealAchievement(string achievementID, Action<bool> callback = null)
  731. {
  732. if (!IsAuthenticated())
  733. {
  734. GooglePlayGames.OurUtils.Logger.e(
  735. "RevealAchievement can only be called after authentication.");
  736. if (callback != null)
  737. {
  738. callback.Invoke(false);
  739. }
  740. return;
  741. }
  742. // map ID, if it's in the dictionary
  743. GooglePlayGames.OurUtils.Logger.d(
  744. "RevealAchievement: " + achievementID);
  745. achievementID = MapId(achievementID);
  746. mClient.RevealAchievement(achievementID, callback);
  747. }
  748. /// <summary>
  749. /// Unlocks the achievement with the passed identifier. This is a Play Games extension of the ISocialPlatform API.
  750. /// </summary>
  751. /// <remarks>If the operation succeeds, the callback
  752. /// will be invoked on the game thread with <code>true</code>. If the operation fails, the
  753. /// callback will be invoked with <code>false</code>. This operation will immediately fail if
  754. /// the user is not authenticated (i.e. the callback will immediately be invoked with
  755. /// <code>false</code>). If the achievement is already unlocked, this call will
  756. /// succeed immediately.
  757. /// </remarks>
  758. /// <param name='achievementID'>
  759. /// The ID of the achievement to increment. This can be a raw Google Play
  760. /// Games achievement ID (alphanumeric string), or an alias that was previously configured
  761. /// by a call to <see cref="AddIdMapping" />.
  762. /// </param>
  763. /// <param name='callback'>
  764. /// The callback to call to report the success or failure of the operation. The callback
  765. /// will be called with <c>true</c> to indicate success or <c>false</c> for failure.
  766. /// </param>
  767. public void UnlockAchievement(string achievementID, Action<bool> callback = null)
  768. {
  769. if (!IsAuthenticated())
  770. {
  771. GooglePlayGames.OurUtils.Logger.e(
  772. "UnlockAchievement can only be called after authentication.");
  773. if (callback != null)
  774. {
  775. callback.Invoke(false);
  776. }
  777. return;
  778. }
  779. // map ID, if it's in the dictionary
  780. GooglePlayGames.OurUtils.Logger.d(
  781. "UnlockAchievement: " + achievementID);
  782. achievementID = MapId(achievementID);
  783. mClient.UnlockAchievement(achievementID, callback);
  784. }
  785. /// <summary>
  786. /// Increments an achievement. This is a Play Games extension of the ISocialPlatform API.
  787. /// </summary>
  788. /// <param name='achievementID'>
  789. /// The ID of the achievement to increment. This can be a raw Google Play
  790. /// Games achievement ID (alphanumeric string), or an alias that was previously configured
  791. /// by a call to <see cref="AddIdMapping" />.
  792. /// </param>
  793. /// <param name='steps'>
  794. /// The number of steps to increment the achievement by.
  795. /// </param>
  796. /// <param name='callback'>
  797. /// The callback to call to report the success or failure of the operation. The callback
  798. /// will be called with <c>true</c> to indicate success or <c>false</c> for failure.
  799. /// </param>
  800. public void IncrementAchievement(string achievementID, int steps, Action<bool> callback)
  801. {
  802. if (!IsAuthenticated())
  803. {
  804. GooglePlayGames.OurUtils.Logger.e(
  805. "IncrementAchievement can only be called after authentication.");
  806. if (callback != null)
  807. {
  808. callback.Invoke(false);
  809. }
  810. return;
  811. }
  812. // map ID, if it's in the dictionary
  813. GooglePlayGames.OurUtils.Logger.d(
  814. "IncrementAchievement: " + achievementID + ", steps " + steps);
  815. achievementID = MapId(achievementID);
  816. mClient.IncrementAchievement(achievementID, steps, callback);
  817. }
  818. /// <summary>
  819. /// Set an achievement to have at least the given number of steps completed.
  820. /// Calling this method while the achievement already has more steps than
  821. /// the provided value is a no-op. Once the achievement reaches the
  822. /// maximum number of steps, the achievement is automatically unlocked,
  823. /// and any further mutation operations are ignored.
  824. /// </summary>
  825. /// <param name='achievementID'>
  826. /// The ID of the achievement to increment. This can be a raw Google Play
  827. /// Games achievement ID (alphanumeric string), or an alias that was previously configured
  828. /// by a call to <see cref="AddIdMapping" />.
  829. /// </param>
  830. /// <param name='steps'>
  831. /// The number of steps to increment the achievement by.
  832. /// </param>
  833. /// <param name='callback'>
  834. /// The callback to call to report the success or failure of the operation. The callback
  835. /// will be called with <c>true</c> to indicate success or <c>false</c> for failure.
  836. /// </param>
  837. public void SetStepsAtLeast(string achievementID, int steps, Action<bool> callback)
  838. {
  839. if (!IsAuthenticated())
  840. {
  841. GooglePlayGames.OurUtils.Logger.e(
  842. "SetStepsAtLeast can only be called after authentication.");
  843. if (callback != null)
  844. {
  845. callback.Invoke(false);
  846. }
  847. return;
  848. }
  849. // map ID, if it's in the dictionary
  850. GooglePlayGames.OurUtils.Logger.d(
  851. "SetStepsAtLeast: " + achievementID + ", steps " + steps);
  852. achievementID = MapId(achievementID);
  853. mClient.SetStepsAtLeast(achievementID, steps, callback);
  854. }
  855. /// <summary>
  856. /// Loads the Achievement descriptions.
  857. /// </summary>
  858. /// <param name="callback">The callback to receive the descriptions</param>
  859. public void LoadAchievementDescriptions(Action<IAchievementDescription[]> callback)
  860. {
  861. if (!IsAuthenticated())
  862. {
  863. GooglePlayGames.OurUtils.Logger.e(
  864. "LoadAchievementDescriptions can only be called after authentication.");
  865. if (callback != null)
  866. {
  867. callback.Invoke(null);
  868. }
  869. return;
  870. }
  871. mClient.LoadAchievements(ach =>
  872. {
  873. IAchievementDescription[] data = new IAchievementDescription[ach.Length];
  874. for (int i = 0; i < data.Length; i++)
  875. {
  876. data[i] = new PlayGamesAchievement(ach[i]);
  877. }
  878. callback.Invoke(data);
  879. });
  880. }
  881. /// <summary>
  882. /// Loads the achievement state for the current user.
  883. /// </summary>
  884. /// <param name="callback">The callback to receive the achievements</param>
  885. public void LoadAchievements(Action<IAchievement[]> callback)
  886. {
  887. if (!IsAuthenticated())
  888. {
  889. GooglePlayGames.OurUtils.Logger.e("LoadAchievements can only be called after authentication.");
  890. callback.Invoke(null);
  891. return;
  892. }
  893. mClient.LoadAchievements(ach =>
  894. {
  895. IAchievement[] data = new IAchievement[ach.Length];
  896. for (int i = 0; i < data.Length; i++)
  897. {
  898. data[i] = new PlayGamesAchievement(ach[i]);
  899. }
  900. callback.Invoke(data);
  901. });
  902. }
  903. /// <summary>
  904. /// Creates an achievement object which may be subsequently used to report an
  905. /// achievement.
  906. /// </summary>
  907. /// <returns>
  908. /// The achievement object.
  909. /// </returns>
  910. public IAchievement CreateAchievement()
  911. {
  912. return new PlayGamesAchievement();
  913. }
  914. /// <summary>
  915. /// Reports a score to a leaderboard.
  916. /// </summary>
  917. /// <param name='score'>
  918. /// The score to report.
  919. /// </param>
  920. /// <param name='board'>
  921. /// The ID of the leaderboard on which the score is to be posted. This may be a raw
  922. /// Google Play Games leaderboard ID or an alias configured through a call to
  923. /// <see cref="AddIdMapping" />.
  924. /// </param>
  925. /// <param name='callback'>
  926. /// The callback to call to report the success or failure of the operation. The callback
  927. /// will be called with <c>true</c> to indicate success or <c>false</c> for failure.
  928. /// </param>
  929. public void ReportScore(long score, string board, Action<bool> callback)
  930. {
  931. if (!IsAuthenticated())
  932. {
  933. GooglePlayGames.OurUtils.Logger.e("ReportScore can only be called after authentication.");
  934. if (callback != null)
  935. {
  936. callback.Invoke(false);
  937. }
  938. return;
  939. }
  940. GooglePlayGames.OurUtils.Logger.d("ReportScore: score=" + score + ", board=" + board);
  941. string leaderboardId = MapId(board);
  942. mClient.SubmitScore(leaderboardId, score, callback);
  943. }
  944. /// <summary>
  945. /// Submits the score for the currently signed-in player
  946. /// to the leaderboard associated with a specific id
  947. /// and metadata (such as something the player did to earn the score).
  948. /// </summary>
  949. /// <param name="score">Score to report.</param>
  950. /// <param name="board">leaderboard id.</param>
  951. /// <param name="metadata">metadata about the score.</param>
  952. /// <param name="callback">Callback invoked upon completion.</param>
  953. public void ReportScore(long score, string board, string metadata, Action<bool> callback)
  954. {
  955. if (!IsAuthenticated())
  956. {
  957. GooglePlayGames.OurUtils.Logger.e("ReportScore can only be called after authentication.");
  958. if (callback != null)
  959. {
  960. callback.Invoke(false);
  961. }
  962. return;
  963. }
  964. GooglePlayGames.OurUtils.Logger.d("ReportScore: score=" + score +
  965. ", board=" + board +
  966. " metadata=" + metadata);
  967. string leaderboardId = MapId(board);
  968. mClient.SubmitScore(leaderboardId, score, metadata, callback);
  969. }
  970. /// <summary>
  971. /// Loads the scores relative the player.
  972. /// </summary>
  973. /// <remarks>This returns the 25
  974. /// (which is the max results returned by the SDK per call) scores
  975. /// that are around the player's score on the Public, all time leaderboard.
  976. /// Use the overloaded methods which are specific to GPGS to modify these
  977. /// parameters.
  978. /// </remarks>
  979. /// <param name="leaderboardId">Leaderboard Id</param>
  980. /// <param name="callback">Callback to invoke when completed.</param>
  981. public void LoadScores(string leaderboardId, Action<IScore[]> callback)
  982. {
  983. LoadScores(
  984. leaderboardId,
  985. LeaderboardStart.PlayerCentered,
  986. mClient.LeaderboardMaxResults(),
  987. LeaderboardCollection.Public,
  988. LeaderboardTimeSpan.AllTime,
  989. (scoreData) => callback(scoreData.Scores));
  990. }
  991. /// <summary>
  992. /// Loads the scores using the provided parameters.
  993. /// </summary>
  994. /// <param name="leaderboardId">Leaderboard identifier.</param>
  995. /// <param name="start">Start either top scores, or player centered.</param>
  996. /// <param name="rowCount">Row count. the number of rows to return.</param>
  997. /// <param name="collection">Collection. social or public</param>
  998. /// <param name="timeSpan">Time span. daily, weekly, all-time</param>
  999. /// <param name="callback">Callback to invoke when completed.</param>
  1000. public void LoadScores(
  1001. string leaderboardId,
  1002. LeaderboardStart start,
  1003. int rowCount,
  1004. LeaderboardCollection collection,
  1005. LeaderboardTimeSpan timeSpan,
  1006. Action<LeaderboardScoreData> callback)
  1007. {
  1008. if (!IsAuthenticated())
  1009. {
  1010. GooglePlayGames.OurUtils.Logger.e("LoadScores can only be called after authentication.");
  1011. callback(new LeaderboardScoreData(
  1012. leaderboardId,
  1013. ResponseStatus.NotAuthorized));
  1014. return;
  1015. }
  1016. mClient.LoadScores(
  1017. leaderboardId,
  1018. start,
  1019. rowCount,
  1020. collection,
  1021. timeSpan,
  1022. callback);
  1023. }
  1024. /// <summary>
  1025. /// Loads more scores.
  1026. /// </summary>
  1027. /// <remarks>This is used to load the next "page" of scores. </remarks>
  1028. /// <param name="token">Token used to recording the loading.</param>
  1029. /// <param name="rowCount">Row count.</param>
  1030. /// <param name="callback">Callback invoked when complete.</param>
  1031. public void LoadMoreScores(
  1032. ScorePageToken token,
  1033. int rowCount,
  1034. Action<LeaderboardScoreData> callback)
  1035. {
  1036. if (!IsAuthenticated())
  1037. {
  1038. GooglePlayGames.OurUtils.Logger.e("LoadMoreScores can only be called after authentication.");
  1039. callback(
  1040. new LeaderboardScoreData(
  1041. token.LeaderboardId,
  1042. ResponseStatus.NotAuthorized));
  1043. return;
  1044. }
  1045. mClient.LoadMoreScores(token, rowCount, callback);
  1046. }
  1047. /// <summary>
  1048. /// Returns a leaderboard object that can be configured to
  1049. /// load scores.
  1050. /// </summary>
  1051. /// <returns>The leaderboard object.</returns>
  1052. public ILeaderboard CreateLeaderboard()
  1053. {
  1054. return new PlayGamesLeaderboard(mDefaultLbUi);
  1055. }
  1056. /// <summary>
  1057. /// Shows the standard Google Play Games achievements user interface,
  1058. /// which allows the player to browse their achievements.
  1059. /// </summary>
  1060. public void ShowAchievementsUI()
  1061. {
  1062. ShowAchievementsUI(null);
  1063. }
  1064. /// <summary>
  1065. /// Shows the standard Google Play Games achievements user interface,
  1066. /// which allows the player to browse their achievements.
  1067. /// </summary>
  1068. /// <param name="callback">If non-null, the callback is invoked when
  1069. /// the achievement UI is dismissed</param>
  1070. public void ShowAchievementsUI(Action<UIStatus> callback)
  1071. {
  1072. if (!IsAuthenticated())
  1073. {
  1074. GooglePlayGames.OurUtils.Logger.e("ShowAchievementsUI can only be called after authentication.");
  1075. return;
  1076. }
  1077. GooglePlayGames.OurUtils.Logger.d("ShowAchievementsUI callback is " + callback);
  1078. mClient.ShowAchievementsUI(callback);
  1079. }
  1080. /// <summary>
  1081. /// Shows the standard Google Play Games leaderboards user interface,
  1082. /// which allows the player to browse their leaderboards. If you have
  1083. /// configured a specific leaderboard as the default through a call to
  1084. /// <see cref="SetDefaultLeaderboardForUi" />, the UI will show that
  1085. /// specific leaderboard only. Otherwise, a list of all the leaderboards
  1086. /// will be shown.
  1087. /// </summary>
  1088. public void ShowLeaderboardUI()
  1089. {
  1090. GooglePlayGames.OurUtils.Logger.d("ShowLeaderboardUI with default ID");
  1091. ShowLeaderboardUI(MapId(mDefaultLbUi), null);
  1092. }
  1093. /// <summary>
  1094. /// Shows the standard Google Play Games leaderboard UI for the given
  1095. /// leaderboard.
  1096. /// </summary>
  1097. /// <param name='leaderboardId'>
  1098. /// The ID of the leaderboard to display. This may be a raw
  1099. /// Google Play Games leaderboard ID or an alias configured through a call to
  1100. /// <see cref="AddIdMapping" />.
  1101. /// </param>
  1102. public void ShowLeaderboardUI(string leaderboardId)
  1103. {
  1104. if (leaderboardId != null)
  1105. {
  1106. leaderboardId = MapId(leaderboardId);
  1107. }
  1108. mClient.ShowLeaderboardUI(leaderboardId, LeaderboardTimeSpan.AllTime, null);
  1109. }
  1110. /// <summary>
  1111. /// Shows the leaderboard UI and calls the specified callback upon
  1112. /// completion.
  1113. /// </summary>
  1114. /// <param name="leaderboardId">leaderboard ID, can be null meaning all leaderboards.</param>
  1115. /// <param name="callback">Callback to call. If null, nothing is called.</param>
  1116. public void ShowLeaderboardUI(string leaderboardId, Action<UIStatus> callback)
  1117. {
  1118. ShowLeaderboardUI(leaderboardId, LeaderboardTimeSpan.AllTime, callback);
  1119. }
  1120. /// <summary>
  1121. /// Shows the leaderboard UI and calls the specified callback upon
  1122. /// completion.
  1123. /// </summary>
  1124. /// <param name="leaderboardId">leaderboard ID, can be null meaning all leaderboards.</param>
  1125. /// <param name="span">Timespan to display scores in the leaderboard.</param>
  1126. /// <param name="callback">Callback to call. If null, nothing is called.</param>
  1127. public void ShowLeaderboardUI(
  1128. string leaderboardId,
  1129. LeaderboardTimeSpan span,
  1130. Action<UIStatus> callback)
  1131. {
  1132. if (!IsAuthenticated())
  1133. {
  1134. GooglePlayGames.OurUtils.Logger.e("ShowLeaderboardUI can only be called after authentication.");
  1135. if (callback != null)
  1136. {
  1137. callback(UIStatus.NotAuthorized);
  1138. }
  1139. return;
  1140. }
  1141. GooglePlayGames.OurUtils.Logger.d("ShowLeaderboardUI, lbId=" +
  1142. leaderboardId + " callback is " + callback);
  1143. mClient.ShowLeaderboardUI(leaderboardId, span, callback);
  1144. }
  1145. /// <summary>
  1146. /// Sets the default leaderboard for the leaderboard UI. After calling this
  1147. /// method, a call to <see cref="ShowLeaderboardUI" /> will show only the specified
  1148. /// leaderboard instead of showing the list of all leaderboards.
  1149. /// </summary>
  1150. /// <param name='lbid'>
  1151. /// The ID of the leaderboard to display on the default UI. This may be a raw
  1152. /// Google Play Games leaderboard ID or an alias configured through a call to
  1153. /// <see cref="AddIdMapping" />.
  1154. /// </param>
  1155. public void SetDefaultLeaderboardForUI(string lbid)
  1156. {
  1157. GooglePlayGames.OurUtils.Logger.d("SetDefaultLeaderboardForUI: " + lbid);
  1158. if (lbid != null)
  1159. {
  1160. lbid = MapId(lbid);
  1161. }
  1162. mDefaultLbUi = lbid;
  1163. }
  1164. /// <summary>
  1165. /// Loads the friends that also play this game. See loadConnectedPlayers.
  1166. /// </summary>
  1167. /// <remarks>This is a callback variant of LoadFriends. When completed,
  1168. /// the friends list set in the user object, so they can accessed via the
  1169. /// friends property as needed.
  1170. /// </remarks>
  1171. /// <param name="user">The current local user</param>
  1172. /// <param name="callback">Callback invoked when complete.</param>
  1173. public void LoadFriends(ILocalUser user, Action<bool> callback)
  1174. {
  1175. if (!IsAuthenticated())
  1176. {
  1177. GooglePlayGames.OurUtils.Logger.e(
  1178. "LoadScores can only be called after authentication.");
  1179. if (callback != null)
  1180. {
  1181. callback(false);
  1182. }
  1183. return;
  1184. }
  1185. mClient.LoadFriends(callback);
  1186. }
  1187. /// <summary>
  1188. /// Loads the leaderboard based on the constraints in the leaderboard
  1189. /// object.
  1190. /// </summary>
  1191. /// <param name="board">The leaderboard object. This is created by
  1192. /// calling CreateLeaderboard(), and then initialized appropriately.</param>
  1193. /// <param name="callback">Callback invoked when complete.</param>
  1194. public void LoadScores(ILeaderboard board, Action<bool> callback)
  1195. {
  1196. if (!IsAuthenticated())
  1197. {
  1198. GooglePlayGames.OurUtils.Logger.e("LoadScores can only be called after authentication.");
  1199. if (callback != null)
  1200. {
  1201. callback(false);
  1202. }
  1203. return;
  1204. }
  1205. LeaderboardTimeSpan timeSpan;
  1206. switch (board.timeScope)
  1207. {
  1208. case TimeScope.AllTime:
  1209. timeSpan = LeaderboardTimeSpan.AllTime;
  1210. break;
  1211. case TimeScope.Week:
  1212. timeSpan = LeaderboardTimeSpan.Weekly;
  1213. break;
  1214. case TimeScope.Today:
  1215. timeSpan = LeaderboardTimeSpan.Daily;
  1216. break;
  1217. default:
  1218. timeSpan = LeaderboardTimeSpan.AllTime;
  1219. break;
  1220. }
  1221. ((PlayGamesLeaderboard)board).loading = true;
  1222. GooglePlayGames.OurUtils.Logger.d("LoadScores, board=" + board +
  1223. " callback is " + callback);
  1224. mClient.LoadScores(
  1225. board.id,
  1226. LeaderboardStart.PlayerCentered,
  1227. board.range.count > 0 ? board.range.count : mClient.LeaderboardMaxResults(),
  1228. board.userScope == UserScope.FriendsOnly ? LeaderboardCollection.Social : LeaderboardCollection.Public,
  1229. timeSpan,
  1230. (scoreData) => HandleLoadingScores(
  1231. (PlayGamesLeaderboard)board, scoreData, callback));
  1232. }
  1233. /// <summary>
  1234. /// Check if the leaderboard is currently loading.
  1235. /// </summary>
  1236. /// <returns><c>true</c>, if loading was gotten, <c>false</c> otherwise.</returns>
  1237. /// <param name="board">The leaderboard to check for loading in progress</param>
  1238. public bool GetLoading(ILeaderboard board)
  1239. {
  1240. return board != null && board.loading;
  1241. }
  1242. /// <summary>
  1243. /// Register an invitation delegate to be
  1244. /// notified when a multiplayer invitation arrives
  1245. /// </summary>
  1246. /// <param name="deleg">The delegate to register</param>
  1247. public void RegisterInvitationDelegate(InvitationReceivedDelegate deleg)
  1248. {
  1249. mClient.RegisterInvitationDelegate(deleg);
  1250. }
  1251. /// <summary>
  1252. /// Handles the processing of scores during loading.
  1253. /// </summary>
  1254. /// <param name="board">leaderboard being loaded</param>
  1255. /// <param name="scoreData">Score data.</param>
  1256. /// <param name="callback">Callback invoked when complete.</param>
  1257. internal void HandleLoadingScores(
  1258. PlayGamesLeaderboard board,
  1259. LeaderboardScoreData scoreData,
  1260. Action<bool> callback)
  1261. {
  1262. bool ok = board.SetFromData(scoreData);
  1263. if (ok && !board.HasAllScores() && scoreData.NextPageToken != null)
  1264. {
  1265. int rowCount = board.range.count - board.ScoreCount;
  1266. // need to load more scores
  1267. mClient.LoadMoreScores(
  1268. scoreData.NextPageToken,
  1269. rowCount,
  1270. (nextScoreData) =>
  1271. HandleLoadingScores(board, nextScoreData, callback));
  1272. }
  1273. else
  1274. {
  1275. callback(ok);
  1276. }
  1277. }
  1278. /// <summary>
  1279. /// Internal implmentation of getFriends.Gets the friends.
  1280. /// </summary>
  1281. /// <returns>The friends.</returns>
  1282. internal IUserProfile[] GetFriends()
  1283. {
  1284. if (!IsAuthenticated())
  1285. {
  1286. GooglePlayGames.OurUtils.Logger.d("Cannot get friends when not authenticated!");
  1287. return new IUserProfile[0];
  1288. }
  1289. return mClient.GetFriends();
  1290. }
  1291. /// <summary>
  1292. /// Maps the alias to the identifier.
  1293. /// </summary>
  1294. /// <remarks>This maps an aliased ID to the actual id. The intent of
  1295. /// this method is to allow easy to read constants to be used instead of
  1296. /// the generated ids.
  1297. /// </remarks>
  1298. /// <returns>The identifier, or null if not found.</returns>
  1299. /// <param name="id">Alias to map</param>
  1300. private string MapId(string id)
  1301. {
  1302. if (id == null)
  1303. {
  1304. return null;
  1305. }
  1306. if (mIdMap.ContainsKey(id))
  1307. {
  1308. string result = mIdMap[id];
  1309. GooglePlayGames.OurUtils.Logger.d("Mapping alias " + id + " to ID " + result);
  1310. return result;
  1311. }
  1312. return id;
  1313. }
  1314. }
  1315. }
  1316. #endif