예제 #1
0
 /// <summary>Fetch the score list for a given board.</summary>
 /// <returns>Promise resolved when the operation has completed. The attached value describes a list of scores, and
 ///     provides pagination functionality.</returns>
 /// <param name="board">The name of the board to fetch scores from.</param>
 /// <param name="limit">The maximum number of results to return per page.</param>
 /// <param name="offset">Number of the first result. Needs to be a multiple of `limit`. The special value of -1 can be used
 ///     to auto-select the page where the current logged in user is located, including his score in the result. After
 ///     that, you may use the paged result handler to fetch pages nearby.</param>
 public Promise<PagedList<Score>> List(string board, int limit = 30, int offset = 0)
 {
     UrlBuilder url = new UrlBuilder("/v2.6/gamer/scores").Path(domain).Path(board).QueryParam("count", limit);
     if (offset == -1) url.QueryParam("page", "me");
     else              url.QueryParam("page", offset / limit + 1);
     return Common.RunInTask<PagedList<Score>>(Gamer.MakeHttpRequest(url), (response, task) => {
         // Pagination computing
         Bundle boardData = response.BodyJson[board];
         int currentItems = boardData["scores"].AsArray().Count;
         int total = Math.Min(boardData["maxpage"] * limit, offset + currentItems);
         // Fetch listed scores
         PagedList<Score> scores = new PagedList<Score>(response.BodyJson, offset, total);
         int rank = boardData["rankOfFirst"];
         foreach (Bundle b in boardData["scores"].AsArray()) {
             scores.Add(new Score(b, rank++));
         }
         // Handle pagination
         if (offset > 0) {
             scores.Previous = () => List(board, limit, offset - limit);
         }
         if (offset + scores.Count < scores.Total) {
             scores.Next = () => List(board, limit, offset + limit);
         }
         task.PostResult(scores);
     });
 }
예제 #2
0
 /// <summary>Fetches a previously indexed object.</summary>
 /// <returns>Promise resolved when the request has finished.</returns>
 /// <param name="objectId">ID of the object to look for, as passed when indexing.</param>
 public Promise<IndexResult> GetObject(string objectId)
 {
     UrlBuilder url = new UrlBuilder("/v1/index").Path(Domain).Path(IndexName).Path(objectId);
     HttpRequest req = Cloud.MakeUnauthenticatedHttpRequest(url);
     return Common.RunInTask<IndexResult>(req, (response, task) => {
         task.PostResult(new IndexResult(response.BodyJson));
     });
 }
예제 #3
0
 /// <summary>Deletes an indexed entry. If you just want to update an entry, simply use IndexObject.</summary>
 /// <returns>Promise resolved when the request has finished.</returns>
 /// <param name="objectId">ID of the object to delete, as passed when indexing.</param>
 public Promise<Done> DeleteObject(string objectId)
 {
     UrlBuilder url = new UrlBuilder("/v1/index").Path(Domain).Path(IndexName).Path(objectId);
     HttpRequest req = Cloud.MakeUnauthenticatedHttpRequest(url);
     req.Method = "DELETE";
     return Common.RunInTask<Done>(req, (response, task) => {
         task.PostResult(new Done(true, response.BodyJson));
     });
 }
예제 #4
0
 /// <summary>Deletes a match. Only works if you are the one who created it and it is already finished.</summary>
 /// <returns>Promise resolved when the operation has completed.</returns>
 /// <param name="matchId">ID of the match to delete.</param>
 public Promise<Done> Delete(string matchId)
 {
     UrlBuilder url = new UrlBuilder("/v1/gamer/matches").Path(matchId);
     HttpRequest req = Gamer.MakeHttpRequest(url);
     req.Method = "DELETE";
     return Common.RunInTask<Done>(req, (response, task) => {
         task.PostResult(new Done(response.BodyJson));
     });
 }
예제 #5
0
 /// <summary>
 /// Allows to store arbitrary data for a given achievement and the current player (appears in the
 /// 'gamerData' node of achievements).
 /// </summary>
 /// <returns>Promise resolved when the operation has completed. The attached value contains the updated definition
 ///     of the achievement.</returns>
 /// <param name="achName">Name of the achievement to update.</param>
 /// <param name="data">Data to associate with the achievement, merged with the current data (that is, existing keys
 ///     are not affected)</param>
 public Promise<AchievementDefinition> AssociateData(string achName, Bundle data)
 {
     UrlBuilder url = new UrlBuilder("/v1/gamer/achievements").Path(domain).Path(achName).Path("gamerdata");
     HttpRequest req = Gamer.MakeHttpRequest(url);
     req.BodyJson = data;
     return Common.RunInTask<AchievementDefinition>(req, (response, task) => {
         task.PostResult(new AchievementDefinition(achName, response.BodyJson["achievement"]));
     });
 }
