Having troubles handling pre-game room disconnections with TTL (to reconnect in-game)

Options
We need to either kick an inactive person, or change TTL before we change from pre-game to in-game.

Our situation is this:
* We start in a pre-game lobby to gather players in a room with 12 min TTL with in-game reconnections in-mind
* When a player is disconnected in a pre-game room, they "linger" for 12 mins.

So we had 2 ideas to resolve this:
* Simply kick them on activity changed callback ONLY while in pre-game. Disconnected in pre-game? Bye. However, you can't kick inactive players, for some reason (why?)

* You can set tons of room options after created, so start with 0 TTL and change the TTL to 12 mins just before the game. However, it seems we can't change TTL after the room is created (why?)

Suddenly, all ideas become complicated no matter what we do past here. This leads to some questions:

1. How come we can't kick an inactive player? This makes sense during pre-game "staging".
2. Why can't we change the room TTL post-creation?
3. Any alternatives or recommendations?

The "last resort" workaround sucks:
* We have max 16 players. Instead, we allow max 31 players.
* We'd have to change all UI to reflect a # of inactive players.
* Upon activity change, we'd have to hide the UI as if they actually disconnected (show 1 less player, remove their name from the playerlist), even though they are still "there", lingering.
* If the player queues up for a game normally (randomly), we'd have to check somehow upon failure to join if it was because you were unable to REJOIN. Then rejoin instead of join (otherwise the player will create a room since he can't join the same room he's inactive inside).
* In-game, we'll need to initialize checking based on inactive players and handle awkwardness of a player over our limit that "rejoins".

Overall ,it's super awkward, all because we can't kick an inactive player or change the player TTL :pensive:

