What do I do when MasterClient goes to sleep?

Options
Arm
Arm
Many of the RPC calls in my game are done in a two-step process:
  • The client send a message to the master client
  • The master client decides if the message had a valid impact in the game, and sends it out to all clients
This works nicely. However, if the device that is running the master client is put to sleep (say, by the user pushing the power button on it), play continues, the master client isn't switched, but any message that needed confirmation by the master goes unconfirmed.

(In my FPS game, this means that you can no longer shoot and kill other players! Oops.)

What can I do about this?

I imagine I could disconnect the master client in OnApplicationPause, but, is there anything cleaner than that? Could I, say, hand of MasterClient responsibilities so that a person could take a phone call and then rejoin the game?

Comments

  • The master client decides if the message had a valid impact in the game, and sends it out to all clients

    Why? Why are you giving the master client this power? It seems you're trying for a authoritative server architecture where it's not applicable.

    Note you're also introducing a little bit of lag here. Client -> Master -> All Clients, there's a network hop that shouldn't be necessary, it could just be Client -> All Clients.

    If the Master Client went to sleep, that should be his own problem, particularly in an FPS!! MasterClient switch should be transparent for most things, save perhaps a victory condition check or changing levels, obviously. But then it should be fine to wait for the sleeping Master to disconnect also.

    The only way I see it to not force a disconnect OnAppPause here is to let go of this validation on the MasterClient, but I have no idea how feasible that would be in your scenario because I don't know why it's there in the first place. :)
  • Arm
    Options
    Hi BlackLotus.

    You have the right of it. For things that are important in my game (such as deciding if another player is going to die, or for ensuring that certain things happen in a consistent order), I've made the master client authoritative. I realize it introduces some lag, but it is small enough that players don't feel it most of the time (providing that the master client is actively running the game).

    I suppose some of this could be reworked, but it does work, and it makes it harder to cheat.


    I've added code like this to address the problem. It doesn't make for a great experience for the person who switches from the game, but makes for a better experience for everyone else:
    	// They have paused the game - a phone call, pushing power, etc.
    	void OnApplicationPause(bool paused)
    	{
    		if (paused) 
    		{
    			PhotonNetwork.LeaveRoom();
    			// PhotonNetwork.Disconnect();	// overkill
    			PhotonNetwork.networkingPeer.SendOutgoingCommands();
    			Application.LoadLevel("RootMenu");
    		} 
    		else 
    		{
    			// Note: this is called in the editor when you start the game scene by itself!
    		}
    	}
    
  • vadim
    Options
    if the device that is running the master client is put to sleep (say, by the user pushing the power button on it), play continues, the master client isn't switched
    You mean that master client is still connected but does not response?
    Can you disconnect it explicitly when going to sleep to let Photon switch the master?
  • Arm
    Options
    vadim wrote:
    You mean that master client is still connected but does not response?

    That's right.

    I conclude this because:
    • the other clients did not get a disconnect message
    • no other client got the message to become the master client
    • if a client sends a message to the master client so that it can authoritatively determine what happens, the expected response never happens (unless the master client wakes up again, in which case it'll respond to pending messages.)
    vadim wrote:
    Can you disconnect it explicitly when going to sleep to let Photon switch the master?

    That is the solution I've come to (and posted code showing how I did it). [I think if I dive in a figure out how to make it automatically reconnect to the same game and room when the users unpauses, that it'd be an acceptable solution.]
  • vadim
    Options
    Saving room name and joining it by that name when unpaused is the way to do so. But you get in the room as new player of course.
  • dontonka
    Options
    Saving room name and joining it by that name when unpaused is the way to do so. But you get in the room as new player of course.
    Make sense but what if meanwhile another player has joined the room and the room has already reach his maximum # of player when you try to join back, or you cannot join it for some reasons? You need also to handle those cases.

    Don T.
  • vadim
    Options
    Setting room.isVisible = false would prevent other players from seeing it and therefore joining.
    You can set it at some point in game when all required players are joined and ready to start.