예제 #6
0
 /// <summary>
 /// Method to call in order to generate a temporary code that can be passed to another gamer so he can
 /// add us as a godfather.
 /// 
 /// The domain as specified by the #Domain method is the domain in which the godfather link should be
 /// established. "private" means it's local to this game only.
 ///
 /// </summary>
 /// <returns>Promise resolved when the operation has completed. The attached string is the generated code.</returns>
 public Promise<string> GenerateCode()
 {
     UrlBuilder url = new UrlBuilder("/v2.6/gamer/godfather").Path(domain);
     HttpRequest req = Gamer.MakeHttpRequest(url);
     req.Method = "PUT";
     return Common.RunInTask<string>(req, (response, task) => {
         task.PostResult(response.BodyJson["godfathercode"]);
     });
 }
예제 #7
0
 /// <summary>Retrieves the rank that a given score would have on the leaderboard, without actually registering the score.</summary>
 /// <returns>Promise resolved when the operation has completed. The attached value contains the rank that the
 ///     score would have (position in the board).</returns>
 /// <param name="score">The score (numeric value) to check for ranking.</param>
 /// <param name="board">The name of the board to check the ranking against. Should match the board where a score has
 ///     already been posted.</param>
 public Promise<int> GetRank(long score, string board)
 {
     UrlBuilder url = new UrlBuilder("/v2.6/gamer/scores").Path(domain).Path(board);
     HttpRequest req = Gamer.MakeHttpRequest(url);
     req.BodyJson = Bundle.CreateObject("score", score);
     req.Method = "PUT";
     return Common.RunInTask<int>(req, (response, task) => {
         task.PostResult(response.BodyJson["rank"]);
     });
 }
예제 #8
0
 /// <summary>This method can be used to retrieve the gamer who have added you as a godfather.</summary>
 /// <returns>Promise resolved when the operation has completed.</returns>
 public Promise<NonpagedList<GamerInfo>> GetGodchildren()
 {
     UrlBuilder url = new UrlBuilder("/v2.6/gamer/godchildren").Path(domain);
     HttpRequest req = Gamer.MakeHttpRequest(url);
     return Common.RunInTask<NonpagedList<GamerInfo>>(req, (response, task) => {
         var result = new NonpagedList<GamerInfo>(response.BodyJson);
         foreach (Bundle b in response.BodyJson["godchildren"].AsArray()) {
             result.Add(new GamerInfo(b));
         }
         task.PostResult(result);
     });
 }
예제 #9
0
 /// <summary>Fetches information about the status of the achievements configured for this game.</summary>
 /// <returns>Promise resolved when the operation has completed. The attached value is the list of achievements
 ///     with their current state.</returns>
 public Promise<Dictionary<string, AchievementDefinition>> List()
 {
     UrlBuilder url = new UrlBuilder("/v1/gamer/achievements").Path(domain);
     HttpRequest req = Gamer.MakeHttpRequest(url);
     return Common.RunInTask<Dictionary<string, AchievementDefinition>>(req, (response, task) => {
         Dictionary<string, AchievementDefinition> result = new Dictionary<string,AchievementDefinition>();
         foreach (var pair in response.BodyJson["achievements"].AsDictionary()) {
             result[pair.Key] = new AchievementDefinition(pair.Key, pair.Value);
         }
         task.PostResult(result);
     });
 }
예제 #10
0
 /// <summary>
 /// Indexes a new object.
 /// Use this API to add or update an object in an index. You can have as many indexes as you need: one
 /// for gamer properties, one for matches, one for finished matches, etc. It only depends on what you
 /// want to search for.
 /// </summary>
 /// <returns>Promise resolved when the request has finished.</returns>
 /// <param name="objectId">The ID of the object to be indexed. It can be anything; this ID only needs to uniquely
 ///     identify your document. Therefore, using the match ID to index a match is recommended for instance.</param>
 /// <param name="properties">A freeform object, whose attributes will be indexed and searchable. These properties
 ///     are typed! So if 'age' is once passed as an int, it must always be an int, or an error will be
 ///     thrown upon insertion.</param>
 /// <param name="payload">Another freeform object. These properties are attached to the document in the same way
 ///     as the properties, however those are not indexed (cannot be looked for in a search request). Its
 ///     content is returned in searches (#CotcSdk.IndexResult.Payload property).</param>
 public Promise<Done> IndexObject(string objectId, Bundle properties, Bundle payload)
 {
     UrlBuilder url = new UrlBuilder("/v1/index").Path(Domain).Path(IndexName);
     HttpRequest req = Cloud.MakeUnauthenticatedHttpRequest(url);
     req.BodyJson = Bundle.CreateObject(
         "id", objectId,
         "properties", properties,
         "payload", payload
     );
     return Common.RunInTask<Done>(req, (response, task) => {
         task.PostResult(new Done(true, response.BodyJson));
     });
 }
