services_for_ios.rst 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  1. .. _doc_services_for_ios:
  2. Services for iOS
  3. ================
  4. At the moment, there are two iOS APIs partially implemented, GameCenter
  5. and Storekit. Both use the same model of asynchronous calls explained
  6. below.
  7. Asynchronous methods
  8. --------------------
  9. When requesting an asynchronous operation, the method will look like
  10. this:
  11. ::
  12. Error purchase(Variant p_params);
  13. The parameter will usually be a Dictionary, with the information
  14. necessary to make the request, and the call will have two phases. First,
  15. the method will immediately return an Error value. If the Error is not
  16. 'OK', the call operation is completed, with an error probably caused
  17. locally (no internet connection, API incorrectly configured, etc). If
  18. the error value is 'OK', a response event will be produced and added to
  19. the 'pending events' queue. Example:
  20. .. code:: python
  21. func on_purchase_pressed():
  22. var result = InAppStore.purchase( { "product_id": "my_product" } )
  23. if result == OK:
  24. animation.play("busy") # show the "waiting for response" animation
  25. else:
  26. show_error()
  27. # put this on a 1 second timer or something
  28. func check_events():
  29. while InAppStore.get_pending_event_count() > 0:
  30. var event = InAppStore.pop_pending_event()
  31. if event.type == "purchase":
  32. if event.result == "ok":
  33. show_success(event.product_id)
  34. else:
  35. show_error()
  36. Remember that when a call returns OK, the API will *always* produce an
  37. event through the pending_event interface, even if it's an error, or a
  38. network timeout, etc. You should be able to, for example, safely block
  39. the interface waiting for a reply from the server. If any of the APIs
  40. don't behave this way it should be treated as a bug.
  41. The pending event interface consists of two methods:
  42. - ``get_pending_event_count()``
  43. Returns the number of pending events on the queue.
  44. - ``Variant pop_pending_event()``
  45. Pops the first event from the queue and returns it.
  46. Store Kit
  47. ---------
  48. Implemented in platform/iphone/in_app_store.mm
  49. The Store Kit API is accessible through the "InAppStore" singleton (will
  50. always be available from gdscript). It is initialized automatically. It
  51. has two methods for purchasing:
  52. - ``Error purchase(Variant p_params);``
  53. - ``Error request_product_info(Variant p_params);``
  54. and the pending_event interface
  55. ::
  56. int get_pending_event_count();
  57. Variant pop_pending_event();
  58. purchase
  59. ~~~~~~~~
  60. Purchases a product id through the Store Kit API.
  61. Parameters
  62. ^^^^^^^^^^
  63. Takes a Dictionary as a parameter, with one field, ``product_id``, a
  64. string with your product id. Example:
  65. ::
  66. var result = InAppStore.purchase( { "product_id": "my_product" } )
  67. Response event
  68. ^^^^^^^^^^^^^^
  69. The response event will be a dictionary with the following fields:
  70. On error:
  71. ::
  72. {
  73. "type": "purchase",
  74. "result": "error",
  75. "product_id": "the product id requested"
  76. }
  77. On success:
  78. ::
  79. {
  80. "type": "purchase",
  81. "result": "ok",
  82. "product_id": "the product id requested"
  83. }
  84. request_product_info
  85. ~~~~~~~~~~~~~~~~~~~~
  86. Requests the product info on a list of product IDs.
  87. Parameters
  88. ^^^^^^^^^^
  89. Takes a Dictionary as a parameter, with one field, ``product_ids``, a
  90. string array with a list of product ids. Example:
  91. ::
  92. var result = InAppStore.request_product_info( { "product_ids": ["my_product1", "my_product2"] } )
  93. Response event
  94. ^^^^^^^^^^^^^^
  95. The response event will be a dictionary with the following fields:
  96. ::
  97. {
  98. "type": "product_info",
  99. "result": "ok",
  100. "invalid_ids": [ list of requested ids that were invalid ],
  101. "ids": [ list of ids that were valid ],
  102. "titles": [ list of valid product titles (corresponds with list of valid ids) ],
  103. "descriptions": [ list of valid product descriptions ] ,
  104. "prices": [ list of valid product prices ],
  105. "localized_prices": [ list of valid product localized prices ],
  106. }
  107. Game Center
  108. -----------
  109. Implemented in platform/iphone/game_center.mm
  110. The Game Center API is available through the "GameCenter" singleton. It
  111. has 6 methods:
  112. - ``Error post_score(Variant p_score);``
  113. - ``Erroraward_achievement(Variant p_params);``
  114. - ``Error reset_achievements();``
  115. - ``Error request_achievements();``
  116. - ``Error request_achievement_descriptions();``
  117. - ``Error show_game_center(Variant p_params);``
  118. plus the standard pending event interface.
  119. post_score
  120. ~~~~~~~~~~
  121. Posts a score to a Game Center leaderboard.
  122. Parameters
  123. ^^^^^^^^^^
  124. Takes a Dictionary as a parameter, with two fields:
  125. - ``score`` a float number
  126. - ``category`` a string with the category name
  127. Example:
  128. ::
  129. var result = GameCenter.post_score( { "score": 100, "category": "my_leaderboard", } )
  130. Response event
  131. ^^^^^^^^^^^^^^
  132. The response event will be a dictionary with the following fields:
  133. On error:
  134. ::
  135. {
  136. "type": "post_score",
  137. "result": "error",
  138. "error_code": the value from NSError::code,
  139. "error_description": the value from NSError::localizedDescription,
  140. }
  141. On success:
  142. ::
  143. {
  144. "type": "post_score",
  145. "result": "ok",
  146. }
  147. award_achievement
  148. ~~~~~~~~~~~~~~~~~
  149. Modifies the progress of a Game Center achievement.
  150. Parameters
  151. ^^^^^^^^^^
  152. Takes a Dictionary as a parameter, with 3 fields:
  153. - ``name`` (string) the achievement name
  154. - ``progress`` (float) the achievement progress from 0.0 to 100.0
  155. (passed to ``GKAchievement::percentComplete``)
  156. - ``show_completion_banner`` (bool) whether Game Center should display
  157. an achievement banner at the top of the screen
  158. Example:
  159. ::
  160. var result = award_achievement( { "name": "hard_mode_completed", "progress": 6.1 } )
  161. Response event
  162. ^^^^^^^^^^^^^^
  163. The response event will be a dictionary with the following fields:
  164. On error:
  165. ::
  166. {
  167. "type": "award_achievement",
  168. "result": "error",
  169. "error_code": the error code taken from NSError::code,
  170. }
  171. On success:
  172. ::
  173. {
  174. "type": "award_achievement",
  175. "result": "ok",
  176. }
  177. reset_achievements
  178. ~~~~~~~~~~~~~~~~~~
  179. Clears all Game Center achievements. The function takes no parameters.
  180. Response event
  181. ^^^^^^^^^^^^^^
  182. The response event will be a dictionary with the following fields:
  183. On error:
  184. ::
  185. {
  186. "type": "reset_achievements",
  187. "result": "error",
  188. "error_code": the value from NSError::code
  189. }
  190. On success:
  191. ::
  192. {
  193. "type": "reset_achievements",
  194. "result": "ok",
  195. }
  196. request_achievements
  197. ~~~~~~~~~~~~~~~~~~~~
  198. Request all the Game Center achievements the player has made progress
  199. on. The function takes no parameters.
  200. Response event
  201. ^^^^^^^^^^^^^^
  202. The response event will be a dictionary with the following fields:
  203. On error:
  204. ::
  205. {
  206. "type": "achievements",
  207. "result": "error",
  208. "error_code": the value from NSError::code
  209. }
  210. On success:
  211. ::
  212. {
  213. "type": "achievements",
  214. "result": "ok",
  215. "names": [ list of the name of each achievement ],
  216. "progress": [ list of the progress made on each achievement ]
  217. }
  218. request_achievement_descriptions
  219. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  220. Request the descriptions of all existing Game Center achievements
  221. regardless of progress. The function takes no parameters.
  222. Response event
  223. ^^^^^^^^^^^^^^
  224. The response event will be a dictionary with the following fields:
  225. On error:
  226. ::
  227. {
  228. "type": "achievement_descriptions",
  229. "result": "error",
  230. "error_code": the value from NSError::code
  231. }
  232. On success:
  233. ::
  234. {
  235. "type": "achievement_descriptions",
  236. "result": "ok",
  237. "names": [ list of the name of each achievement ],
  238. "titles": [ list of the title of each achievement ]
  239. "unachieved_descriptions": [ list of the description of each achievement when it is unachieved ]
  240. "achieved_descriptions": [ list of the description of each achievement when it is achieved ]
  241. "maximum_points": [ list of the points earned by completing each achievement ]
  242. "hidden": [ list of booleans indicating whether each achievement is initially visible ]
  243. "replayable": [ list of booleans indicating whether each achievement can be earned more than once ]
  244. }
  245. show_game_center
  246. ~~~~~~~~~~~~~~~~
  247. Displays the built in Game Center overlay showing leaderboards,
  248. achievements, and challenges.
  249. Parameters
  250. ^^^^^^^^^^
  251. Takes a Dictionary as a parameter, with two fields:
  252. - ``view`` (string) (optional) the name of the view to present. Accepts
  253. "default", "leaderboards", "achievements", or "challenges". Defaults
  254. to "default".
  255. - ``leaderboard_name`` (string) (optional) the name of the leaderboard
  256. to present. Only used when "view" is "leaderboards" (or "default" is
  257. configured to show leaderboards). If not specified, Game Center will
  258. display the aggregate leaderboard.
  259. Examples:
  260. ::
  261. var result = show_game_center( { "view": "leaderboards", "leaderboard_name": "best_time_leaderboard" } )
  262. var result = show_game_center( { "view": "achievements" } )
  263. Response event
  264. ^^^^^^^^^^^^^^
  265. The response event will be a dictionary with the following fields:
  266. On close:
  267. ::
  268. {
  269. "type": "show_game_center",
  270. "result": "ok",
  271. }
  272. Multi-platform games
  273. --------------------
  274. When working on a multi-platform game, you won't always have the
  275. "GameCenter" singleton available (for example when running on PC or
  276. Android). Because the gdscript compiler looks up the singletons at
  277. compile time, you can't just query the singletons to see and use what
  278. you need inside a conditional block, you need to also define them as
  279. valid identifiers (local variable or class member). This is an example
  280. of how to work around this in a class:
  281. .. code:: python
  282. var GameCenter = null # define it as a class member
  283. func post_score(p_score):
  284. if GameCenter == null:
  285. return
  286. GameCenter.post_score( { "value": p_score, "category": "my_leaderboard" } )
  287. func check_events():
  288. while GameCenter.get_pending_event_count() > 0:
  289. # do something with events here
  290. pass
  291. func _ready():
  292. # check if the singleton exists
  293. if Globals.has_singleton("GameCenter"):
  294. GameCenter = Globals.get_singleton("GameCenter")
  295. # connect your timer here to the "check_events" function