SmartFox/Unity3D/MSSQL expert needed

SmartFoxServer gurus looking for a new job and companies looking for multi-player developers, this is the right place to meet!

Moderators: Lapo, Bax

User avatar
JalenBlade
Posts: 14
Joined: 11 Jun 2009, 15:35

SmartFox/Unity3D/MSSQL expert needed

Postby JalenBlade » 13 Jun 2009, 01:18

I'm looking for someone who can answer a few questions and get some basic configurations set-up for me in SFS with Unity3d and MS SQL.

I'm personally not a programmer but a network administrator and level designer. I could wade through all of these things over the course of a week or so but would rather pay someone who can get the job done in less time with more accuracy. I don't want to be a mooch and nickel and dime the boards to death with dumb questions.

I need a login screen, buddy system, and a few other minor things done ASAP. More work to do as time goes on if interested.
Please PM me if you've got a day or two to kill and would like to get paid for your skills!
ThomasLund
Posts: 1297
Joined: 14 Mar 2008, 07:52
Location: Sweden

Postby ThomasLund » 15 Jun 2009, 14:27

Hi

I would normally be interested, but I am way past my limit on current jobs really.

But I can give you a few pointers! For free. And feel free to contact me later if you need/want any contractors onboard.

For the client side - the Unity tutorials more or less have what you request. Login screen, infrastructure code for complete scene and all - except buddy list part. That needs to be done, but the tutorials will get you 80% of the way right from the start.

For the database part - you will need to download the MS SQL jdbc driver:

http://msdn.microsoft.com/en-us/data/aa937724.aspx

Once you have that, database access and setup is 99% the same for all database engines. Driver into libs, maybe need to fix classpath and then basically simply instantiate and code up against jdbc. There should be several database examples already here (check the java cookbook and SFS documentation).

Hope that helps you along!

/Thomas
User avatar
JalenBlade
Posts: 14
Joined: 11 Jun 2009, 15:35

Postby JalenBlade » 15 Jun 2009, 15:40

I was able to get config.xml to connect to my SQL database using odbc. Are you sure I need the jdbc driver? Keep in mind, I know nothing about it...lol
ThomasLund
Posts: 1297
Joined: 14 Mar 2008, 07:52
Location: Sweden

Postby ThomasLund » 15 Jun 2009, 15:45

On a Windows box you might get away with it. But SmartFoxServer is a java environment, and the jdbc driver works cross platform, while odbc is windows only.

So the safe bet is to use jdbc, and from code use jdbc connections.

:-)

/Thomas
User avatar
JalenBlade
Posts: 14
Joined: 11 Jun 2009, 15:35

Postby JalenBlade » 15 Jun 2009, 16:04

So, Unity has login screens that demonstrate connecting to a database and verifying the username and password? I haven't run across them yet. I've been pouring over SFS's docs and I see a lot of good info but nothing that shows me code for connecting and verifying a user against an existing database. I already have an account creation system so that's not a problem at the moment. I'll want to integrate it all at some point but for now it works.

Another question I have is whether or not I could contain all chat in a lower window (frame) below the actual game in the web browser. My reasoning is to keep the text readable and off the game screen...and if so, how does that work when a player changes zones/levels in the game?

I really wish there was a working example of the login/verification process so I could get past it and move on!

Thank you!
ThomasLund
Posts: 1297
Joined: 14 Mar 2008, 07:52
Location: Sweden

Postby ThomasLund » 15 Jun 2009, 17:08

Here is the script for a Unity login page using a custom login handler:

Code: Select all

using UnityEngine;
using System;
using System.Collections;
using SmartFoxClientAPI;
using SmartFoxClientAPI.Data;
using SmartFoxClientAPI.Util;

public class LoginGUI : MonoBehaviour {
   private SmartFoxClient smartFox;
   private bool shuttingDown = false;

   public string serverIP = "72.47.211.194";
   public int serverPort = 9339;
   public string zone = "SmartTactics";
   public bool debug = true;