예제 #11
0
 /// <summary>
 /// Fetch the list of products as configured on the backoffice. Note that this doesn't include any information
 /// about pricing and so on: the external store plugin is required to do so.
 /// Note that this call returns the catalog as configured on the CotC server, which may not be exhaustive if
 /// additional products are configured on iTunes Connect but not reported to the CotC servers.
 /// </summary>
 /// <param name="limit">The maximum number of results to return per page.</param>
 /// <param name="offset">Number of the first result.</param>
 /// <returns>Promise resolved when the operation has completed. The attached value describes a list of products,
 ///     with pagination functionality.</returns>
 public Promise<PagedList<ConfiguredProduct>> ListConfiguredProducts(int limit = 30, int offset = 0)
 {
     UrlBuilder url = new UrlBuilder("/v1/gamer/store/products").QueryParam("limit", limit).QueryParam("skip", offset);
     return Common.RunInTask<PagedList<ConfiguredProduct>>(Gamer.MakeHttpRequest(url), (response, task) => {
         PagedList<ConfiguredProduct> products = new PagedList<ConfiguredProduct>(response.BodyJson, offset, response.BodyJson["count"]);
         foreach (Bundle b in response.BodyJson["products"].AsArray()) {
             products.Add(new ConfiguredProduct(b));
         }
         // Handle pagination
         if (offset > 0) {
             products.Previous = () => ListConfiguredProducts(limit, offset - limit);
         }
         if (offset + products.Count < products.Total) {
             products.Next = () => ListConfiguredProducts(limit, offset + limit);
         }
         task.PostResult(products);
     });
 }
예제 #12
0
        /// <summary>
        /// Creates a match, available for join by other players. If you would like to make your match private, please read
        /// the general documentation about matches.
        /// </summary>
        /// <returns>Promise resolved when the operation has completed. The attached Match object allows to operate with the
        ///     match.</returns>
        /// <param name="maxPlayers">The maximum number of players who may be in the game at a time.</param>
        /// <param name="description">String describing the match (available for other who want to join).</param>
        /// <param name="customProperties">Freeform object containing the properties of the match, which may be used by other players
        ///     to search for a suited match.</param>
        /// <param name="shoe">Freeform object containing a list of objects which will be shuffled upon match creation. This offers
        ///     an easy way to make a random generator that is safe, unbiased (since made on the server) and can be verified
        ///     by all players once the game is finished. This bundle needs to be an array (use Bundle.CreateArray).</param>
        public Promise<Match> Create(int maxPlayers, string description = null, Bundle customProperties = null, Bundle shoe = null)
        {
            var task = new Promise<Match>();
            if (shoe != null && shoe.Type != Bundle.DataType.Array) {
                task.PostResult(ErrorCode.BadParameters, "The shoe must be an array");
                return task;
            }

            UrlBuilder url = new UrlBuilder("/v1/gamer/matches").QueryParam("domain", domain);
            HttpRequest req = Gamer.MakeHttpRequest(url);
            Bundle config = Bundle.CreateObject();
            config["maxPlayers"] = maxPlayers;
            config["description"] = description;
            config["customProperties"] = customProperties;
            config["shoe"] = shoe;
            req.BodyJson = config;
            return Common.RunRequest(req, task, (HttpResponse response) => {
                task.PostResult(new Match(Gamer, response.BodyJson["match"]));
            });
        }
예제 #13
0
 /// <summary>
 /// Asks to join the match with a given ID. Do not use this if you are already part of the match.
 /// This call is not scoped by domain (it uses the Match ID directly).
 /// </summary>
 /// <returns>Promise resolved when the operation has completed. In case of success, you get the exact same
 ///     match object that would be returned by a call to Create or Fetch. It can be used to interact with
 ///     the match as the user who just joined.</returns>
 /// <param name="matchId">The ID of an existing match to join. It can be fetched from the Match object (MatchId).</param>
 /// <param name="notification">Optional push notification to be sent to inactive players (see class definition).</param>
 public Promise<Match> Join(string matchId, PushNotification notification = null)
 {
     UrlBuilder url = new UrlBuilder("/v1/gamer/matches").Path(matchId).Path("join");
     HttpRequest req = Gamer.MakeHttpRequest(url);
     req.BodyJson = Bundle.CreateObject("osn", notification != null ? notification.Data : null);
     return Common.RunInTask<Match>(req, (response, task) => {
         task.PostResult(new Match(Gamer, response.BodyJson["match"]));
     });
 }
