Saturday, June 18, 2011

Foray into Photon - Part 11 - WaitingForConnect and Connected

In our last post, the Disconnected state really didn't do anything more than report errors. It isn't very helpful in terms of doing anything for us. This time we will be creating our Waiting for Connect which again doesn't do anything different from Disconnected except call Service in the OnUpdate and let us know when we are connected. So lets take a look at it:


using AegisBornCommon;
using ExitGames.Client.Photon;


public class WaitingForConnect : IGameState
{


    public static readonly IGameState Instance = new WaitingForConnect();


    public GameState State
    {
        get { return GameState.WaitingForConnect; }
    }


    public void OnEventReceive(Game gameLogic, AegisBornCommon.EventCode eventCode, System.Collections.Hashtable eventData)
    {
        gameLogic.OnUnexpectedEventReceive(eventCode, eventData);
    }


    public void OnOperationReturn(Game gameLogic, AegisBornCommon.OperationCode operationCode, int returnCode, System.Collections.Hashtable returnValues)
    {
        gameLogic.OnUnexpectedPhotonReturn(returnCode, operationCode, returnValues);
    }


    public void OnPeerStatusCallback(Game gameLogic, ExitGames.Client.Photon.StatusCode returnCode)
    {
        switch (returnCode)
        {
            case StatusCode.Connect:
                {
                    gameLogic.SetConnected();
                    break;
                }


            case StatusCode.Disconnect:
            case StatusCode.DisconnectByServer:
            case StatusCode.DisconnectByServerLogic:
            case StatusCode.DisconnectByServerUserLimit:
            case StatusCode.TimeoutDisconnect:
                {
                    gameLogic.SetDisconnected(returnCode);
                    break;
                }


            default:
                {
                    gameLogic.OnUnexpectedPhotonReturn((int)returnCode, OperationCode.Nil, null);
                    break;
                }
        }
    }


    public void OnUpdate(Game gameLogic)
    {
        gameLogic.Peer.Service();
    }


    public void SendOperation(Game gameLogic, AegisBornCommon.OperationCode operationCode, System.Collections.Hashtable parameter, bool sendReliable, byte channelId)
    {
    }
}

It uses 2 new functions we need to add to Game, SetConnected and SetDisconnected. These functions set the state of Game to Connected and Disconnected, respectively. Open up Game.cs and add them real quick:

    public void SetConnected()
    {
        _stateStrategy = Connected.Instance;
    }

    public void SetDisconnected(StatusCode returnCode)
    {
        _stateStrategy = Disconnected.Instance;
    }

Next we are going to add the last piece to begin our connect phase. To do this, go into Game.Initialize and add the following line before the Peer.Connect:

        _stateStrategy = WaitingForConnect.Instance;

Once this is done, Initialize will connect to the server. When the callback gets called because our status changes, it sets the strategy to Connected. The reason we are going with connected is because we need a state that is between waiting for a connection and being logged in. Here is the code for Connected:


using AegisBornCommon;
using ExitGames.Client.Photon;


public class Connected : IGameState
{


    public static readonly IGameState Instance = new Connected();


    public GameState State
    {
        get { return GameState.Connected; }
    }


    public void OnEventReceive(Game gameLogic, AegisBornCommon.EventCode eventCode, System.Collections.Hashtable eventData)
    {
        gameLogic.OnUnexpectedEventReceive(eventCode, eventData);
    }


    public void OnOperationReturn(Game gameLogic, AegisBornCommon.OperationCode operationCode, int returnCode, System.Collections.Hashtable returnValues)
    {
        gameLogic.OnUnexpectedPhotonReturn(returnCode, operationCode, returnValues);
    }


    public void OnPeerStatusCallback(Game gameLogic, ExitGames.Client.Photon.StatusCode returnCode)
    {
        switch (returnCode)
        {
            case StatusCode.Disconnect:
            case StatusCode.DisconnectByServer:
            case StatusCode.DisconnectByServerLogic:
            case StatusCode.DisconnectByServerUserLimit:
            case StatusCode.TimeoutDisconnect:
                {
                    gameLogic.SetDisconnected(returnCode);
                    break;
                }


            default:
                {
                    gameLogic.OnUnexpectedPhotonReturn((int)returnCode, OperationCode.Nil, null);
                    break;
                }
        }
    }


    public void OnUpdate(Game gameLogic)
    {
        gameLogic.Peer.Service();
    }


    public void SendOperation(Game gameLogic, AegisBornCommon.OperationCode operationCode, System.Collections.Hashtable parameter, bool sendReliable, byte channelId)
    {
        gameLogic.Peer.OpCustom((byte)operationCode, parameter, sendReliable, channelId);
    }
}


I made a couple minor modifications to my code in Game.cs and Login.cs. I removed the status and added a new property that adds the state. I added this code to Game.cs:


    public GameState State
    {
        get
        {
            return _stateStrategy.State;
        }
    }

Then I went into Login.cs and modified the OnGUI line for the label and made it:

        GUI.Label(new Rect(100, 100, 300, 300), _engine.State.ToString());

So now it uses the engine's state to display if we are disconnected, waiting for connection, or connected. If you press the operation button it sends operation 100 like we did before and we get an unexpected return because we didn't implement that portion into the connect class.

With those changes, we are caught up to my check in. This covers the majority of the functionality of the demo in terms of patterns and design. From here on out we are going to modify how things are done to rebuild what we built in SmartFoxServer by making the server look up our user data and allow logins and follow through character select. Next time we will look at modifying Connected to pass our login data and begin getting the operation on the server side. See you then!

No comments: