LoadBalancingDemo 4.1.3 rejoin feature doesn't work

Options
Hi there,

I've just upgraded to photon 4.1.3 with c++ SDK. The rejoining room feature in the previous version 4.0.1 worked well with my project but this feature in 4.1.3 version doesn't work. I try to test this feature with LoadBalancingDemo but it also doesn't work.
To test rejoining room feature in LoadBalancingDemo I made some changes as following:
File: RoomOption.h (change default playerTtl and emptyRoomTtl)
RoomOptions(bool isVisible=true, bool isOpen=true, nByte maxPlayers=0, const Common::Hashtable& customRoomProperties=Common::Hashtable(), const Common::JVector<Common::JString>& propsListedInLobby=Common::JVector<Common::JString>(), const Common::JString& lobbyName=Common::JString(), nByte lobbyType=LobbyType::DEFAULT, int playerTtl=60000, int emptyRoomTtl=60000);

File: NetworkLogic.cpp (remove false to turn on rejoin feature)
if(mLastJoinedRoom.length()) { mpOutputListener->writeLine(ExitGames::Common::JString(L"rejoining ") + mLastJoinedRoom + " with actorNr = " + mLastPlayerNr + "..."); mLoadBalancingClient.opJoinRoom(mLastJoinedRoom, mLastPlayerNr); }
Here is the return error:
ERROR NetworkLogic.cpp joinRoomReturn() line: 361 - Game does not exists


Help me please. My project is in production with SDK 4.1.3, I need a quick update for it.

Comments

  • Kaiserludi
    Kaiserludi admin
    edited July 2016
    Options
    Hi @guipong.

    This is caused by a bug in the Photon C++ Client SDK, that got introduced with v4.0.5.0.

    To fix it, please change the line
    mLastJoinType = JoinType::JOIN_ROOM;
    at the end of the implementation of Client::opJoinRoom() in yourPhotonSDKRootFolder\LoadBalancing-cpp\src\Client.cpp to
    if(mState != PeerStates::Joining)
    	mLastJoinType = JoinType::JOIN_ROOM;
    and afterwards rebuild LoadBalancing-cpp.
  • guipong
    guipong
    edited July 2016
    Options
    Hi @Kaiserludi admin,

    It still does not work with your modification, demo code still goes into the line
    mLastJoinType = JoinType::JOIN_ROOM;
    However, if I comment this line, it works with demo. Unfortunately, there are many cases it doesn't work with my project if I comment this line.
  • Kaiserludi
    Options
    Hi @guipong.

    I can't reproduce it with demo_loadBalancing anymore after doing that change.
    What's the callstack that you get when demo code still goes into that line?
  • guipong
    Options
    In order to test rejoining room, I create game and then leave game and then join game.
    The line mLastJoinType = JoinType::JOIN_ROOM; was called directly from rejoin code line in NetworkLogic::run mLoadBalancingClient.opJoinRoom(mLastJoinedRoom, mLastPlayerNr);
    Stack:
    #0 0x000000010bb28cf9 in ExitGames::LoadBalancing::Client::opJoinRoom(ExitGames::Common::JString const&, int, int) at /Users/QuangDong/Downloads/Source/Photon-iOS-Sdk_v4-1-3-0/LoadBalancing-cpp/src/Client.cpp:605
    #1 0x000000010bae7226 in NetworkLogic::run() at /Users/QuangDong/Downloads/Source/Photon-iOS-Sdk_v4-1-3-0/Demos/demo_loadBalancing/src/NetworkLogic.cpp:178


    The value of mState is PeerStates::JoinedLobby that why it still run into that line.
  • Kaiserludi
    Options
    Hi @guipong.

    That is actually totally fine and behaving like intended. The point of adding if(mState != PeerStates::Joining) there, instead of outcommenting the line completely is, that that line needs to get executed when the application code calls opJoinRoom(), but should not get executed when LoadBalancing::Client is calling that function internally.

    Background info:
    When the app calls that line, then the client sends a joinRoom operation to the master server, waits for the master to respond with the address of the game server on which this room resides, disconnects from the master and reconnects to that game server and then calls the function a second time itself to send a joinRoom operation the game server. So in the first call mLastJoinType gets set so that the client knows how to continue after connecting to the game server (should it create or join a room?).

    Now the joinRandomRoom function is only available on the master server. The master server, which knows all available rooms on all game servers that are connected to it, chooses a room and sends the room name and the address of the game server that hosts this room back to the client. Now the clients after connecting to that game server just does not send a joinRandomRoom operation (which is unknown to the gameserver), but the joinRoom operation with the room name that it received from the master to the gameserver. Now when that happens, the client is in the Joining state and at that moment it executes opJoinRoom() internally, although your applications call was to opJoinRandomRoom(). So this internal call did override the last join type that your call set before with a wrong value, which lead to the client calling the wrong callback (it called Listener::joinRoomReturn() when it should call Listener::joinRandomRoomReturn()). This confused the demo code, which prevented the demo from rejoining. So with the if-check added the client now does not wrongly set the join type anymore for internal call and therefor calls the correct callback, so that the demo can happily rejoin again.

    If instead of that if-check you would outcomment the line completely, then the state would also not be set anymore for calls that come from your app, which would break the functionality of joining rooms by name.
  • guipong
    guipong
    edited July 2016
    Options
    Hi @Kaiserludi ,
    Thank you for all the interesting information.
    Could you make an update for Client C++ SDK? Or could you send me your LoadBalancing demo C++ source code?
    Because it still doesn't work with mine.
    My email: guipong@gmail.com
  • Kaiserludi
    Options
    Hi @guipong.

    I have not done any special modifications to demo_loadBalancing, but just set a valid appID and removed the 'false && ' in if(false && mLastJoinedRoom.length()) to turn on rejoining.
  • guipong
    Options
    Hi @Kaiserludi,

    I see the case that the demo works when calling leaving room with willComeBack = true
    mLoadBalancingClient.opLeaveRoom(true)
    It will disconnect with game server
    if(willComeBack) { mState = PeerStates::DisconnectingFromGameserver; mPeer.disconnect(); } else { if(!mPeer.opLeaveRoom()) return false; mState = PeerStates::Leaving; }

    However what I want is that I can rejoin a room with the same actor number after losing internet connection or calling Client::disconnect(void) { mState = PeerStates::Disconnecting; mPeer.disconnect(); } which can be done in old version.
  • guipong
    guipong
    edited July 2016
    Options
    With further debug, I notice that user id has been reset with new connection to master server if I don't set it in the authentication values for connection:
    Client::connect(AuthenticationValues authenticationValues, const Common::JString& username, const JString& serverAddress, nByte serverType) .
    User id has been reset:
    mAuthenticationValues.setUserID(ValueObject<JString>(operationResponse.getParameterForCode(ParameterCode::USER_ID)).getDataCopy()); EGLOG(DebugLevel::INFO, L"Setting userID sent by server: " + mAuthenticationValues.getUserID());
    Therefore, after calling Client::disconnect() I cannot rejoin to the room. My problem was solved with the init of user id for authenticationValues.
    Thank you!
  • Kaiserludi
    Options
    Hi @guipong.

    Great news that you found it.

    Yes, if you don't set any user id yourself, then the server will set it to a random guid for you and if you then don't store that ID to set it yourself on the next connect, then the server will assign you a new and different guid, so your client then identifies as a different user and can therefore not rejoin any rooms that it was in with it's previous user id.