예제 #14
0
 /// <summary>
 /// Can be used to list the active matches for this game. In general, it is not recommended to proceed this way
 /// if your goal is to display the games that may be joined. The indexing API is better suited to this use case
 /// (index the match along with properties and look for matches matching the desired properties).
 /// </summary>
 /// <returns>Promise resolved when the operation has completed. The list of matches filtered according to the
 ///     following parameters is provided.</returns>
 /// <param name="participating">Set to true to only list matches to which this user is participating.</param>
 /// <param name="invited">Set to true to filter by matches you are invited to (only include them).</param>
 /// <param name="finished">Set to true to also include finished matchs (which are filtered out by default).</param>
 /// <param name="full">Set to true to also include games where the maximum number of players has been reached.</param>
 /// <param name="limit">For pagination, allows to set a greater or smaller page size than the default 30.</param>
 /// <param name="offset">For pagination, avoid using it explicitly.</param>
 public Promise<PagedList<MatchListResult>> List(bool participating = false, bool invited = false, bool finished = false, bool full = false, int limit = 30, int offset = 0)
 {
     UrlBuilder url = new UrlBuilder("/v1/gamer/matches");
     url.QueryParam("domain", domain).QueryParam("offset", offset).QueryParam("limit", limit);
     if (participating) url.QueryParam("participating");
     if (finished) url.QueryParam("finished");
     if (invited) url.QueryParam("invited");
     if (full) url.QueryParam("full");
     // Request for current results
     return Common.RunInTask<PagedList<MatchListResult>>(Gamer.MakeHttpRequest(url), (response, task) => {
         PagedList<MatchListResult> matches = new PagedList<MatchListResult>(response.BodyJson, offset, response.BodyJson["count"]);
         foreach (Bundle b in response.BodyJson["matches"].AsArray()) {
             matches.Add(new MatchListResult(b));
         }
         // Handle pagination
         if (offset > 0) {
             matches.Previous = () => List(participating, invited, finished, full, limit, offset - limit);
         }
         if (offset + matches.Count < matches.Total) {
             matches.Next = () => List(participating, invited, finished, full, limit, offset + limit);
         }
         task.PostResult(matches);
     });
 }
예제 #15
0
파일: Match.cs 프로젝트: StudioJD/unity-sdk
        /// <summary>Posts a move to other players.</summary>
        /// <returns>Promise resolved when the operation has completed.</returns>
        /// <param name="moveData">A freeform object indicating the move data to be posted and transfered to other players. This
        ///     move data will be kept in the events, and new players should be able to use it to reproduce the local game
        ///     state.</param>
        /// <param name="updatedGameState">A freeform object replacing the global game state, to be used by players who join from
        ///     now on. Passing a non null value clears the pending events in the match.</param>
        /// <param name="notification">A push notification that can be sent to all players except you.</param>
        public Promise<Done> PostMove(Bundle moveData, Bundle updatedGameState = null, PushNotification notification = null)
        {
            UrlBuilder url = new UrlBuilder("/v1/gamer/matches").Path(MatchId).Path("move").QueryParam("lastEventId", LastEventId);
            Bundle config = Bundle.CreateObject();
            config["move"] = moveData;
            config["globalState"] = updatedGameState;
            if (notification != null) config["osn"] = notification.Data;

            HttpRequest req = Gamer.MakeHttpRequest(url);
            req.BodyJson = config;
            return Common.RunInTask<Done>(req, (response, task) => {
                UpdateWithServerData(response.BodyJson["match"]);
                // Record event
                if (updatedGameState != null) {
                    Moves.Clear();
                    GlobalState = updatedGameState;
                }
                Moves.Add(new MatchMove(Gamer.GamerId, moveData));
                task.PostResult(new Done(true, response.BodyJson));
            });
        }
예제 #16
0
파일: Match.cs 프로젝트: StudioJD/unity-sdk
 /// <summary>Leaves the match.</summary>
 /// <returns>Promise resolved when the operation has completed.</returns>
 /// <param name="notification">A push notification that can be sent to all players except you.</param>
 public Promise<Done> Leave(PushNotification notification = null)
 {
     UrlBuilder url = new UrlBuilder("/v1/gamer/matches").Path(MatchId).Path("leave");
     HttpRequest req = Gamer.MakeHttpRequest(url);
     req.BodyJson = Bundle.CreateObject("osn", notification != null ? notification.Data : null);
     return Common.RunInTask<Done>(req, (response, task) => {
         UpdateWithServerData(response.BodyJson["match"]);
         task.PostResult(new Done(true, response.BodyJson));
     });
 }
