How to use DirectMessage ?

Options
benjaml
benjaml
edited September 2019 in Native
Hello,

I'm trying to use the DirectMessage feature, but I don't succeed in it as I think it's missing example in the documentation to understand well the feature.

So here is how I send a directMessage (this part seems right but we never know)

ExitGames::Photon::OperationRequestParameters parameters; parameters.put(1, ExitGames::Common::ValueObject<ExitGames::Common::JString>(L"Money")); parameters.put(2, ExitGames::Common::ValueObject<int>(200)); outputListener->writeLine(L"Sending add 200 money request"); auto roomMaster = getCurrentRoomMaster(); ExitGames::Common::JVector<int> targetPlayers; targetPlayers.addElement(roomMaster->getNumber()); if (!loadBalancingClient.sendDirect<ExitGames::Photon::OperationRequestParameters>(parameters, targetPlayers)); { outputListener->writeLine(ExitGames::Common::JString(L"failed to send the custom request")); }

Then there is the onDirectMessage function that I don't understand how should I use the msg parameter.

How should I read the const ExitGames::Common::Object& msg parameter ?

Thanks in advance

Comments

  • Kaiserludi
    Kaiserludi admin
    edited September 2019
    Options
    Hi @benjaml.

    I think it's missing example in the documentation to understand well the feature
    demo_loadBalancing inside the Client SDK contains example code for using Client::sendDirect().


    (this part seems right but we never know)

    Well, technically you can do it that way, as OperationRequestParameters is just a typedef for a Dictionary< nByte, Object>, but I would recommend against using OperationRequestParameters with sendDirect(), as its misleading.
    The purpose of <code class="CodeInline">OperationRequestParameters is to use it when implementing an an operation request, either for a custom operation (as a user of the client) or a builtin operation (if you would be part of the team that develops Photon). An "operation" is a term that is strongly related to communicating with the Photon server: a client sends an operation request to the server and that request might trigger an operation response that is sent back from the server to that client or an event that is sent from the server to certain clients in the same room (which may, but does not have to, include the sender of the request) - what exactly happens depends on the operation in question.
    In Photon terms operations have nothing at all to do with sending direct p2p messages directly between clients, but always involve a server.

    sendDirect() supports the same data types for its payloads like opRaiseEvent(). You can look up the supported types in the C++ Client API reference under "Common-cpp" -> "Table of datatypes" (https://doc-api.photonengine.com/en/cpp/current/html/a00038.html).

    So in a very simple example you could very well just pass '200" to it like this:
    loadBalancingClient.sendDirect(200, targetPlayers)

    Obviously whenever you want to send multiple variables at once, then you have to put them in some kind of container like an array, an Object-array, a Hashtable, a Dictionary or even a CustumType or you could serialize them into a byte-array yourself and pass that byte-array to sendDirect() . The best option depends on the specific usage. (the order of increasing flexibility (that comes with increasing overhead) is: array, Object-array, Dictionary, Hashtable - use a container as far left in the list as you can and as far right in the list as you have to).


    How should I read the const ExitGames::Common::Object& msg parameter ?

    In your example of sending a Dictionary< nByte, Object> the simplest way to access it on the receiving side is
    Dictionary< nByte, Object> dic = ValueObject< Dictionary< nByte, Object> >(msg).getDataCopy();
  • benjaml
    Options
    I'm trying to send an Object array but I can't make it work. at first I've tried to send JVector but it seems to not be authorized, then I've seen on the supported types that I should rather send Object* but I can't make it work do you have an example ?
  • benjaml
    benjaml
    edited September 2019
    Options
    I have a ExitGames::Common::JVector<ExitGames::Common::Object> messageData that I want to send with the following version of sendDirect
    template< typename Ftype > bool sendDirect(const Ftype & parameters, const Common::JVector<int> & targetPlayers = Common::JVector<int>(), bool fallbackRelay = false)

    here is how I use it :
    loadBalancingClient.sendDirect<ExitGames::Common::Object*>(messageData.getCArray());

    But it does not compile as it does not find an instance of the function that matches the parameters.

    Also just to be sure, JVector<int>() as targetPlayers means that it will send to everyone ?
  • benjaml
    benjaml
    edited September 2019
    Options
    I have a JVector<Object> that I want to send with sendDirect, at first I've tried to send the JVector directly but I found that I cannot and should rather send an Object* so now I'm trying to use this version of sendDirect template< typename Ftype > bool sendDirect(const Ftype & parameters, const Common::JVector<int> & targetPlayers = Common::JVector<int>(), bool fallbackRelay = false)

    and now I have loadBalancingClient.sendDirect<ExitGames::Common::Object*>(messageData.getCArray());

    But it does not compile as it says that it cannot find an instance of sendDirect matching those argument

    I also want to make sure that when using an empty JVector for the targetPlayers argument, it does indeed send to everyone.
  • benjaml
    Options
    I have a JVector< Object> that I want to send with sendDirect, at first I've tried to send the JVector directly but I found that I cannot and should rather send an Object* so now I'm trying to use this version of sendDirect template< typename Ftype > bool sendDirect(const Ftype & parameters, const Common::JVector & targetPlayers = Common::JVector(), bool fallbackRelay = false)

    and now I have loadBalancingClient.sendDirect< Object*>(messageData.getCArray());

    But it does not compile as it says that it cannot find an instance of sendDirect matching those argument

    I also want to make sure that when using an empty JVector for the targetPlayers argument, it does indeed send to everyone.
  • Kaiserludi
    Kaiserludi admin
    edited September 2019
    Options
    Hi @benjaml.

    When you want to send an array, then you need to call the array-overload of sendDirect(), which accepts an additional size parameter:
    loadBalancingClient.sendDirect(messageData.getCArray(), static_cast< short>(messageData.getSize()));

    I also want to make sure that when using an empty JVector for the targetPlayers argument, it does indeed send to everyone.

    Not to everyone, but to everyone ELSE inside the room. The client that sends the message is not part of the target players if you pass an empty JVector for the 'targetPlayers'.

    Note that only if you pass 'true' for 'fallbackRelay' the messages are actually sent to all the target players, including those to which no p2p connection exists. Otherwise they are only sent to those target players, to which NAT punch-through has been successful and a direct p2p connection could actually be established.
  • benjaml
    benjaml
    edited September 2019
    Options
    It seems like we cannot send a directMessage to ourself, what is the way to do it if we want to keep the same workflow, call onDirectMessage directly ?
  • Kaiserludi
    Options
    Hi @benjaml.

    You can send a message to yourself through sendDirect() by explicitly specifying yourself as target player / adding yourself to the target players and setting 'fallbackRelay' to 'true'.
    Such messages to yourself will always be sent through the relay and never successfully get sent if you attempt to send them with 'fallbackRelay' set to 'false' at the clients don't establish p2p connections to the local client, but only to remote clients.