Friends and channels questions

Hi, I'm adding the Photon Chat API to my Shiva engine plugin, and I'm wondering how these friends and channels stuff works actually.
When you connect to the chat server (region -> nameserver -> front-end server) you use an username (userid), questions:
1) how do i assert or check that username is unique?
2) if I add a friend, where is the friendlist saved?
3) is this friendlist from (2) a forever list or just for this chat session (for that username)?
4) what happen if i disconnect or i change the username?
5) why when i subscribe to a channel then this channel does not appears (not in another client nor in the same client who subscribe) using the get public list function?
6) users from photoncloud server and photonchat servers are different, the find friends function uses a list of friends, that implies i have to save it somewhere from the first time a client start the game and each time it adds or remove a friend and keep it synched with all the platforms this user may use, is that a proper method to do this stuff?

Comments

  • Hi @juaxix.

    1.
    Those functions expect you to pass in user IDs not usernames and you must make sure that your clients use unique IDs as user IDs. It is not necessary that the user IDs are equivalent to the displayed user names that the users can choose themselves and that are displayed to them. For example you could use something like GETTIMEMS()+rand() as an ID that is likely to be unique (two clients would need to generate the exact same random value at the exact same millisecond point in time for both IDs to be the same). If you are afraid this might not be unique enough, please read up about GUIDs and generate one. You could also use something like the users email-address or facebook-userid.

    2.
    The friendlist gets stored in the servers temporary storage.

    3.
    It's just for that chat session. You need to store it elsewhere, retrieve it from there and provide it to Photon Chat after every reconnect.

    4.
    You need to store your user ID somewhere, so you can retrieve it and reuse it after a restart of the app or a reconnect. Keep in mind that storing it locally inside an app means it might get lost of the user deletes the app, so you might want to store it on an external service.
    Do NOT change the user ID, but only let the user change the visible display name. The user ID should always stay the same for the same user.

    5.
    opSubscribe() sends a request to the server to subscribe the client to the specified channels. It takes a moment for the server to respond to that request.

    6.
    This is the same for Realtime and Chat: You need to keep a synchronized storage for the friend lists somewhere else and supply the up to date friendlist to Photon with every new session. Photon is a networking or and online multiplayer engine, not a Social Gaming SDK. We usually recommend our partner playfab.com for these kinds of features.
  • Ok ,let me add some code to understand this better.
    This is the initialization of the chat connection inside of a Chat::Listener class method:

    void connect(){
    //create new chat client instance now:
    chatClient = new Chat::Client(*this, appID, appVersion, bUseTcp ? Photon::ConnectionProtocol::TCP : Photon::ConnectionProtocol::UDP);
    chatClient->setDebugOutputLevel(
    DEBUG_RELEASE(ExitGames::Common::DebugLevel::INFO, ExitGames::Common::DebugLevel::WARNINGS));
    ExitGames::Common::Base::setListener(this);
    ExitGames::Common::Base::setDebugOutputLevel(
    DEBUG_RELEASE(ExitGames::Common::DebugLevel::INFO, ExitGames::Common::DebugLevel::WARNINGS));
    //Set region
    chatClient->setRegion(region);
    //chatClient->setDebugOutputLevel(DEBUG_RELEASE(Common::DebugLevel::ALL, Common::DebugLevel::ALL));
    chatClient->setCrcEnabled(bUseCRC);
    //Connect
    Console::get().writeLine(L"Connecting to nameserver as user " + userID);
    Console::get().writeLine();
    chatClient->connect(Chat::AuthenticationValues().setUserID(userID + GETTIMEMS()+rand()));
    }

    Using this code, the PhotonChat will eventually get connected (onStateChange event will receive connected to chat name server and then to chat front-end server)


    1.
    Those functions expect you to pass in user IDs not usernames and you must make sure that your clients use unique IDs as user IDs. It is not necessary that the user IDs are equivalent to the displayed user names that the users can choose themselves and that are displayed to them. For example you could use something like GETTIMEMS()+rand() as an ID that is likely to be unique (two clients would need to generate the exact same random value at the exact same millisecond point in time for both IDs to be the same). If you are afraid this might not be unique enough, please read up about GUIDs and generate one. You could also use something like the users email-address or facebook-userid.

    ok, and this userid ,is this userID for only this connection? so are you saying that this userID must be saved for this device to use the same next connection time?


    2.
    The friendlist gets stored in the servers temporary storage.
    3.
    It's just for that chat session. You need to store it elsewhere, retrieve it from there and provide it to Photon Chat after every reconnect.

    Ok, so if I add a friend ,i would be able to see this friend in my friend list as long as either my userID as my friend userID don't change, right?


    4.
    You need to store your user ID somewhere, so you can retrieve it and reuse it after a restart of the app or a reconnect. Keep in mind that storing it locally inside an app means it might get lost of the user deletes the app, so you might want to store it on an external service.
    Do NOT change the user ID, but only let the user change the visible display name. The user ID should always stay the same for the same user.

    do you mean that the SDK will only save the userID because i could not find any display name.


    5.
    opSubscribe() sends a request to the server to subscribe the client to the specified channels. It takes a moment for the server to respond to that request.

    After the connected state received in onStateChange, i list all the channels using

    const Common::JVector& channels =
    chatClient->getPublicChannels();
    for (unsigned int i = 0; i < channels.getSize(); i++)
    {
    //...
    }

    but it will never find any channel, and i dont know why.
    How long should i wait before getting the list of channels with the new ones?


    6.
    This is the same for Realtime and Chat: You need to keep a synchronized storage for the friend lists somewhere else and supply the up to date friendlist to Photon with every new session. Photon is a networking or and online multiplayer engine, not a Social Gaming SDK. We usually recommend our partner playfab.com for these kinds of features.

    Ok then,thanks


  • Hi @juaxix.

    Please wait for connectReturn() to be called until considering the client connected. onStateChange() is intended for informational purposes, but not for actual code logic to rely on it.

    1.
    Yes, that is correct.

    2. && 3.
    You need to reset the friend list after each connect.

    4.
    It doesn't change either of them in persistent storage. You need to reset the userID after each connect. Display names are not a built-in feature of Photon, but just what you would display as the name of a user. You can transfer the information what the display name of a certain player should be by just sending it as a message to every channel to which the user subscribes to right after successfully subscribing to it.
    You can send anything as a message that is supported by Photons serialization, not just text, so you could for example send an initial message to a channel right after subscribing to it that contains a Dictionary with various key-value pairs that contain information about that player, for example the display name, the code of the color in which the user want's to be displayed, an enum value for the avatar that he has chosen, etc.

    5.
    getPublicChannels() returns the list of public channels that you have subscribed to after connecting, meaning the channels in which the user currently is in. Of course this list is empty right after connect before you have actually subscribed to any channel. There currently is no built-in support for listing all existing channels including the ones you have not subscribed to, yet.
    There is a potentially infinite amount of channels that could exist as there is no hard upper limit. So this works similar to IIRC: a client specifies a channel name it wants to subscribe to and if a channel with tha name already exists then it subscribes to the existing channel, otherwise a new channel gets created and if 2 clients subscribe to a public channel with the same name they subscribe to the same public channel and can see messages from each other that get sent to that channel.
    You can easily let your client UI just present a list of predefined (by you) channels to the end users and only let your users subscribe to these public channels instead of letting the users specify the channel names themselves, if you want to make it easier for your users to find channels that are already used by other players.
  • 1-3: ok, thanks
    4: I use serialization for other synch functions, ok.
    5: i can understand that, ok.
    6. ok.
    7.One more thing, if userId from PhotonCloud (Loadbalancing client) and PhotonChat are different, what is the Peer function for LoadBalancing client :
    https://doc-api.photonengine.com/en/cpp/current/html/a00054.html

    bool Peer::opFindFriends(const JString* friendsToFind, short numFriendsToFind)
    {
    if(!friendsToFind || !numFriendsToFind)
    return false;
    OperationRequestParameters op;
    op.put(ParameterCode::FIND_FRIENDS_REQUEST_LIST, ValueObject(friendsToFind, numFriendsToFind));

    return opCustom(OperationRequest(OperationCode::FIND_FRIENDS, op), true);
    }


    doing?, how can i add a photon cloud friend (not chat friend)?
    I was adding chat friends and then looking for them with the photoncloud loadbalancing client function just like this:
    inline bool FindFriends(const ExitGames::Common::JString* friends, short numElements)
    {
    return mLoadBalancingClient.opFindFriends(friends, numElements);
    }

    but then i realise that this is not listing any friend added with chat sdk, so,...what am i doing wrong?

    8. Ah, and how can i list all of my photon chat friends then?
  • Hi @juaxix.

    7.
    Photon Realtime/Server and Photon Chat are separate independent products that can be used on their own without the other one. Therefor they are independent from each other. This includes their respective friend list features. So adding a friend to the Chat friend list will not have any influence on the LoadBalancing friend list and vice versa.

    You can pass a list of friends that you got from an external source to opFindFriends() to ask the server for information who of those friends (users with the names specified in that list) is currently online.



    8.
    Photon Chat does not offer functionality for that. You need to provide the list of friends to Photon with opAddfriends() anyway, so you should already have a list of your friends available locally.
  • 7. Ok, so a friend is not added in any way to the photon cloud server, i think the name of the function is confusing because it is searching users not friends...

    8. Ok

    Thanks @kaiserudi
  • Just one more question, the loadbalancing client function opFindFriend uses PlayerName as parameter,and the chat client function addFriend uses userID's list, so, you can't add a photon user as friend using chat api because you can't know the userID from a player's room list, right (and if we could, the userIDs should be the same in both servers)?
  • Hi @juaxix.

    To be able to add an entry from one friend list also to the other one you must get to know the identity of that user in the other product. The simplest way to achieve this is to just don't allow your users to use different nicknames for Chat and Realtime for the same user account in your game, so that you can be sure that the user juaxix in Realtime is the user juaxix in Chat and vice versa.