Can I just send byte arrays using opRaiseEvent?

So for the past 2 days, I've been trying to get a byte array to be sent to all users. But during my work, it kept giving me an error stating there was something wrong with the data.

I read up on needing to declare CustomType and wasn't sure if this is why it wasn't working. This is the code I used to try and send a byte array:

if (client != nullptr)
	{
		uint8 data[35];
		for (uint8 i = 0; i < 35; i++)
		{
			data[i] = _data.Data[i];
		}
		return client->opRaiseEvent(_data.Reliable, data, 35, _data.EventCode, RaiseEventOptions().setReceiverGroup(ExitGames::Lite::ReceiverGroup::OTHERS));
	}
	return false;

Best Answer

  • Kaiserludi
    Kaiserludi admin
    Accepted Answer

    Hi @StereoJunkie.

    In the line

    nByte* pContent = ExitGames::Common::ValueObject<nByte*>(eventContent).getDataCopy();
    

    you tell the compiler that eventContent is a ValueObject that holds an array of nByte as its payload.

    However in the line

    float contentElementCount = *ExitGames::Common::ValueObject<float>(eventContent).getSizes();
    

    you tell it that it is is a ValueObject that holds a float as its payload.


    As you say that pContent can successfully be retrieved, that means that it is indeed holding an array of nByte.

    That means that the second line is incorrect and should instead look like this:

    float contentElementCount = *ExitGames::Common::ValueObject<nByte*>(eventContent).getSizes();
    

    You can compare the return value of eventContent.getType() with the constants in Common::TypeCode to see the type of the payload. Attempting to access the Object as a ValueObject with a different payload type than the one that getType() returns will result in an empty ValueObject instance.


    You can print the return value of eventContent.toString(true) to the console or to a text file to inspect the payload while debugging. This can often help tracking down such issues.

Answers

  • Hi @StereoJunkie.


    byte arrays are among the types for which there is out of the box support built-in, so you don't need to define a custom type for them.


    What is the error message that you get from the compiler?

    Your code snippet works just fine for me.

  • This is the error i keep getting:

    ERROR   Client.cpp                     ExitGames::LoadBalancing::Client::onOperationResponse()      1604  OperationResponse - operationCode: 253, returnCode: -2 (Unknown operation code)
    
  • The weird part is that the opRaiseEvent returns true. But no event is received.

  • Hi @StereoJunkie.


    The weird part is that the opRaiseEvent returns true. But no event is received.

    This isn't really weird, but expected, intended and accordingly documented behavior. It returns false, when the client can already determine that the raiseEvent operation will fail, like when you provide invalid parameters or call the operation in a disconnected state or outside of a room. In such cases, the client returns false and does not send the operation.


    It returns true, when the client successfully queues the operation for sending.

    In case that the operation fails on the server, the client receives an according operationResponse with an error message. As due to latency this takes some time, opRaiseEvent() can't provide this info in its return value without blocking the calling thread for up to potentially multiple seconds. That's why it doesn't wait for this information before returning.


    (Unknown operation code)

    This means that the server does not know the raise event operation. Hence it does not have anything to do with the content of your raise event. It would happen just as well if you would send something else than a byte-array.


    This error can have 2 potential reasons:

    a) You have not waited for the callback that you have actually entered the room before you call opRaiseEvent(). In this case the operation might already get send out while the client is still in the process of switching from the region master server to the game server on which the room is hosted. opRaiseEvent is only available inside of rooms and hence the master server doesn't know this operation.

    b) You are using a Chat appID with a Photon Realtime Client and hence the Photon nameserver has connected you to a Photon Chat fronted instead of a Photon Realtime master server. The Chat servers don't know Realtime operations. However in this case the operation to create or join a room should already have failed as well. So as that does not seem the case for you, your issue is probably related to a) and not to b).

  • It seems that the issue was a lack of rooms. The sending works now but I have an issue with decoding the eventContent.

    I'm most likely doing this wrong because I had to adapt the hashtable tutorial for this.

    The pContent is correct (used breakpoints to see it),

    The contentElementCount doesn't work which causes the transition to TArray<uint8> to fail.

    nByte* pContent = ExitGames::Common::ValueObject<nByte*>(eventContent).getDataCopy();
    float contentElementCount = *ExitGames::Common::ValueObject<float>(eventContent).getSizes();
    
    TArray<uint8> ue_received;
    ue_received.Append(&pContent[0], contentElementCount);
    
    networkManager->UpdateHeartbeat(ue_received);
    
    ExitGames::Common::MemoryManagement::deallocateArray(pContent);
    
  • Kaiserludi
    Kaiserludi admin
    Accepted Answer

    Hi @StereoJunkie.

    In the line

    nByte* pContent = ExitGames::Common::ValueObject<nByte*>(eventContent).getDataCopy();
    

    you tell the compiler that eventContent is a ValueObject that holds an array of nByte as its payload.

    However in the line

    float contentElementCount = *ExitGames::Common::ValueObject<float>(eventContent).getSizes();
    

    you tell it that it is is a ValueObject that holds a float as its payload.


    As you say that pContent can successfully be retrieved, that means that it is indeed holding an array of nByte.

    That means that the second line is incorrect and should instead look like this:

    float contentElementCount = *ExitGames::Common::ValueObject<nByte*>(eventContent).getSizes();
    

    You can compare the return value of eventContent.getType() with the constants in Common::TypeCode to see the type of the payload. Attempting to access the Object as a ValueObject with a different payload type than the one that getType() returns will result in an empty ValueObject instance.


    You can print the return value of eventContent.toString(true) to the console or to a text file to inspect the payload while debugging. This can often help tracking down such issues.