   private string username = "";
   private string password = "";
   private string loginErrorMessage = "";

   /************
     * Unity callback methods
     ************/

   void OnApplicationQuit() {
      shuttingDown = true;
   }

   void Awake() {
      Application.runInBackground = true;

      if ( SmartFox.IsInitialized() ) {
         smartFox = SmartFox.Connection;
      } else {
         try {
            smartFox = new SmartFoxClient(debug);
         } catch ( Exception e ) {
            loginErrorMessage = e.ToString();
         }
      }

      // Register callback delegate
      SFSEvent.onConnection += OnConnection;
      SFSEvent.onConnectionLost += OnConnectionLost;
      SFSEvent.onExtensionResponse += OnExtensionResponse;
      SFSEvent.onRoomListUpdate += OnRoomList;
      SFSEvent.onDebugMessage += OnDebugMessage;

      smartFox.Connect(serverIP, serverPort);
   }

   void OnGUI() {
      if ( smartFox.IsConnected() ) {
         // Login
         GUI.Label(new Rect(10, 30, 100, 100), "Userame: ");
         username = GUI.TextField(new Rect(100, 30, 200, 20), username, 25);

         GUI.Label(new Rect(10, 50, 100, 100), "Password: ");
         password = GUI.TextField(new Rect(100, 50, 200, 20), password, 4);

         GUI.Label(new Rect(10, 130, 100, 100), loginErrorMessage);

         if ( GUI.Button(new Rect(10, 80, 100, 30), "Login") ) {
            smartFox.Login(zone, username, password);
         }
      } else {
         GUI.Label(new Rect(10, 100, 100, 100), "Waiting for connection");
         GUI.Label(new Rect(10, 130, 100, 100), loginErrorMessage);
      }
   }

   /************
    * Helper methods
    ************/

   private void UnregisterSFSSceneCallbacks() {
      // This should be called when switching scenes, so callbacks from the backend do not trigger code in this scene
      SFSEvent.onConnection -= OnConnection;
      SFSEvent.onConnectionLost -= OnConnectionLost;
      SFSEvent.onExtensionResponse -= OnExtensionResponse;
      SFSEvent.onRoomListUpdate -= OnRoomList;
      SFSEvent.onDebugMessage -= OnDebugMessage;
   }

   /************
    * Callbacks from the SFS API
    ************/

   void OnConnection(bool success, string error) {
      if ( success ) {
         SmartFox.Connection = smartFox;
      } else {
         loginErrorMessage = error;
      }
   }

   void OnConnectionLost() {
      loginErrorMessage = "Connection lost / no connection to server";
   }

   public void OnDebugMessage(string message) {
      Debug.Log("[SFS DEBUG] " + message);
   }

   public void OnExtensionResponse(object data, string type) {
      // We only use XML based messages in this tutorial, so ignore string and json types
      if ( type == SmartFoxClient.XTMSG_TYPE_XML ) {
         // For XML based communication the data object is a SFSObject
         SFSObject dataObject = (SFSObject)data;

         switch ( dataObject.GetString("_cmd") ) {
            case "logOK":
               // Login was OK, so lets set the variables usually done on regular login event by the API
               smartFox.myUserName = dataObject.GetString("name");
               smartFox.myUserId = int.Parse(dataObject.GetString("id"));
               break;
            case "logKO":
               // Login failed - lets display the error message sent to us
               loginErrorMessage = dataObject.GetString("err");
               break;
         }
      }
   }

   void OnRoomList(Hashtable roomList) {
      // When room list is updated we are ready to move on to the lobby
      UnregisterSFSSceneCallbacks();
      Application.LoadLevel("lobby");
   }
}



And the backend is more or less taken straight from the cookbooks - there is not yet hooked any database into it, but with the cookbook exmaples you should be able to finish this in a breeze.

Extension code in java to handle login:

Code: Select all

package dk.fullcontrol.smarttactics;