예제 #17
0
파일: Match.cs 프로젝트: StudioJD/unity-sdk
 /// <summary>Terminates the match. You need to be the creator of the match to perform this operation.</summary>
 /// <returns>Promise resolved when the operation has completed.</returns>
 /// <param name="deleteToo">If true, deletes the match if it finishes successfully or is already finished.</param>
 /// <param name="notification">A notification that can be sent to all players currently playing the match (except you).</param>
 public Promise<Done> Finish(bool deleteToo = false, PushNotification notification = null)
 {
     UrlBuilder url = new UrlBuilder("/v1/gamer/matches").Path(MatchId).Path("finish");
     url.QueryParam("lastEventId", LastEventId);
     HttpRequest req = Gamer.MakeHttpRequest(url);
     req.BodyJson = Bundle.CreateObject("osn", notification != null ? notification.Data : null);
     return Common.RunInTask<Done>(req, (response, task) => {
         UpdateWithServerData(response.BodyJson["match"]);
         // Affect match
         Status = MatchStatus.Finished;
         // Also delete match
         if (deleteToo) {
             Gamer.Matches.Delete(MatchId).ForwardTo(task);
         }
         else {
             task.PostResult(new Done(true, response.BodyJson));
         }
     });
 }
예제 #18
0
파일: Match.cs 프로젝트: StudioJD/unity-sdk
 /// <summary>Draws an item from the shoe.</summary>
 /// <returns>Promise resolved when the operation has completed. The attached bundle contains an array of items drawn
 ///     from the shoe. You may do `(int)result.Value[0]` to fetch the first value as integer.</returns>
 /// <param name="count">The number of items to draw from the shoe.</param>
 /// <param name="notification">A notification that can be sent to all players currently playing the match (except you).</param>
 public Promise<DrawnItemsResult> DrawFromShoe(int count = 1, PushNotification notification = null)
 {
     UrlBuilder url = new UrlBuilder("/v1/gamer/matches").Path(MatchId).Path("shoe").Path("draw");
     url.QueryParam("count", count).QueryParam("lastEventId", LastEventId);
     HttpRequest req = Gamer.MakeHttpRequest(url);
     req.BodyJson = Bundle.CreateObject("osn", notification != null ? notification.Data : null);
     return Common.RunInTask<DrawnItemsResult>(req, (response, task) => {
         UpdateWithServerData(response.BodyJson["match"]);
         task.PostResult(new DrawnItemsResult(response.BodyJson));
     });
 }
예제 #19
0
        /// <summary>
        /// When you have data about friends from another social network, you can post them to CotC servers using
        /// these function.
        /// This will automatically add them as a friend on CotC as they get recognized on our servers.
        /// The friends get associated to the domain of this object.
        /// Note: this function was once called PostSocialNetworkFriends but renamed due to it being misleading.
        /// </summary>
        /// <returns>Promise resolved when the operation has completed. The attached value is the same list as passed,
        ///     enriched with potential information about the gamer (member #CotcSdk.SocialNetworkFriend.ClanInfo) for
        ///     gamers who are already registered on CotC servers.</returns>
        /// <param name="network">The network with which these friends are associated.</param>
        /// <param name="friends">A list of data about the friends fetched on the social network.</param>
        /// <param name="automatching">If true, synchronizes the CotC friends with the list. That is, the provided
        /// social network friends become your friends on CotC as well (reported on ListFriends and such).</param>
        public Promise<SocialNetworkFriendResponse> ListNetworkFriends(LoginNetwork network, List<SocialNetworkFriend> friends, bool automatching = false)
        {
            var task = new Promise<SocialNetworkFriendResponse>();
            UrlBuilder url = new UrlBuilder("/v2.12/gamer/friends").Path(domain).QueryParam("network", network.Describe());
            HttpRequest req = Gamer.MakeHttpRequest(url);
            Bundle body = Bundle.CreateObject();
            Bundle friendData = (body["friends"] = Bundle.CreateObject());
            foreach (SocialNetworkFriend f in friends) {
                friendData[f.Id] = f.ToBundle();
            }
            body["automatching"] = automatching;

            req.BodyJson = body;
            return Common.RunRequest(req, task, (HttpResponse response) => {
                task.PostResult(new SocialNetworkFriendResponse(response.BodyJson));
            });
        }
예제 #20
0
 /// <summary>Fetch the score list for a given board, restricting to the scores made by the friends of the current user.</summary>
 /// <returns>Promise resolved when the operation has completed. The attached value describes a list of scores,
 ///     without pagination functionality.</returns>
 /// <param name="board">The name of the board to fetch scores from.</param>
 public Promise<NonpagedList<Score>> ListFriendScores(string board)
 {
     UrlBuilder url = new UrlBuilder("/v2.6/gamer/scores").Path(domain).Path(board).QueryParam("type", "friendscore");
     return Common.RunInTask<NonpagedList<Score>>(Gamer.MakeHttpRequest(url), (response, task) => {
         var scores = new NonpagedList<Score>(response.BodyJson);
         foreach (Bundle b in response.BodyJson[board].AsArray()) {
             scores.Add(new Score(b));
         }
         task.PostResult(scores);
     });
 }
예제 #21
0
 /// <summary>Retrieves the best scores of this gamer, on all board he has posted one score to.</summary>
 /// <returns>Promise resolved when the operation has completed. The attached value contains information about
 ///     the best scores of the user, indexed by board name.
 ///     *IMPORTANT*: in the results, the gamer information is not provided. GamerInfo is always null.</returns>
 public Promise<Dictionary<string, Score>> ListUserBestScores()
 {
     UrlBuilder url = new UrlBuilder("/v2.6/gamer/bestscores").Path(domain);
     HttpRequest req = Gamer.MakeHttpRequest(url);
     return Common.RunInTask<Dictionary<string, Score>>(req, (response, task) => {
         Dictionary<string, Score> scores = new Dictionary<string, Score>();
         foreach (var pair in response.BodyJson.AsDictionary()) {
             Score s = new Score(pair.Value);
             s.GamerInfo = null;
             scores[pair.Key] = s;
         }
         task.PostResult(scores);
     });
 }
예제 #22
0
 private Promise<IndexSearchResult> Search(string query, Bundle jsonData, List<string> sortingProperties, int limit, int offset)
 {
     UrlBuilder url = new UrlBuilder("/v1/index").Path(Domain).Path(IndexName).Path("search");
     if (query != null) url.QueryParam("q", query);
     url.QueryParam("from", offset).QueryParam("max", limit);
     // Build sort property
     if (sortingProperties != null) {
         Bundle sort = Bundle.CreateArray();
         foreach (string s in sortingProperties) sort.Add(s);
         url.QueryParam("sort", sort.ToJson());
     }
     var request = Cloud.MakeUnauthenticatedHttpRequest(url);
     request.Method = "POST";
     if (jsonData != null) request.BodyJson = jsonData;
     return Common.RunInTask<IndexSearchResult>(request, (response, task) => {
         // Fetch listed scores
         IndexSearchResult result = new IndexSearchResult(response.BodyJson, offset);
         foreach (Bundle b in response.BodyJson["hits"].AsArray()) {
             result.Hits.Add(new IndexResult(b));
         }
         // Handle pagination
         if (offset > 0) {
             result.Hits.Previous = () => {
                 var promise = new Promise<PagedList<IndexResult>>();
                 Search(query, jsonData, sortingProperties, limit, offset - limit)
                     .Then(r => promise.Resolve(r.Hits))
                     .Catch(e => promise.Reject(e));
                 return promise;
             };
         }
         if (offset + result.Hits.Count < result.Hits.Total) {
             result.Hits.Next = () => {
                 var promise = new Promise<PagedList<IndexResult>>();
                 Search(query, jsonData, sortingProperties, limit, offset + limit)
                     .Then(r => promise.Resolve(r.Hits))
                     .Catch(e => promise.Reject(e));
                 return promise;
             };
         }
         task.PostResult(result);
     });
 }
예제 #23
0
 /// <summary>
 /// Fetches a Match object corresponding to a match which the player already belongs to.
 /// It can be used either to obtain additional information about a running match (by inspecting the resulting
 /// match object), or to continue an existing match (by keeping the match object which corresponds to the one
 /// that was returned by the Create method).
 /// This call is not scoped by domain (it uses the Match ID directly).
 /// </summary>
 /// <returns>Promise resolved when the operation has completed. The attached Match object allows to operate with
 ///     the match.</returns>
 /// <param name="matchId">The ID of an existing match to resume. It can be fetched from the Match object (MatchId).</param>
 public Promise<Match> Fetch(string matchId)
 {
     UrlBuilder url = new UrlBuilder("/v1/gamer/matches").Path(matchId);
     HttpRequest req = Gamer.MakeHttpRequest(url);
     return Common.RunInTask<Match>(req, (response, task) => {
         task.PostResult(new Match(Gamer, response.BodyJson["match"]));
     });
 }
