Asynchronous Invites

Hey guys,

So I have been analyzing the Memory Demo quite throughly and it has all the features I need for an asynchronous game except one :

The ability for Asynchronous Invites to happen. To be more specific :

For a two player game like chess -

1. Player A starts a game, is waiting for an opponent but doesn't find one yet, so quits the app.

2. Player B starts a game. Currently, this would start a new game for Player B, even though Player A has a game that's waiting for another player.

I would like Player B, to have joined the game that Player A had started.

Currently, that would only happen, if both were online at the same time.

Any advice on how I can achieve this functionality ?

The only solution I can think of is, somehow getting the currently existing rooms which have only one player (even if noone is in the room currently) and get the roomId/name and join it. Is this possible with the current Photon Tech ?

Comments

  • This sounds like matchmaking. Maybe http://doc.exitgames.com/en/turnbased/current/reference/matchmaking-and-lobby could shed some light on what you want to achieve.
  • @ZZyrex
    Thanks for the link. I had looked through it before but did another look through to make sure.

    Doesn't seem like there is that sort of functionality in the documentation.

    So on the database side, the game does exist (created via the GameCreate Webhook, I assume).

    But on the photon side, I am unsure if Photon kills rooms where there are no active players, for the sake of efficiency/storage.

    If my guess is right, this is why they can't be match made against.

    I am hoping someone from Photon verifies this for me. If so, maybe there is some way to do this via a Webhook.
  • *Bump*

    Any help on this ?
  • Hi guys,

    with the current turnbased version you do have to implement this via WebHook/WebRpc.
    That said we are working to add this feature (async matchmaking) right now and its high in our prio
    so it should be ready soonish ... though I can't give you an ETA jet.

    -Philip

    PS: sorry for the delayed answer ...
  • Hi Philip,

    Thanks for confirming this.

    I know the ETA might be hard to give and its good to know that its high in priority.

    If possible, could you hint at how you would do it in the Webhook ?

    Also from the Webhook stuff, I am having a hard time figuring out when a game is actually saved as an entry in the database.

    Is it only when all players (or the MasterClient) leave the game, the first time it is created ?

    Thanks!
  • Hi,

    > I am having a hard time figuring out when a game is actually saved as an entry in the database.
    The GameClose WebHook is called when all active (connected) players disconnected.
    If the room still has inactive players planning to come back (did not abandon) you will get the state
    (and Type="Save") otherewise you will get the call without the state (and Type="Close").

    In case you'd like to have the state in between - we include it in the GameProperties Webhook as well.

    > could you hint at how you would do it in the Webhook ?
    you are almost right with
    > somehow getting the currently existing rooms which have only one player
    You'd have to extend the service with a WebRpc call that does return one game
    from the list of games that have only one player.
    Note: You should mark the game and not return it for a while - since you can assume
    the user requesting it is goin to endup joining ... you should include the game again if
    it wasn't joind for a minute for instance.

    #More details on implementation of WebRpc:
    If you have a look at the Memory demo you'll see that the client requests its saved games list. For this
    we use the WebRPC feature to call GetGameList.
    OpWebRpc("GetGameList", null);

    Where you can send parameters to your service as get parameters in the path (NOTE: that it will be still a POST request to your service
    but you can gather the parameters from the request)
    [code2=csharp]OpWebRpc("YourServicePath?getpar1=1&getpar2=xyz", null);[/code2]

    or you send it in an object, that will be auto transformed to a json object:
    [code2=csharp]OpWebRpc("YourServicePath?getpar1=1&getpar2=xyz", new Dictionary<string, object>() { { "p1", "one" }, { "p2", "two" } });
    OpWebRpc("YourServicePath?getpar1=1&getpar2=xyz", new int[] { 1, 2, 3 });[/code2]

    Your webservice will get a call like this:
    [code2=plain]POST yourservice.yourcompany.io/YourServicePath?getpar1=1&getpar2=xyz& HTTP/1.1
    Content-Length: 112
    ...
    Accept: application/json
    Content-Type: application/json

    {"AppId":"F71D7B45-82BF-44E1-9C19-1C299E0C27E9","AppVersion":"","Region":"EU","UserId":"MyUserId0", "p1":"one","p2":"two"}[/code2]
    Note: that we'll move the parameters sent by the client into a a separate json object "Data" for the final release.

    If you have a look at the GetGameList code you'll see we send back a json object "Data":

    [code2=javascript]{
    "ResultCode": 0,
    "Data": {
    "MyRoom1": {
    "ActorNr": 1,
    "Properties": {
    "lobby4Key": "lobby4Val",
    "lobby3Key": "lobby3Val"
    }
    }
    }
    }[/code2]

    In the client you'll get the response like this

    [code2=csharp]public override void OnOperationResponse(OperationResponse operationResponse)
    ...
    switch (operationResponse.OperationCode)
    {
    ...
    case OperationCode.WebRpc:

    if (operationResponse.ReturnCode != 0)
    {
    DebugReturn(DebugLevel.ERROR, "WebRpc failed. Response: " + operationResponse.ToStringFull());
    }
    else
    {
    WebRpcResponse webResponse = new WebRpcResponse(operationResponse);
    this.OnWebRpcResponse(webResponse);
    }
    ...
    public void OnWebRpcResponse(WebRpcResponse webResponse)
    {
    if (webResponse.ReturnCode != 0)
    {
    DebugReturn(
    DebugLevel.ERROR,
    "WebRpc '" + webResponse.Name + "' failed. Error: " + webResponse.ReturnCode + " Message: " + webResponse.DebugMessage);
    return;
    }

    switch (webResponse.Name)
    {
    case "GetGameList":
    this.savedGamesList = new List<SavedGameInfo>();

    var data = webResponse.Parameters;
    if (data != null)
    {
    foreach (var item in data)
    {
    var gameInfo = new SavedGameInfo { Name = item.Key, ActorNr = -1, Properties = new Dictionary<string, object>() };
    var listItem = item.Value as Dictionary<string, object>;
    if (listItem != null)
    {
    gameInfo.ActorNr = (int)listItem["ActorNr"];
    if (listItem.ContainsKey("Properties")) gameInfo.Properties = (Dictionary<string, object>)listItem["Properties"];
    }
    this.savedGamesList.Add(gameInfo);
    }
    }

    this.ListSavedGamesToConsole();
    break;
    }
    }[/code2]

    -Philip