Comments

  • Tobias
    Options
    Currently, you can set the PlayerTTL (or EmptyRoomTTL) only while a room gets created.

    However:
    We understand your usecase and think it's a good feature to have, so we plan to implement it soon.
    The respective task has a link to this post, so we might give you a heads up in the coming weeks. Hopefully that's OK, timing-wise.

    One crude workaround would be to make up a room name, share it and make everyone JoinOrCreate() it with fitting PlayerTTL set. But that's not great.

    If I may ask for that: Please consolidate your posts on this topic. One thread for this topic is enough ;)

  • xblade724
    xblade724
    edited May 2017
    Options
    Although it'll be awesome when you make it (woot!), we don't have a few weeks :( we went "too deep" into this reconnection code not even considering that I couldn't change TTL post-creation, so we're on the workaround.

    For this, we had to set the official max players to 128. Then we have a const for the "true" max players (16). That is, 16 ACTIVE players.

    We ended up joining the lobby and made our own query for the "best match" based on the sorted result from lobby room list player counts. Now that we have the room info before we join, we can:

    1. Verify the room doesnt match with a cached "old room" they have have disconnected from. If so, rejoin() instead of join if it's the best match.
    2. We can also check if they are in-game via custom props. Here is where I'm stuck. The room I obtained from the lobby does not seem to return custom room properties. (EDIT: Fixed! Maybe! Found the special str[] prop needed for lobby display)

    Overall, it's been .... stressful ;) but it should work as soon as I figure out why the custom room props seem to be returning null in the lobby.

    As for consolidating -- np, let's stick to this thread. Some of the other topics were scattered ideas leading up to this post that's more concrete.

    PS -- How come hashtables are used for custom props instead of dictionaries? Mostly curious
  • Tobias
    Options
    Yes, with the "props listed in lobby" you should be able to get selected props as room info.
    With all the rooms being used, make sure to close those you don't need anymore (or make them visible = false).

    Hashtables for properties: On the server, we allow byte keys as well. Those are props Photon uses and the byte keys avoid clashes with custom keys. So Dictionary was not an option anyways.
  • xblade724
    xblade724
    edited June 2017
    Options
    Thanks for the timely response, this helps.

    Heads up, I posted a new question with your call in mind to consolidate, but made a judgment call that it was outside the scope of OP so posted as new topic, only partially being related to reconnection.
  • xblade724
    xblade724
    edited October 2017
    Options
    Tobias said:

    Currently, you can set the PlayerTTL (or EmptyRoomTTL) only while a room gets created.

    However:
    We understand your usecase and think it's a good feature to have, so we plan to implement it soon.
    The respective task has a link to this post, so we might give you a heads up in the coming weeks. Hopefully that's OK, timing-wise.

    Following up on this @Tobias - did you ever work this in?
  • JohnTube
    JohnTube ✭✭✭✭✭
    Options
    Hi @xblade724,

    Changing PlayerTTL and EmptyRoomTTL post room creation should be available on Photon Cloud now.
    You should call OpSetProperties with Hashtable that has PlayerTTL and EmptyRoomTTL GameProperty codes (byte) as keys.
  • xblade724
    xblade724
    edited October 2017
    Options
    JohnTube said:

    Hi @xblade724,

    Changing PlayerTTL and EmptyRoomTTL post room creation should be available on Photon Cloud now

    Awesome, but this a PUN thread -- how about PUN? :)
  • JohnTube
    JohnTube ✭✭✭✭✭
    edited October 2017
    Options
    Hi @xblade724,

    It's not supported out of the box yet.
    Try this code (not tested yet):
    using Hashtable = ExitGames.Client.Photon.Hashtable;
    
    // [...]
    
    public static bool UpdateTTLs(int playerTTL, int emptyRoomTTL)
        {
            Hashtable hash = new Hashtable(2);
            hash.Add((byte)246, playerTTL);
            hash.Add((byte)245, emptyRoomTTL);
            return PhotonNetwork.networkingPeer.OpSetPropertiesOfRoom(hash);
        }
  • JohnTube
    JohnTube ✭✭✭✭✭
    Options
    Hi @xblade724,

    Did you test this yet?
  • xblade724
    xblade724
    edited October 2017
    Options
    JohnTube said:

    Hi @xblade724,

    Did you test this yet?

    Ah, not yet. I took a look and remember that weird workaround we said we'd have to do in OP? We pretty much changed our entire architecture to support the lobby (we originally didn't even use the lobby), among some other TTL workarounds (we needed them to timeout in the lobby FAST, but timeout in the game SLOW) -- in the end, I looked back and I can't find a good spot to implement this, so I can no longer test it.

    Perhaps next game. However, I still am curious if it works if someone else wants to give it a shot and respond here.
  • querwilly
    Options
    JohnTube said:

    Hi @xblade724,

    It's not supported out of the box yet.
    Try this code (not tested yet):

    using Hashtable = ExitGames.Client.Photon.Hashtable;
    
    // [...]
    
    public static bool UpdateTTLs(int playerTTL, int emptyRoomTTL)
        {
            Hashtable hash = new Hashtable(2);
            hash.Add(ParameterCode.PlayerTTL, playerTTL);
            hash.Add(ParameterCode.EmptyRoomTTL, emptyRoomTTL);
            return PhotonNetwork.networkingPeer.OpSetPropertiesOfRoom(hash);
        }
    not working
  • JohnTube
    JohnTube ✭✭✭✭✭
    Options
    Hi @querwilly,

    My bad! Check now the updated snippet with correct Well Known Room Property keys values.
    I tested it and it works.
    using Hashtable = ExitGames.Client.Photon.Hashtable;
    
    // [...]
    
    public static bool UpdateTTLs(int playerTTL, int emptyRoomTTL)
        {
            Hashtable hash = new Hashtable(2);
            hash.Add((byte)246, playerTTL);
            hash.Add((byte)245, emptyRoomTTL);
            return PhotonNetwork.networkingPeer.OpSetPropertiesOfRoom(hash);
        }
  • xblade724
    xblade724
    edited November 2017
    Options
    public static bool UpdatePlayerTTL(int playerTTL)
    {
        ExitGames.Client.Photon.Hashtable hash = new ExitGames.Client.Photon.Hashtable(1);
        hash.Add((byte)246, playerTTL);
    
        bool isDone = PhotonNetwork.networkingPeer.OpSetPropertiesOfRoom(hash);
        return isDone;
    }
    Heads up, this does not work. In a simple repro setup:

    1. Create room with initial playerTTL to 0 in RoomOptions
    2. on OnCreatedRoom(), call UpdatePlayerTTL(720000); // 12 min TTL
    3. Notice that whenever a player joins a room, then leaves, he instantly leaves. The TTL is still 0. Try setting a breakpoint at OnPhotonPlayerActivityChanged(), docs reading "This will be called ONLY if PlayerTtl is greater than 0." and it'll never be triggered.

    Screencast: https://drive.google.com/open?id=1k7PlAkUdxBk60wVQk8QwRc-OIxh705BO

    You're sure 246 is for playerTTL, and currently works with PUN? It's at least not roomTTL (I tried rejoining an empty room)

    EDIT: I was given some diag tools to mess around with -- curious, though -- if anyone else tries this and it either works or doesn't work, let me know :)
  • JohnTube
    JohnTube ✭✭✭✭✭
    edited November 2017
    Options
    Hi @xblade724,

    In step 1, try creating rooms with RoomOptions.PlayerTtl = 1 (which is the lowest value possible and different than 0, zero is the default, one means 1 millisecond).
    The thing is currently the rejoin by UserId does not work if the room is created with PlayerTtl = 0.

    Let me know if this fixes the issue you have.
  • xblade724
    Options
    JohnTube said:

    Hi @xblade724,

    In step 1, try creating rooms with RoomOptions.PlayerTtl = 1 (which is the lowest value possible and different than 0, zero is the default, one means 1 millisecond).
    The thing is currently the rejoin by UserId does not work if the room is created with PlayerTtl = 0.

    Let me know if this fixes the issue you have.

    Ah, we had this idea the other day -- tested and still didn't work :(

    We're okay now -- we ran out of time to wait on TTL fixes (customers are getting upset that we took away reconnection), so we worked around it by setting our system to allow users to just join() via a specific sql filter that lets them know it's ok to "rejoin" (regular join). Then just join() instead of rejoin().

    However, since you guys are so close, it would still be cool to see an actual fix in the future since we gave up using TTL features for our workaround. Maybe we can swap back later.