예제 #24
0
 /// <summary>Post a score.</summary>
 /// <returns>Promise resolved when the operation has completed. The attached value contains the new rank of the
 ///     player as well as whether the score was saved.</returns>
 /// <param name="score">The score (numeric value) to record.</param>
 /// <param name="board">The name of the board to post the score to. You may have as many boards as you like for your
 ///     game, and scores are scoped between them.</param>
 /// <param name="order">The order for this board. As board are not configured on the server, any client can create a
 ///     board dynamically. This parameter serves as as a description for the board and is used only upon
 ///     creation (that is, the first player posting to the named board).</param>
 /// <param name="scoreInfo">An optional string used to describe the score made by the user.</param>
 /// <param name="forceSave">When set to true, the score is saved even if its value is less than the past best score
 ///     for this player.</param>
 public Promise<PostedGameScore> Post(long score, string board, ScoreOrder order, string scoreInfo = null, bool forceSave = false)
 {
     UrlBuilder url = new UrlBuilder("/v2.6/gamer/scores").Path(domain).Path(board);
     switch (order) {
         case ScoreOrder.HighToLow: url.QueryParam("order", "hightolow"); break;
         case ScoreOrder.LowToHigh: url.QueryParam("order", "lowtohigh"); break;
     }
     url.QueryParam("mayvary", forceSave);
     HttpRequest req = Gamer.MakeHttpRequest(url);
     req.BodyJson = Bundle.CreateObject("score", score, "info", scoreInfo);
     return Common.RunInTask<PostedGameScore>(req, (response, task) => {
         task.PostResult(new PostedGameScore(response.BodyJson));
     });
 }
예제 #25
0
        /// <summary>
        /// Use this method to send a message to another user from your game.
        /// 
        /// Messages are sent to a specific user, in a specific domain. You can use domains to send messages
        /// across games (or use private for messages sent to your game only).
        ///
        /// </summary>
        /// <returns>Promise resolved when the operation has completed.</returns>
        /// <param name="gamerId">ID of the recipient gamer.</param>
        /// <param name="eventData">JSON object representing the event to be sent. The recipient will receive it as is
        ///     when subscribed to a #CotcSdk.DomainEventLoop (ReceivedEvent property). If the application is not active,
        ///     the message will be queued and transmitted the next time the domain event loop is started.</param>
        /// <param name="notification">Push notification to send to the recipient player if not currently active.</param>
        public Promise<Done> SendEvent(string gamerId, Bundle eventData, PushNotification notification = null)
        {
            UrlBuilder url = new UrlBuilder("/v1/gamer/event").Path(domain).Path(gamerId);
            HttpRequest req = Gamer.MakeHttpRequest(url);
            Bundle config = Bundle.CreateObject();
            config["type"] = "user";
            config["event"] = eventData;
            config["from"] = Gamer.GamerId;
            config["to"] = gamerId;
            config["name"] = Gamer["profile"]["displayname"];
            if (notification != null) config["osn"] = notification.Data;

            req.BodyJson = config;
            return Common.RunInTask<Done>(req, (response, task) => {
                task.PostResult(new Done(true, response.BodyJson));
            });
        }
예제 #26
0
 /// <summary>Call this to attribute a godfather to the currently logged in user.</summary>
 /// <returns>Promise resolved when the operation has completed.</returns>
 /// <param name="code">Is a string as generated by #GenerateCode.</param>
 /// <param name="rewardTx">A transaction Json rewarding the godfather formed as follows:
 ///     { transaction : { "unit" : amount},
 ///     description : "reward transaction",
 ///     domain : "com.clanoftcloud.text.DOMAIN" }
 ///     where description and domain are optional.</param>
 /// <param name="notification">Optional OS notification to be sent to the godfather who generated the code.
 ///     The godfather will reveive an event of type 'godchildren' containing the id of the godchildren
 ///     and the balance/achievements field if rewarded.</param>
 public Promise<Done> UseCode(string code, Bundle rewardTx = null, PushNotification notification = null)
 {
     UrlBuilder url = new UrlBuilder("/v2.6/gamer/godfather").Path(domain);
     HttpRequest req = Gamer.MakeHttpRequest(url);
     Bundle config = Bundle.CreateObject();
     config["godfather"] = code;
     config["osn"] = notification != null ? notification.Data : null;
     config["reward"] = rewardTx;
     req.BodyJson = config;
     return Common.RunInTask<Done>(req, (response, task) => {
         task.PostResult(new Done(response.BodyJson));
     });
 }