import it.gotoandplay.smartfoxserver.data.User;
import it.gotoandplay.smartfoxserver.events.InternalEventObject;
import it.gotoandplay.smartfoxserver.extensions.AbstractExtension;
import it.gotoandplay.smartfoxserver.extensions.ExtensionHelper;
import it.gotoandplay.smartfoxserver.lib.ActionscriptObject;
import it.gotoandplay.smartfoxserver.exceptions.LoginException;
import org.json.JSONObject;

import java.nio.channels.SocketChannel;
import java.util.LinkedList;
import java.util.Iterator;

/**
 * Security services for authentication and account creation
 *
 * For usage in UDM article 2
 */
public class SecurityServices extends AbstractExtension {

   private ExtensionHelper helper;

    public void init()
    {
       // Instantiate our helper object
           helper = ExtensionHelper.instance();
    }


   public void destroy() {
      // Nothing for now
   }


   public void handleRequest(String cmd, ActionscriptObject ao, User u, int fromRoom) {
      System.out.println("XML command recieved " + cmd.toString());
      // Nothing for now - we will later add the account creation request here
   }

   public void handleRequest(String cmd, JSONObject jso, User u, int fromRoom) {
      System.out.println("JSon command recieved " + cmd.toString());
      // Nothing for now - we will later add the account creation request here
   }

   public void handleRequest(String cmd, String params[], User u, int fromRoom) {
      System.out.println("Str command recieved " + cmd.toString());
      System.out.println("Str command recieved " + cmd.toString());
      // Nothing for now - we will later add the account creation request here
   }

   public void handleInternalEvent(InternalEventObject ieo) {
      System.out.println("Internal command recieved " + ieo.getEventName());
      if (ieo.getEventName().equals("loginRequest")) {
         authenticate(ieo.getParam("nick"), ieo.getParam("pass"), (SocketChannel)ieo.getObject("chan"));
      }
   }

   /**
    * Authenticate given credentials
    * @param username The username of the player who wants to login
    * @param password The password given for the username
    * @param channel SocketChannel the given player is connected to, so response can be sent back through that channel
    */
   private void authenticate(String username, String password, SocketChannel channel) {
      ActionscriptObject res = new ActionscriptObject();

      try {
         User user = helper.canLogin(username, password, channel, this.getOwnerZone());
         // The login was successfull
         res.put("_cmd", "logOK");
         res.put("id", String.valueOf(user.getUserId()));
         res.put("name", user.getName());

      } catch (LoginException e) {
         // The server did not allow the user to login
         res.put("_cmd", "logKO");
         res.put("err", e.getMessage());
      }

      // Send response back to calling client
      LinkedList ll = new LinkedList();
      ll.add(channel);
      sendResponse(res, -1, null, ll);

      // Send an update room list to the client to mimick the build in login fundtionality
      if (res.getString("_cmd").equals("logOK")) {
         helper.sendRoomList(channel);
      }
   }
}



Thats about as far as I can help you for free and without anything but cut'n'paste :-)

/T
User avatar
JalenBlade
Posts: 14
Joined: 11 Jun 2009, 15:35

Postby JalenBlade » 15 Jun 2009, 19:29

Thanks a ton...I'll see what I can do. Cross your fingers...I'm going in!
User avatar
JalenBlade
Posts: 14
Joined: 11 Jun 2009, 15:35

Postby JalenBlade » 15 Jun 2009, 23:16

I think I'm lost...
I'm using the island demo from Unity and SFS...
I'm assuming I replace the existing code in LoginGui.cs with the code you posted above..do I then need to rebuild?
Anything else that needs to be changed from within the Unity editor?

Then, I'm looking at the cookbook Login recipe. It appears that Recipe 2 is the one I need for connecting to my MS SQL database. I have a table called citizen_one that contains the usernames and passwords. So I'll need to change that right?

Then the big question is...where do I put all of this code? what file/script? config.xml?

