Wednesday, December 15, 2010

Unity3D Login and Joining a Room

First of all a big thank you to those who have been patient all this time. Its been a long time just to get to the part where we are going to create our login call from Unity3D into SmartFoxServer. Having said that lets just dive right in.

In Unity create a new C Sharp Script under Lobby\Scripts and lets call it LobbyGUI.

using UnityEngine;
using System.Collections;
using Sfs2X;
using Sfs2X.Core;
using Sfs2X.Logging;
using Sfs2X.Requests;
using Sfs2X.Entities.Data;
using Sfs2X.Util;


public class LobbyGUI : ConnectionHandler
{
}


Hopefully you noticed right away that we put ConnectionHandler instead of MonoBehavior. With this simple change, all that code we covered last time is now part of this class. If you aren't familiar with coding, this is something called Inheritance. I won't cover that here, please look it up for yourself. Now to add the code. We will start with the variables this class will use:



    public string serverIP = "127.0.0.1";
    public int serverPort = 9933;
    public string gameZone = "[GameName]";


    private string username = "";
    private string password = "";
    private string loginErrorMessage = "";
    private string lastModMessage = "";
    private bool debugMessages = false;


This list of variable is pretty self explanatory. The only confusing thing might be the lastModMessage which will contain the last message passed by the moderator. We will use this later to show the user what happened if they were kicked from the server. Remeber to update the gameZone with your game's name.

Next up is our awake call. Here we will register for all the SmartFox Messages that might be passed to us:

    new void Awake()
    {
        base.Awake();
        // Register callback delegate
        smartFox.AddEventListener(SFSEvent.CONNECTION, OnConnection);
        smartFox.AddEventListener(SFSEvent.CONNECTION_LOST, OnConnectionLost);
        smartFox.AddEventListener(SFSEvent.LOGIN, OnLogin);
        smartFox.AddEventListener(SFSEvent.LOGIN_ERROR, OnLoginError);
        smartFox.AddEventListener(SFSEvent.LOGOUT, OnLogout);
smartFox.AddEventListener(SFSEvent.MODERATOR_MESSAGE, OnMod);
        smartFox.AddLogListener(LogLevel.DEBUG, OnDebugMessage);

    }

You will notice that we call base.Awake(). This is so that when this object's awake call is made, it calls ConnectionHandler's Awake function also which will make sure we are ready to use our SmartFox connection. If you were to try and run the code now, however, you will get a bunch of errors talking about missing functions. We will cover those shortly. First we are going to get our GUI into place. You can play with this if you want, but I'm just going to give it to you. I'll leave it up to you to use Unity to figure out what it does. Also you could watch the tutorials over at BurgZerg Arcade.

    void OnGUI()
    {


        //GUI.skin = gSkin;


        //GUI.Label(new Rect(2, -2, 680, 70), "");


            // Login


            GUI.Label(new Rect(10, 116, 100, 100), "Userame: ");
            username = GUI.TextField(new Rect(100, 116, 200, 20), username, 25);
            GUI.Label(new Rect(10, 141, 100, 100), "Password: ");
            password = GUI.PasswordField(new Rect(100, 141, 200, 20), password, '*', 25);

GUI.Label(new Rect(10, 225, 400, 100), lastModMessage);
            GUI.Label(new Rect(10, 255, 400, 100), loginErrorMessage);


            if (GUI.Button(new Rect(100, 165, 100, 25), "Login") || (Event.current.type == EventType.keyDown && Event.current.character == '\n'))
            {
lastModMessage = "";
                smartFox.Connect(serverIP, serverPort);
            }
            if (GUI.Button(new Rect(100, 195, 100, 25), "Logout"))
            {
                UnregisterSFSSceneCallbacks();
            }
    }


So now we are set and ready to put in those missing functions. I will describe what each of the are doing. First is OnConnection. Here we check if we successfully connected and if we did we send the username to the server and join the General room.
    public void OnConnection(BaseEvent evt)
    {
        bool success = (bool)evt.Params["success"];
        string error = (string)evt.Params["error"];

        if (success)
        {
            loginErrorMessage = "";
            if(debug)
            {
                Debug.Log("Connected");
            }
            smartFox.Send(new LoginRequest(username, "", gameZone));
            smartFox.Send(new JoinRoomRequest("General"));
        }
        else
        {
            loginErrorMessage = error;
        }
    }
Next we will put in the code that happens when we get disconnected.
    public void OnConnectionLost(BaseEvent evt)
    {
        loginErrorMessage = "Connection lost / no connection to server";
    }

    public void OnDebugMessage(BaseEvent evt)
    {
        string message = (string)evt.Params["message"];
if(debugMessages)
{
Debug.Log("**** DEBUG ****" + message);
}
    }
I also included the code that happens when you turn on message debugging. On a disconnect we just put up the connection lost message. When a debug message comes it we simply print it out. This can be useful if you are getting errors but don't know what message is coming in and causing problems.

So now we set up our connection lets get the function in place for when we successfully log in to our zone. This function's purpose is to tell us if we successfully logged in or not.
    public void OnLogin(BaseEvent evt)
    {
        if (evt.Params.ContainsKey("success") && !(bool)evt.Params["success"])
        {
            // Login failed - lets display the error message sent to us
            loginErrorMessage = (string)evt.Params["errorMessage"];
            Debug.Log("Login error: " + loginErrorMessage);
        }
        else
        {
            // We logged into the main game successfully
        }
    }
We left the else block blank. You can play around with this area. You could load the next level or you could set up public/private key encryption, or any number of other things. Lets go ahead and get in the code that happens when an error occurs during login.
    public void OnLoginError(BaseEvent evt)
    {
        Debug.Log("Login error: " + (string)evt.Params["errorMessage"]);
    }

    void OnLogout(BaseEvent evt)
    {
        Debug.Log("OnLogout");
    }
I just put in some simple debugging. There really isn't anything to do in these functions as far as the tutorial is concerned. You could have functions in OnLogout that take you back to the Lobby Scene, but since we are here already, it really isn't useful. The last function we will cover is the OnMod. We use this function to display a message to the user if a Moderator sends us a message.
    void OnMod(BaseEvent evt)
    {
        if(evt.Params.ContainsKey("message"))
        {
            lastModMessage = (string)evt.Params["message"];
        }
    }
That about covers it for this chunk. We now can run our unity program and be logged into our SmartFox server admin panel and see the user as they join the [GameName] extension and then join the General Room. Next time we will cover sending the client's public key and getting back the server's public key so we can use private/public key encryption to send our username and password to the server to look up against our SfGuardUser.

2 comments:

Anonymous said...

SmartFoxConnection.Connection = smartFox;

SmartFoxConnection doesn't contain a Connection function.

Unknown said...

Again, another modification to use the Singleton pattern. I have updated the code. We no longer need the line:

SmartFoxConnection.Connection = smartFox;

So feel free to remove that line from the OnConnection function.