예제 #27
0
 /// <summary>Allows to change the relation of a friendship inside the application.</summary>
 /// <returns>Promise resolved when the operation has completed.</returns>
 /// <param name="gamerId">ID of the gamer to change the relationship (fetched using ListFriends for instance).</param>
 /// <param name="state">The new state to set.</param>
 /// <param name="notification">Optional OS notification to be sent to indicate the player that the status has changed.</param>
 public Promise<Done> ChangeRelationshipStatus(string gamerId, FriendRelationshipStatus state, PushNotification notification = null)
 {
     UrlBuilder url = new UrlBuilder("/v2.6/gamer/friends").Path(domain).Path(gamerId).QueryParam("status", state.ToString().ToLower());
     HttpRequest req = Gamer.MakeHttpRequest(url);
     req.BodyJson = Bundle.CreateObject("osn", notification != null ? notification.Data : null);
     return Common.RunInTask<Done>(req, (response, task) => {
         task.PostResult(new Done(response.BodyJson));
     });
 }
예제 #28
0
 /// <summary>Method used to retrieve the application's friends of the currently logged in profile.</summary>
 /// <returns>Promise resolved when the operation has completed, with the fetched list of friends.</returns>
 /// <param name="filterBlacklisted">When set to true, restricts to blacklisted friends.</param>
 public Promise<NonpagedList<GamerInfo>> ListFriends(bool filterBlacklisted = false)
 {
     UrlBuilder url = new UrlBuilder("/v2.6/gamer/friends").Path(domain);
     if (filterBlacklisted) url.QueryParam("status", "blacklist");
     HttpRequest req = Gamer.MakeHttpRequest(url);
     return Common.RunInTask<NonpagedList<GamerInfo>>(req, (response, task) => {
         var result = new NonpagedList<GamerInfo>(response.BodyJson);
         foreach (Bundle f in response.BodyJson["friends"].AsArray()) {
             result.Add(new GamerInfo(f));
         }
         task.PostResult(result);
     });
 }
예제 #29
0
 /// <summary>This method can be used to retrieve the godfather of the gamer.</summary>
 /// <returns>Promise resolved when the operation has completed.</returns>
 public Promise<GamerInfo> GetGodfather()
 {
     UrlBuilder url = new UrlBuilder("/v2.6/gamer/godfather").Path(domain);
     HttpRequest req = Gamer.MakeHttpRequest(url);
     return Common.RunInTask<GamerInfo>(req, (response, task) => {
         task.PostResult(new GamerInfo(response.BodyJson["godfather"]));
     });
 }
예제 #30
0
        private void Run()
        {
            int delay = LoopIterationDuration;
            string messageToAcknowledge = null;
            bool lastResultPositive = true;

            while (!Stopped) {
                if (!lastResultPositive) {
                    // Last time failed, wait a bit to avoid bombing the Internet.
                    Thread.Sleep(PopEventDelayThreadHold);
                }

                UrlBuilder url = new UrlBuilder("/v1/gamer/event");
                url.Path(Domain).QueryParam("timeout", delay);
                if (messageToAcknowledge != null) {
                    url.QueryParam("ack", messageToAcknowledge);
                }

                CurrentRequest = Gamer.MakeHttpRequest(url);
                CurrentRequest.RetryPolicy = HttpRequest.Policy.NonpermanentErrors;
                CurrentRequest.TimeoutMillisec = delay + 30000;
                CurrentRequest.DoNotEnqueue = true;

                Managers.HttpClient.Run(CurrentRequest, (HttpResponse res) => {
                    CurrentRequest = null;
                    try {
                        lastResultPositive = true;
                        if (res.StatusCode == 200) {
                            messageToAcknowledge = res.BodyJson["id"];
                            ProcessEvent(res);
                        }
                        else if (res.StatusCode != 204) {
                            lastResultPositive = false;
                            // Non retriable error -> kill ourselves
                            if (res.StatusCode >= 400 && res.StatusCode < 500) {
                                Stopped = true;
                            }
                        }
                    }
                    catch (Exception e) {
                        Common.LogError("Exception happened in pop event loop: " + e.ToString());
                    }
                    SynchronousRequestLock.Set();
                });

                // Wait for request (synchronous)
                SynchronousRequestLock.WaitOne();

                // Wait if suspended
                if (Paused) {
                    SynchronousRequestLock.WaitOne();
                    lastResultPositive = true;
                }
            }
            Common.Log("Finished pop event thread " + Thread.CurrentThread.ManagedThreadId);
        }