UNPKG

phaser

Version:

A fast, free and fun HTML5 Game Framework for Desktop and Mobile web browsers from the team at Phaser Studio Inc.

1,418 lines (1,251 loc) 79.3 kB
/* eslint no-console: 0 */ /** * @author Richard Davey <rich@photonstorm.com> * @copyright 2018 Photon Storm Ltd. * @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License} */ var AdInstance = require('./AdInstance'); var Class = require('../../../src/utils/Class'); var DataManager = require('../../../src/data/DataManager'); var EventEmitter = require('eventemitter3'); var Leaderboard = require('./Leaderboard'); var Product = require('./Product'); var Purchase = require('./Purchase'); /** * @classdesc * The Facebook Instant Games Plugin for Phaser 3 provides a seamless bridge between Phaser * and the Facebook Instant Games API version 6.2. * * You can access this plugin via the `facebook` property in a Scene, i.e: * * ```javascript * this.facebook.getPlatform(); * ``` * * If this is unavailable please check to make sure you're using a build of Phaser that has * this plugin within it. You can quickly check this by looking at the dev tools console * header - the Phaser version number will have `-FB` after it if this plugin is loaded. * * If you are building your own version of Phaser then use this Webpack DefinePlugin flag: * * `"typeof PLUGIN_FBINSTANT": JSON.stringify(true)` * * You will find that every Instant Games API method has a mapping in this plugin. * For a full list please consult either the plugin documentation, or the 6.2 SDK documentation * at https://developers.facebook.com/docs/games/instant-games/sdk/fbinstant6.2 * * Internally this plugin uses its own Data Manager to handle seamless user data updates and provides * handy functions for advertisement displaying, opening share dialogs, logging, leaderboards, purchase API requests, * loader integration and more. * * To get started with Facebook Instant Games you will need to register on Facebook and create a new Instant * Game app that has its own unique app ID. Facebook have also provided a dashboard interface for setting up * various features for your game, including leaderboards, ad requests and the payments API. There are lots * of guides on the Facebook Developers portal to assist with setting these * various systems up: https://developers.facebook.com/docs/games/instant-games/guides * * For more details follow the Quick Start guide here: https://developers.facebook.com/docs/games/instant-games * * @class FacebookInstantGamesPlugin * @memberOf Phaser * @constructor * @extends Phaser.Events.EventEmitter * @since 3.13.0 * * @param {Phaser.Game} game - A reference to the Phaser.Game instance. */ var FacebookInstantGamesPlugin = new Class({ Extends: EventEmitter, initialize: function FacebookInstantGamesPlugin (game) { EventEmitter.call(this); /** * A reference to the Phaser.Game instance. * * @name Phaser.FacebookInstantGamesPlugin#game * @type {Phaser.Game} * @readOnly * @since 3.13.0 */ this.game = game; /** * A Data Manager instance. * It allows you to store, query and retrieve any key/value data you may need to store. * It's also used internally by the plugin to store FBIG API data. * * @name Phaser.FacebookInstantGamesPlugin#data * @type {Phaser.Data.DataManager} * @since 3.13.0 */ this.data = new DataManager(this); this.on('setdata', this.setDataHandler, this); this.on('changedata', this.changeDataHandler, this); /** * Has the Facebook Instant Games API loaded yet? * This is set automatically during the boot process. * * @name Phaser.FacebookInstantGamesPlugin#hasLoaded * @type {boolean} * @since 3.13.0 */ this.hasLoaded = false; /** * Is the Data Manager currently locked? * * @name Phaser.FacebookInstantGamesPlugin#dataLocked * @type {boolean} * @since 3.13.0 */ this.dataLocked = false; /** * A list of the Facebook Instant Games APIs that are available, * based on the given platform, context and user privacy settings. * This value is populated automatically during boot. * * @name Phaser.FacebookInstantGamesPlugin#supportedAPIs * @type {string[]} * @since 3.13.0 */ this.supportedAPIs = []; /** * Holds the entry point that the game was launched from. * This value is populated automatically during boot. * * @name Phaser.FacebookInstantGamesPlugin#entryPoint * @type {string} * @since 3.13.0 */ this.entryPoint = ''; /** * An object that contains any data associated with the entry point that the game was launched from. * The contents of the object are developer-defined, and can occur from entry points on different platforms. * This will return null for older mobile clients, as well as when there is no data associated with the particular entry point. * This value is populated automatically during boot. * * @name Phaser.FacebookInstantGamesPlugin#entryPointData * @type {any} * @since 3.13.0 */ this.entryPointData = null; /** * A unique identifier for the current game context. This represents a specific context * that the game is being played in (for example, a particular messenger conversation or facebook post). * The identifier will be null if game is being played in a solo context. * This value is populated automatically during boot. * * @name Phaser.FacebookInstantGamesPlugin#contextID * @type {string} * @since 3.13.0 */ this.contextID = null; /** * The current context in which your game is running. This can be either `null` or * one of: * * `POST` - The game is running inside of a Facebook post. * `THREAD` - The game is running inside a Facebook Messenger thread. * `GROUP` - The game is running inside a Facebook Group. * `SOLO` - This is the default context, the player is the only participant. * * This value is populated automatically during boot. * * @name Phaser.FacebookInstantGamesPlugin#contextType * @type {?string} * @since 3.13.0 */ this.contextType = null; /** * The current locale. * See https://origincache.facebook.com/developers/resources/?id=FacebookLocales.xml for a complete list of supported locale values. * Use this to determine what languages the current game should be localized with. * This value is populated automatically during boot. * * @name Phaser.FacebookInstantGamesPlugin#locale * @type {?string} * @since 3.13.0 */ this.locale = null; /** * The platform on which the game is currently running, i.e. `IOS`. * This value is populated automatically during boot. * * @name Phaser.FacebookInstantGamesPlugin#platform * @type {?string} * @since 3.13.0 */ this.platform = null; /** * The string representation of the Facebook Instant Games SDK version being used. * This value is populated automatically during boot. * * @name Phaser.FacebookInstantGamesPlugin#version * @type {?string} * @since 3.13.0 */ this.version = null; /** * Holds the id of the player. This is a string based ID, the same as `FBInstant.player.getID()`. * This value is populated automatically during boot if the API is supported. * * @name Phaser.FacebookInstantGamesPlugin#playerID * @type {?string} * @since 3.13.0 */ this.playerID = null; /** * The player's localized display name. * This value is populated automatically during boot if the API is supported. * * @name Phaser.FacebookInstantGamesPlugin#playerName * @type {?string} * @since 3.13.0 */ this.playerName = null; /** * A url to the player's public profile photo. The photo will always be a square, and with dimensions * of at least 200x200. When rendering it in the game, the exact dimensions should never be assumed to be constant. * It's recommended to always scale the image to a desired size before rendering. * This value is populated automatically during boot if the API is supported. * * @name Phaser.FacebookInstantGamesPlugin#playerPhotoURL * @type {?string} * @since 3.13.0 */ this.playerPhotoURL = null; /** * Whether a player can subscribe to the game bot or not. * * @name Phaser.FacebookInstantGamesPlugin#playerCanSubscribeBot * @type {boolean} * @since 3.13.0 */ this.playerCanSubscribeBot = false; /** * Does the current platform and context allow for use of the payments API? * Currently this is only available on Facebook.com and Android 6+. * * @name Phaser.FacebookInstantGamesPlugin#paymentsReady * @type {boolean} * @since 3.13.0 */ this.paymentsReady = false; /** * The set of products that are registered to the game. * * @name Phaser.FacebookInstantGamesPlugin#catalog * @type {Product[]} * @since 3.13.0 */ this.catalog = []; /** * Contains all of the player's unconsumed purchases. * The game must fetch the current player's purchases as soon as the client indicates that it is ready to perform payments-related operations, * i.e. at game start. The game can then process and consume any purchases that are waiting to be consumed. * * @name Phaser.FacebookInstantGamesPlugin#purchases * @type {Purchase[]} * @since 3.13.0 */ this.purchases = []; /** * Contains all of the leaderboard data, as populated by the `getLeaderboard()` method. * * @name Phaser.FacebookInstantGamesPlugin#leaderboards * @type {Phaser.FacebookInstantGamesLeaderboard[]} * @since 3.13.0 */ this.leaderboards = {}; /** * Contains AdInstance objects, as created by the `preloadAds()` method. * * @name Phaser.FacebookInstantGamesPlugin#ads * @type {AdInstance[]} * @since 3.13.0 */ this.ads = []; }, /** * Internal set data handler. * * @method Phaser.FacebookInstantGamesPlugin#setDataHandler * @private * @since 3.13.0 * * @param {Phaser.Data.DataManager} parent - The parent Data Manager instance. * @param {string} key - The key of the data. * @param {any} value - The value of the data. */ setDataHandler: function (parent, key, value) { if (this.dataLocked) { return; } var data = {}; data[key] = value; var _this = this; FBInstant.player.setDataAsync(data).then(function () { _this.emit('savedata', data); }); }, /** * Internal change data handler. * * @method Phaser.FacebookInstantGamesPlugin#changeDataHandler * @private * @since 3.13.0 * * @param {Phaser.Data.DataManager} parent - The parent Data Manager instance. * @param {string} key - The key of the data. * @param {any} value - The value of the data. */ changeDataHandler: function (parent, key, value) { if (this.dataLocked) { return; } var data = {}; data[key] = value; var _this = this; FBInstant.player.setDataAsync(data).then(function () { _this.emit('savedata', data); }); }, /** * Call this method from your `Scene.preload` in order to sync the load progress * of the Phaser Loader with the Facebook Instant Games loader display, i.e.: * * ```javascript * this.facebook.showLoadProgress(this); * this.facebook.once('startgame', this.startGame, this); * ``` * * @method Phaser.FacebookInstantGamesPlugin#showLoadProgress * @since 3.13.0 * * @param {Phaser.Scene} scene - The Scene for which you want to show loader progress for. * * @return {this} This Facebook Instant Games Plugin instance. */ showLoadProgress: function (scene) { scene.load.on('progress', function (value) { if (!this.hasLoaded) { FBInstant.setLoadingProgress(value * 100); } }, this); scene.load.on('complete', function () { if (!this.hasLoaded) { this.hasLoaded = true; FBInstant.startGameAsync().then(this.gameStartedHandler.bind(this)); } }, this); return this; }, /** * This method is called automatically when the game has finished loading, * if you used the `showLoadProgress` method. If your game doesn't need to * load any assets, or you're managing the load yourself, then call this * method directly to start the API running. * * When the API has finished starting this plugin will emit a `startgame` event * which you should listen for. * * @method Phaser.FacebookInstantGamesPlugin#gameStarted * @since 3.13.0 */ gameStarted: function () { if (!this.hasLoaded) { this.hasLoaded = true; FBInstant.startGameAsync().then(this.gameStartedHandler.bind(this)); } else { this.gameStartedHandler(); } }, /** * The internal gameStarted handler. * * @method Phaser.FacebookInstantGamesPlugin#gameStartedHandler * @private * @since 3.20.0 */ gameStartedHandler: function () { var APIs = FBInstant.getSupportedAPIs(); var supported = {}; var dotToUpper = function (match) { return match[1].toUpperCase(); }; APIs.forEach(function (api) { api = api.replace(/\../g, dotToUpper); supported[api] = true; }); this.supportedAPIs = supported; this.getID(); this.getType(); this.getLocale(); this.getPlatform(); this.getSDKVersion(); this.getPlayerID(); this.getPlayerName(); this.getPlayerPhotoURL(); var _this = this; FBInstant.onPause(function () { _this.emit('pause'); }); FBInstant.getEntryPointAsync().then(function (entrypoint) { _this.entryPoint = entrypoint; _this.entryPointData = FBInstant.getEntryPointData(); _this.emit('startgame'); }).catch(function (e) { console.warn(e); }); // Facebook.com and Android 6 only if (this.supportedAPIs.paymentsPurchaseAsync) { FBInstant.payments.onReady(function () { _this.paymentsReady = true; }).catch(function (e) { console.warn(e); }); } }, /** * Checks to see if a given Facebook Instant Games API is available or not. * * @method Phaser.FacebookInstantGamesPlugin#checkAPI * @since 3.13.0 * * @param {string} api - The API to check for, i.e. `player.getID`. * * @return {boolean} `true` if the API is supported, otherwise `false`. */ checkAPI: function (api) { if (!this.supportedAPIs[api]) { return false; } else { return true; } }, /** * Returns the unique identifier for the current game context. This represents a specific context * that the game is being played in (for example, a particular messenger conversation or facebook post). * The identifier will be null if game is being played in a solo context. * * It is only populated if `contextGetID` is in the list of supported APIs. * * @method Phaser.FacebookInstantGamesPlugin#getID * @since 3.13.0 * * @return {string} The context ID. */ getID: function () { if (!this.contextID && this.supportedAPIs.contextGetID) { this.contextID = FBInstant.context.getID(); } return this.contextID; }, /** * Returns the current context in which your game is running. This can be either `null` or one of: * * `POST` - The game is running inside of a Facebook post. * `THREAD` - The game is running inside a Facebook Messenger thread. * `GROUP` - The game is running inside a Facebook Group. * `SOLO` - This is the default context, the player is the only participant. * * It is only populated if `contextGetType` is in the list of supported APIs. * * @method Phaser.FacebookInstantGamesPlugin#getType * @since 3.13.0 * * @return {?string} The context type. */ getType: function () { if (!this.contextType && this.supportedAPIs.contextGetType) { this.contextType = FBInstant.context.getType(); } return this.contextType; }, /** * Returns the current locale. * See https://origincache.facebook.com/developers/resources/?id=FacebookLocales.xml for a complete list of supported locale values. * Use this to determine what languages the current game should be localized with. * It is only populated if `getLocale` is in the list of supported APIs. * * @method Phaser.FacebookInstantGamesPlugin#getLocale * @since 3.13.0 * * @return {?string} The current locale. */ getLocale: function () { if (!this.locale && this.supportedAPIs.getLocale) { this.locale = FBInstant.getLocale(); } return this.locale; }, /** * Returns the platform on which the game is currently running, i.e. `IOS`. * It is only populated if `getPlatform` is in the list of supported APIs. * * @method Phaser.FacebookInstantGamesPlugin#getPlatform * @since 3.13.0 * * @return {?string} The current platform. */ getPlatform: function () { if (!this.platform && this.supportedAPIs.getPlatform) { this.platform = FBInstant.getPlatform(); } return this.platform; }, /** * Returns the string representation of the Facebook Instant Games SDK version being used. * It is only populated if `getSDKVersion` is in the list of supported APIs. * * @method Phaser.FacebookInstantGamesPlugin#getSDKVersion * @since 3.13.0 * * @return {?string} The sdk version. */ getSDKVersion: function () { if (!this.version && this.supportedAPIs.getSDKVersion) { this.version = FBInstant.getSDKVersion(); } return this.version; }, /** * Returns the id of the player. This is a string based ID, the same as `FBInstant.player.getID()`. * It is only populated if `playerGetID` is in the list of supported APIs. * * @method Phaser.FacebookInstantGamesPlugin#getPlayerID * @since 3.13.0 * * @return {?string} The player ID. */ getPlayerID: function () { if (!this.playerID && this.supportedAPIs.playerGetID) { this.playerID = FBInstant.player.getID(); } return this.playerID; }, /** * Returns the player's localized display name. * It is only populated if `playerGetName` is in the list of supported APIs. * * @method Phaser.FacebookInstantGamesPlugin#getPlayerName * @since 3.13.0 * * @return {?string} The player's localized display name. */ getPlayerName: function () { if (!this.playerName && this.supportedAPIs.playerGetName) { this.playerName = FBInstant.player.getName(); } return this.playerName; }, /** * Returns the url to the player's public profile photo. The photo will always be a square, and with dimensions * of at least 200x200. When rendering it in the game, the exact dimensions should never be assumed to be constant. * It's recommended to always scale the image to a desired size before rendering. * It is only populated if `playerGetPhoto` is in the list of supported APIs. * * @method Phaser.FacebookInstantGamesPlugin#getPlayerPhotoURL * @since 3.13.0 * * @return {?string} The player's photo url. */ getPlayerPhotoURL: function () { if (!this.playerPhotoURL && this.supportedAPIs.playerGetPhoto) { this.playerPhotoURL = FBInstant.player.getPhoto(); } return this.playerPhotoURL; }, /** * Load the player's photo and store it in the Texture Manager, ready for use in-game. * * This method works by using a Scene Loader instance and then asking the Loader to * retrieve the image. * * When complete the plugin will emit a `photocomplete` event, along with the key of the photo. * * ```javascript * this.facebook.loadPlayerPhoto(this, 'player').once('photocomplete', function (key) { * this.add.image(x, y, 'player'); * }, this); * ``` * * @method Phaser.FacebookInstantGamesPlugin#loadPlayerPhoto * @since 3.13.0 * * @param {Phaser.Scene} scene - The Scene that will be responsible for loading this photo. * @param {string} key - The key to use when storing the photo in the Texture Manager. * * @return {this} This Facebook Instant Games Plugin instance. */ loadPlayerPhoto: function (scene, key) { if (this.playerPhotoURL) { scene.load.setCORS('anonymous'); scene.load.image(key, this.playerPhotoURL); scene.load.once('filecomplete-image-' + key, function () { this.emit('photocomplete', key); }, this); scene.load.start(); } return this; }, /** * Checks if the current player can subscribe to the game bot. * * It makes an async call to the API, so the result isn't available immediately. * * If they can subscribe, the `playerCanSubscribeBot` property is set to `true` * and this plugin will emit the `cansubscribebot` event. * * If they cannot, i.e. it's not in the list of supported APIs, or the request * was rejected, it will emit a `cansubscribebotfail` event instead. * * @method Phaser.FacebookInstantGamesPlugin#canSubscribeBot * @since 3.13.0 * * @return {this} This Facebook Instant Games Plugin instance. */ canSubscribeBot: function () { if (this.supportedAPIs.playerCanSubscribeBotAsync) { var _this = this; FBInstant.player.canSubscribeBotAsync().then(function () { _this.playerCanSubscribeBot = true; _this.emit('cansubscribebot'); }).catch(function (e) { _this.emit('cansubscribebotfail', e); }); } else { this.emit('cansubscribebotfail'); } return this; }, /** * Subscribes the current player to the game bot. * * It makes an async call to the API, so the result isn't available immediately. * * If they are successfully subscribed this plugin will emit the `subscribebot` event. * * If they cannot, i.e. it's not in the list of supported APIs, or the request * was rejected, it will emit a `subscribebotfail` event instead. * * @method Phaser.FacebookInstantGamesPlugin#subscribeBot * @since 3.13.0 * * @return {this} This Facebook Instant Games Plugin instance. */ subscribeBot: function () { if (this.playerCanSubscribeBot) { var _this = this; FBInstant.player.subscribeBotAsync().then(function () { _this.emit('subscribebot'); }).catch(function (e) { _this.emit('subscribebotfail', e); }); } else { this.emit('subscribebotfail'); } return this; }, /** * Gets the associated data from the player based on the given key, or array of keys. * * The data is requested in an async call, so the result isn't available immediately. * * When the call completes the data is set into this plugins Data Manager and the * `getdata` event will be emitted. * * @method Phaser.FacebookInstantGamesPlugin#getData * @since 3.13.0 * * @param {(string|string[])} keys - The key/s of the data to retrieve. * * @return {this} This Facebook Instant Games Plugin instance. */ getData: function (keys) { if (!this.checkAPI('playerGetDataAsync')) { return this; } if (!Array.isArray(keys)) { keys = [ keys ]; } var _this = this; FBInstant.player.getDataAsync(keys).then(function (data) { _this.dataLocked = true; for (var key in data) { _this.data.set(key, data[key]); } _this.dataLocked = false; _this.emit('getdata', data); }); return this; }, /** * Set data to be saved to the designated cloud storage of the current player. The game can store up to 1MB of data for each unique player. * * The data save is requested in an async call, so the result isn't available immediately. * * Data managed via this plugins Data Manager instance is automatically synced with Facebook. However, you can call this * method directly if you need to replace the data object directly. * * When the APIs `setDataAsync` call resolves it will emit the `savedata` event from this plugin. If the call fails for some * reason it will emit `savedatafail` instead. * * The call resolving does not necessarily mean that the input has already been persisted. Rather, it means that the data was valid and * has been scheduled to be saved. It also guarantees that all values that were set are now available in `getData`. * * @method Phaser.FacebookInstantGamesPlugin#saveData * @since 3.13.0 * * @param {object} data - An object containing a set of key-value pairs that should be persisted to cloud storage. * The object must contain only serializable values - any non-serializable values will cause the entire modification to be rejected. * * @return {this} This Facebook Instant Games Plugin instance. */ saveData: function (data) { if (!this.checkAPI('playerSetDataAsync')) { return this; } var _this = this; FBInstant.player.setDataAsync(data).then(function () { _this.emit('savedata', data); }).catch(function (e) { _this.emit('savedatafail', e); }); return this; }, /** * Immediately flushes any changes to the player data to the designated cloud storage. * This function is expensive, and should primarily be used for critical changes where persistence needs to be immediate * and known by the game. Non-critical changes should rely on the platform to persist them in the background. * NOTE: Calls to player.setDataAsync will be rejected while this function's result is pending. * * Data managed via this plugins Data Manager instance is automatically synced with Facebook. However, you can call this * method directly if you need to flush the data directly. * * When the APIs `flushDataAsync` call resolves it will emit the `flushdata` event from this plugin. If the call fails for some * reason it will emit `flushdatafail` instead. * * @method Phaser.FacebookInstantGamesPlugin#flushData * @since 3.13.0 * * @return {this} This Facebook Instant Games Plugin instance. */ flushData: function () { if (!this.checkAPI('playerFlushDataAsync')) { return this; } var _this = this; FBInstant.player.flushDataAsync().then(function () { _this.emit('flushdata'); }).catch(function (e) { _this.emit('flushdatafail', e); }); return this; }, /** * Retrieve stats from the designated cloud storage of the current player. * * The data is requested in an async call, so the result isn't available immediately. * * When the call completes the `getstats` event will be emitted along with the data object returned. * * If the call fails, i.e. it's not in the list of supported APIs, or the request was rejected, * it will emit a `getstatsfail` event instead. * * @method Phaser.FacebookInstantGamesPlugin#getStats * @since 3.13.0 * * @param {string[]} [keys] - An optional array of unique keys to retrieve stats for. If the function is called without it, it will fetch all stats. * * @return {this} This Facebook Instant Games Plugin instance. */ getStats: function (keys) { if (!this.checkAPI('playerGetStatsAsync')) { return this; } var _this = this; FBInstant.player.getStatsAsync(keys).then(function (data) { _this.emit('getstats', data); }).catch(function (e) { _this.emit('getstatsfail', e); }); return this; }, /** * Save the stats of the current player to the designated cloud storage. * * Stats in the Facebook Instant Games API are purely numerical values paired with a string-based key. Only numbers can be saved as stats, * all other data types will be ignored. * * The data is requested in an async call, so the result isn't available immediately. * * When the call completes the `savestats` event will be emitted along with the data object returned. * * If the call fails, i.e. it's not in the list of supported APIs, or the request was rejected, * it will emit a `savestatsfail` event instead. * * @method Phaser.FacebookInstantGamesPlugin#saveStats * @since 3.13.0 * * @param {object} data - An object containing a set of key-value pairs that should be persisted to cloud storage as stats. Note that only numerical values are stored. * * @return {this} This Facebook Instant Games Plugin instance. */ saveStats: function (data) { if (!this.checkAPI('playerSetStatsAsync')) { return this; } var output = {}; for (var key in data) { if (typeof data[key] === 'number') { output[key] = data[key]; } } var _this = this; FBInstant.player.setStatsAsync(output).then(function () { _this.emit('savestats', output); }).catch(function (e) { _this.emit('savestatsfail', e); }); return this; }, /** * Increment the stats of the current player and save them to the designated cloud storage. * * Stats in the Facebook Instant Games API are purely numerical values paired with a string-based key. Only numbers can be saved as stats, * all other data types will be ignored. * * The data object provided for this call should contain offsets for how much to modify the stats by: * * ```javascript * this.facebook.incStats({ * level: 1, * zombiesSlain: 17, * rank: -1 * }); * ``` * * The data is requested in an async call, so the result isn't available immediately. * * When the call completes the `incstats` event will be emitted along with the data object returned. * * If the call fails, i.e. it's not in the list of supported APIs, or the request was rejected, * it will emit a `incstatsfail` event instead. * * @method Phaser.FacebookInstantGamesPlugin#incStats * @since 3.13.0 * * @param {object} data - An object containing a set of key-value pairs indicating how much to increment each stat in cloud storage. Note that only numerical values are processed. * * @return {this} This Facebook Instant Games Plugin instance. */ incStats: function (data) { if (!this.checkAPI('playerIncrementStatsAsync')) { return this; } var output = {}; for (var key in data) { if (typeof data[key] === 'number') { output[key] = data[key]; } } var _this = this; FBInstant.player.incrementStatsAsync(output).then(function (stats) { _this.emit('incstats', stats); }).catch(function (e) { _this.emit('incstatsfail', e); }); return this; }, /** * Sets the data associated with the individual gameplay session for the current context. * * This function should be called whenever the game would like to update the current session data. * * This session data may be used to populate a variety of payloads, such as game play webhooks. * * @method Phaser.FacebookInstantGamesPlugin#saveSession * @since 3.13.0 * * @param {object} data - An arbitrary data object, which must be less than or equal to 1000 characters when stringified. * * @return {this} This Facebook Instant Games Plugin instance. */ saveSession: function (data) { if (!this.checkAPI('setSessionData')) { return this; } var test = JSON.stringify(data); if (test.length <= 1000) { FBInstant.setSessionData(data); } else { console.warn('Session data too long. Max 1000 chars.'); } return this; }, /** * This invokes a dialog to let the user share specified content, either as a message in Messenger or as a post on the user's timeline. * * A blob of data can be attached to the share which every game session launched from the share will be able to access via the `this.entryPointData` property. * * This data must be less than or equal to 1000 characters when stringified. * * When this method is called you should consider your game paused. Listen out for the `resume` event from this plugin to know when the dialog has been closed. * * The user may choose to cancel the share action and close the dialog. The resulting `resume` event will be dispatched regardless if the user actually shared the content or not. * * @method Phaser.FacebookInstantGamesPlugin#openShare * @since 3.13.0 * * @param {string} text - A text message to be shared. * @param {string} key - The key of the texture to use as the share image. * @param {string} [frame] - The frame of the texture to use as the share image. Set to `null` if you don't require a frame, but do need to set session data. * @param {object} [sessionData] - A blob of data to attach to the share. * * @return {this} This Facebook Instant Games Plugin instance. */ openShare: function (text, key, frame, sessionData) { return this._share('SHARE', text, key, frame, sessionData); }, /** * This invokes a dialog to let the user invite a friend to play this game, either as a message in Messenger or as a post on the user's timeline. * * A blob of data can be attached to the share which every game session launched from the share will be able to access via the `this.entryPointData` property. * * This data must be less than or equal to 1000 characters when stringified. * * When this method is called you should consider your game paused. Listen out for the `resume` event from this plugin to know when the dialog has been closed. * * The user may choose to cancel the share action and close the dialog. The resulting `resume` event will be dispatched regardless if the user actually shared the content or not. * * @method Phaser.FacebookInstantGamesPlugin#openInvite * @since 3.13.0 * * @param {string} text - A text message to be shared. * @param {string} key - The key of the texture to use as the share image. * @param {string} [frame] - The frame of the texture to use as the share image. Set to `null` if you don't require a frame, but do need to set session data. * @param {object} [sessionData] - A blob of data to attach to the share. * * @return {this} This Facebook Instant Games Plugin instance. */ openInvite: function (text, key, frame, sessionData) { return this._share('INVITE', text, key, frame, sessionData); }, /** * This invokes a dialog to let the user share specified content, either as a message in Messenger or as a post on the user's timeline. * * A blob of data can be attached to the share which every game session launched from the share will be able to access via the `this.entryPointData` property. * * This data must be less than or equal to 1000 characters when stringified. * * When this method is called you should consider your game paused. Listen out for the `resume` event from this plugin to know when the dialog has been closed. * * The user may choose to cancel the share action and close the dialog. The resulting `resume` event will be dispatched regardless if the user actually shared the content or not. * * @method Phaser.FacebookInstantGamesPlugin#openRequest * @since 3.13.0 * * @param {string} text - A text message to be shared. * @param {string} key - The key of the texture to use as the share image. * @param {string} [frame] - The frame of the texture to use as the share image. Set to `null` if you don't require a frame, but do need to set session data. * @param {object} [sessionData] - A blob of data to attach to the share. * * @return {this} This Facebook Instant Games Plugin instance. */ openRequest: function (text, key, frame, sessionData) { return this._share('REQUEST', text, key, frame, sessionData); }, /** * This invokes a dialog to let the user share specified content, either as a message in Messenger or as a post on the user's timeline. * * A blob of data can be attached to the share which every game session launched from the share will be able to access via the `this.entryPointData` property. * * This data must be less than or equal to 1000 characters when stringified. * * When this method is called you should consider your game paused. Listen out for the `resume` event from this plugin to know when the dialog has been closed. * * The user may choose to cancel the share action and close the dialog. The resulting `resume` event will be dispatched regardless if the user actually shared the content or not. * * @method Phaser.FacebookInstantGamesPlugin#openChallenge * @since 3.13.0 * * @param {string} text - A text message to be shared. * @param {string} key - The key of the texture to use as the share image. * @param {string} [frame] - The frame of the texture to use as the share image. Set to `null` if you don't require a frame, but do need to set session data. * @param {object} [sessionData] - A blob of data to attach to the share. * * @return {this} This Facebook Instant Games Plugin instance. */ openChallenge: function (text, key, frame, sessionData) { return this._share('CHALLENGE', text, key, frame, sessionData); }, /** * Internal share handler. * * @method Phaser.FacebookInstantGamesPlugin#_share * @private * @since 3.13.0 * * @param {string} intent - ("INVITE" | "REQUEST" | "CHALLENGE" | "SHARE") Indicates the intent of the share. * @param {string} text - A text message to be shared. * @param {string} key - The key of the texture to use as the share image. * @param {string} [frame] - The frame of the texture to use as the share image. Set to `null` if you don't require a frame, but do need to set session data. * @param {object} [sessionData] - A blob of data to attach to the share. * * @return {this} This Facebook Instant Games Plugin instance. */ _share: function (intent, text, key, frame, sessionData) { if (!this.checkAPI('shareAsync')) { return this; } if (sessionData === undefined) { sessionData = {}; } if (key) { var imageData = this.game.textures.getBase64(key, frame); } // intent ("INVITE" | "REQUEST" | "CHALLENGE" | "SHARE") Indicates the intent of the share. // image string A base64 encoded image to be shared. // text string A text message to be shared. // data Object? A blob of data to attach to the share. All game sessions launched from the share will be able to access this blob through FBInstant.getEntryPointData(). var payload = { intent: intent, image: imageData, text: text, data: sessionData }; var _this = this; FBInstant.shareAsync(payload).then(function () { _this.emit('resume'); }); return this; }, /** * This function determines whether the number of participants in the current game context is between a given minimum and maximum, inclusive. * If one of the bounds is null only the other bound will be checked against. * It will always return the original result for the first call made in a context in a given game play session. * Subsequent calls, regardless of arguments, will return the answer to the original query until a context change occurs and the query result is reset. * * @method Phaser.FacebookInstantGamesPlugin#isSizeBetween * @since 3.13.0 * * @param {integer} [min] - The minimum bound of the context size query. * @param {integer} [max] - The maximum bound of the context size query. * * @return {object} The Context Size Response object in the format: `{answer: boolean, minSize: number?, maxSize: number?}`. */ isSizeBetween: function (min, max) { if (!this.checkAPI('contextIsSizeBetween')) { return this; } return FBInstant.context.isSizeBetween(min, max); }, /** * Request a switch into a specific context. If the player does not have permission to enter that context, * or if the player does not provide permission for the game to enter that context, this will emit a `switchfail` event. * * Otherwise, the plugin will emit the `switch` event when the game has switched into the specified context. * * @method Phaser.FacebookInstantGamesPlugin#switchContext * @since 3.13.0 * * @param {string} contextID - The ID of the desired context. * * @return {this} This Facebook Instant Games Plugin instance. */ switchContext: function (contextID) { if (!this.checkAPI('contextSwitchAsync')) { return this; } if (contextID !== this.contextID) { var _this = this; FBInstant.context.switchAsync(contextID).then(function () { _this.contextID = FBInstant.context.getID(); _this.emit('switch', _this.contextID); }).catch(function (e) { _this.emit('switchfail', e); }); } return this; }, /** * A filter that may be applied to a Context Choose operation. * * 'NEW_CONTEXT_ONLY' - Prefer to only surface contexts the game has not been played in before. * 'INCLUDE_EXISTING_CHALLENGES' - Include the "Existing Challenges" section, which surfaces actively played-in contexts that the player is a part of. * 'NEW_PLAYERS_ONLY' - In sections containing individuals, prefer people who have not played the game. * * @typedef {string} ContextFilter */ /** * A configuration object that may be applied to a Context Choose operation. * * @typedef {object} ChooseContextConfig * @property {ContextFilter[]} [filters] - The set of filters to apply to the context suggestions: 'NEW_CONTEXT_ONLY', 'INCLUDE_EXISTING_CHALLENGES' or 'NEW_PLAYERS_ONLY'. * @property {number} [maxSize] - The maximum number of participants that a suggested context should ideally have. * @property {number} [minSize] - The minimum number of participants that a suggested context should ideally have. */ /** * Opens a context selection dialog for the player. If the player selects an available context, * the client will attempt to switch into that context, and emit the `choose` event if successful. * Otherwise, if the player exits the menu or the client fails to switch into the new context, the `choosefail` event will be emitted. * * @method Phaser.FacebookInstantGamesPlugin#chooseContext * @since 3.13.0 * * @param {ChooseContextConfig} [options] - An object specifying conditions on the contexts that should be offered. * * @return {this} This Facebook Instant Games Plugin instance. */ chooseContext: function (options) { if (!this.checkAPI('contextChooseAsync')) { return this; } var _this = this; FBInstant.context.chooseAsync(options).then(function () { _this.contextID = FBInstant.context.getID(); _this.emit('choose', _this.contextID); }).catch(function (e) { _this.emit('choosefail', e); }); return this; }, /** * Attempts to create or switch into a context between a specified player and the current player. * This plugin will emit the `create` event once the context switch is completed. * If the API call fails, such as if the player listed is not a Connected Player of the current player or if the * player does not provide permission to enter the new context, then the plugin will emit a 'createfail' event. * * @method Phaser.FacebookInstantGamesPlugin#createContext * @since 3.13.0 * * @param {string} playerID - ID of the player. * * @return {this} This Facebook Instant Games Plugin instance. */ createContext: function (playerID) { if (!this.checkAPI('contextCreateAsync')) { return this; } var _this = this; FBInstant.context.createAsync(playerID).then(function () { _this.contextID = FBInstant.context.getID(); _this.emit('create', _this.contextID); }).catch(function (e) { _this.emit('createfail', e); }); return this;