I told you I didn't want to be a mooch! But since there are no takers so far who would like to do it for cash, I'm stuck asking dumb questions...lots of them...lol.
User avatar
JalenBlade
Posts: 14
Joined: 11 Jun 2009, 15:35

more advice needed...

Postby JalenBlade » 24 Jun 2009, 17:05

ok, I'm trying to use your code and the cook book example to make an extension using Eclipse and am getting all kinds of odd errors. Maybe you could look at this and tell me where I'm going wrong... here's my code so far...## lines are creating problems in Eclipse...I've already followed Eclipse's recommendations in many other error situations and have no idea if it will work...there could be all kinds of problems in this code as far as I know. It would be nice if there was an extension for log in verification to a MS SQL database available for modification. Do I NEED to use java for this? Is there an .as extension that would work as well?


Code: Select all

import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.LinkedList;

import it.gotoandplay.smartfoxserver.data.User;
import it.gotoandplay.smartfoxserver.extensions.AbstractExtension;
import it.gotoandplay.smartfoxserver.db.DbManager;
import it.gotoandplay.smartfoxserver.events.InternalEventObject;
import it.gotoandplay.smartfoxserver.exceptions.LoginException;
import it.gotoandplay.smartfoxserver.extensions.ExtensionHelper;
import it.gotoandplay.smartfoxserver.lib.ActionscriptObject;
import org.json.JSONObject;

public class Login{
   
   private ExtensionHelper helper;
   DbManager dbManager;

   public void init()
   {
      helper = ExtensionHelper.instance();
   }
   
   public void destroy() {
   }
   
   public void handleInternalEvent(InternalEventObject ieo) {
         System.out.println("Internal command recieved " + ieo.getEventName());
         if (ieo.getEventName().equals("loginRequest")) {
            authenticate(ieo.getParam("nick"), ieo.getParam("pass"), (SocketChannel)ieo.getObject("chan"));
         }
   }
   /**
       * Authenticate given credentials
       * @param username The username of the player who wants to login
       * @param password The password given for the username
       * @param channel SocketChannel the given player is connected to, so response can be sent back through that channel
       */
      private void authenticate(String username, String password, SocketChannel channel) {
         ActionscriptObject res = new ActionscriptObject();

         try {
            User user = helper.canLogin(username, password, channel, this.getOwnerZone());
            // The login was successfull
            res.put("_cmd", "logOK");
            res.put("id", String.valueOf(user.getUserId()));
            res.put("name", user.getName());

         } catch (LoginException e) {
            // The server did not allow the user to login
            res.put("_cmd", "logKO");
            res.put("err", e.getMessage());
         }

         // Send response back to calling client
        ## LinkedList ll = new LinkedList();
         ll.add(channel);
         sendResponse(res, -1, null, ll); ##

         // Send an update room list to the client to mimick the build in login fundtionality
         if (res.getString("_cmd").equals("logOK")) {
            helper.sendRoomList(channel);
         }
      }


   private String getOwnerZone() {
      // TODO Auto-generated method stub
      return null;
   }

   // Here we execute the check on the database
   boolean checkCredentials(String name, String pass)
   {
      boolean result = false;
      
      
      // SQL statement to execute
      String sql = "SELECT id,name,pass FROM citizen_one WHERE" +
               "name='" + name + "'" +
               "AND pass='" + pass + "'";
      
      // Execute the SQL statement
      ##ArrayList queryRes = dbManager.executeQuery(sql);##
         
      // If record was found exist...
      if (queryRes != null && queryRes.size() > 0)
      {
         result = true;
      }   
         
      return result;
   }


}
Satyarth
Posts: 131
Joined: 06 Nov 2008, 12:45
Location: Delhi, India
Contact:

Postby Satyarth » 26 Jun 2009, 12:28

Hi Jalen,

I can make it work for you. Ping me at :

Return to “Job offers and requests”

Who is online

Users browsing this forum: No registered users and 30 guests