Smartfoxserver 2x

SmartFoxServer 2x

  1. Setup

  2. Connect GUI

  3. Handling Information between Server and Client

  4. Setup

  • download the SmartFoxServer 2x here .
  • install the server on your desktop.
  • start the server
  • open the admin tool with typing in your browser http://localhost:8080/admin/
  • connect to server
  • default Username/Password:
    Username: sfsadmin Password: sfsadmin

  • go to Administration modules → Server Configurator
  • add a new socketaddress, same ip, port type = UDP

  • don’t forget to submit

  • I get the basics for the connect/login from the FPS Demo, which can be downloaded here

  • in the folder SFS2x you will find a new folder with the name extensions open the folder and put in it the folder from the FPS Demo called SFS2XFPSextension

  • you can give this folder a name you like

  • now open the project “SFS2XFPSTutorial” with unity3d

  • go to the NetworkManager.cs and change the name

public readonly static string ExtName = "tng";// <----this is the SFS2XFPSextension folder if you renamed it , then put the current name here

  • thats all on the configuration part, you can start the server and login.
  1. Connect GUI
    You can change the Connect/Login phase like you want i do it this way, because i do not like the "chatroom " in the demo:

LobbyGUI.cs

using System.Text;
using Sfs2X;
using Sfs2X.Core;
using Sfs2X.Entities;
using Sfs2X.Requests;
using Sfs2X.Logging;


public class LobbyGUI : MonoBehaviour {

	private SmartFox smartFox;
	private string zone = "SimpleChat";
	public string serverName = "127.0.0.1";
	public int serverPort = 9933;
	private string username = "";
	private string userpassword="";
	private string loginErrorMessage = "";
	public int areaHeight = 240;
 	public int areaWidth = 200;
	public Texture2D background;
	private ArrayList messages = new ArrayList();
	private System.Object messagesLocker = new System.Object();
	public GUISkin gSkin;

	void Start()
	{
		bool debug = false;
		if (SmartFoxConnection.IsInitialized)
		{
			smartFox = SmartFoxConnection.Connection;
		}
		else
		{
			smartFox = new SmartFox(debug);
		}
			
		smartFox.AddLogListener(LogLevel.INFO, OnDebugMessage);
	}
	
	void FixedUpdate() {
		smartFox.ProcessEvents();
	}
	
	#region Callbacks
	
	private void AddEventListeners() {
		
		smartFox.RemoveAllEventListeners();
		
		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.ROOM_JOIN, OnJoinRoom);
		smartFox.AddEventListener(SFSEvent.PUBLIC_MESSAGE, OnPublicMessage);
		
		smartFox.AddEventListener(SFSEvent.ROOM_CREATION_ERROR, OnCreateRoomError);
		smartFox.AddEventListener(SFSEvent.USER_ENTER_ROOM, OnUserEnterRoom);
		smartFox.AddEventListener(SFSEvent.USER_EXIT_ROOM, OnUserLeaveRoom);
		smartFox.AddEventListener(SFSEvent.ROOM_ADD, OnRoomAdded);
		smartFox.AddEventListener(SFSEvent.ROOM_REMOVE, OnRoomDeleted);
		smartFox.AddEventListener(SFSEvent.USER_COUNT_CHANGE, OnUserCountChange);
		smartFox.AddEventListener(SFSEvent.UDP_INIT, OnUdpInit);
	}
	
	private void UnregisterSFSSceneCallbacks() {
		smartFox.RemoveAllEventListeners();
	}
	
	public void OnConnection(BaseEvent evt) {
		bool success = (bool)evt.Params["success"];
		if (success) {
			SmartFoxConnection.Connection = smartFox;
			Debug.Log("Connected...");
			isConnected=true;
			smartFox.Send(new LoginRequest(username, "", zone));
		}
	}

	public void OnConnectionLost(BaseEvent evt) {
		UnregisterSFSSceneCallbacks();
	}

	public void OnLogin(BaseEvent evt) {
		try {
			if (evt.Params.ContainsKey("success")  !(bool)evt.Params["success"]) {
				loginErrorMessage = (string)evt.Params["errorMessage"];
				Debug.Log("Login error: "+loginErrorMessage);
			}
			else {
				Debug.Log("Logged in successfully");
				// Startup up UDP
				smartFox.InitUDP(serverName, serverPort);
			}
		}
		catch (Exception ex) {
			Debug.Log("Exception handling login request: "+ex.Message+" "+ex.StackTrace);
		}
	}

	public void OnLoginError(BaseEvent evt) {
		Debug.Log("Login error: "+(string)evt.Params["errorMessage"]);
	}
	
	public void OnUdpInit(BaseEvent evt) {
		if (evt.Params.ContainsKey("success")  !(bool)evt.Params["success"]) {
			loginErrorMessage = (string)evt.Params["errorMessage"];
			Debug.Log("UDP error: "+loginErrorMessage);
		} else {
			Debug.Log("UDP ok");
			SetupRoom("Sunna");
		}
	}
	
	void OnLogout(BaseEvent evt) {
		smartFox.Disconnect();
	}
	
	public void OnDebugMessage(BaseEvent evt) {
		string message = (string)evt.Params["message"];
		Debug.Log("[SFS DEBUG] " + message);
	}

	public void OnJoinRoom(BaseEvent evt)
	{
		Room room = (Room)evt.Params["room"];
		// If we joined a game room, then we either created it (and auto joined) or manually selected a game to join
		if (room.IsGame) {
			Debug.Log ("Joined game room " + room.Name);
			UnregisterSFSSceneCallbacks();
			Application.LoadLevel("game");
		}
	}

	public void OnCreateRoomError(BaseEvent evt) {
		string error = (string)evt.Params["errorMessage"];
		Debug.Log("Room creation error; the following error occurred: " + error);
	}

	public void OnUserEnterRoom(BaseEvent evt) {
		User user = (User)evt.Params["user"];
		lock (messagesLocker) {
			messages.Add(user.Name + " joined room");
		}
	}

	private void OnUserLeaveRoom(BaseEvent evt) {
		User user = (User)evt.Params["user"];
		lock (messagesLocker) {
			messages.Add(user.Name + " left room");
		}
	}

	public void OnRoomAdded(BaseEvent evt) {
		Room room = (Room)evt.Params["room"];
		if ( room.IsGame ) {
			smartFox.Send(new JoinRoomRequest("Sunna", null, smartFox.LastJoinedRoom.Id));
		}
	}
	
	public void OnUserCountChange(BaseEvent evt) {
		Room room = (Room)evt.Params["room"];
		if (room.IsGame ) {
		}
	}

	public void OnRoomDeleted(BaseEvent evt) {
	}

	void OnPublicMessage(BaseEvent evt) {
		try {
			string message = (string)evt.Params["message"];
			User sender = (User)evt.Params["sender"];
	
			lock (messagesLocker) {
				messages.Add(sender.Name + " said " + message);
			}
			
			Debug.Log("User " + sender.Name + " said: " + message);
		}
		catch (Exception ex) {
			Debug.Log("Exception handling public message: "+ex.Message+ex.StackTrace);
		}
	}

	#endregion Callbacks
	
	

	private bool isConnected;
	
	void OnGUI()
	{
		if (smartFox == null){
			return;
		}
	
		GUI.DrawTexture(new Rect(0,0,Screen.width,Screen.height), background);
		GUI.skin = gSkin;
		
		int ScreenX = ((int)(Screen.width / 2) - (areaWidth / 2));
    	int ScreenY = ((int)(Screen.height / 2) - (areaHeight / 2));

		// Connect
		if (!isConnected) {
			GUILayout.BeginArea (new Rect (ScreenX, ScreenY, areaWidth, areaHeight),"Login","Window");
			GUILayout.Label("Server: ");
			serverName = GUILayout.TextField(serverName, 25);

			GUILayout.Label("Port: ");
			serverPort = int.Parse(GUILayout.TextField(serverPort.ToString(), 4));
			
			GUILayout.Label( "Username: ");
			username = GUILayout.TextField( username, 25);
			
			GUILayout.Label("Password: ");
			userpassword=GUILayout.PasswordField (userpassword, "*"[0], 25);
			
			GUILayout.Space(4);
			if (GUILayout.Button("Login")  || (Event.current.type == EventType.keyDown  Event.current.character == '\n'))
			{
				AddEventListeners();
				smartFox.Connect(serverName, serverPort);
			}
			GUILayout.EndArea();
		}
	}
	
	private void SetupRoom(string roomName){
		if(smartFox.GetRoomByName(roomName)==null){
			
			RoomSettings settings = new RoomSettings(roomName);
			settings.GroupId = "game";
			settings.IsGame = true;
			settings.MaxSpectators = 0;
			settings.Extension = new RoomExtension(NetworkManager.ExtName, NetworkManager.ExtClass);
			smartFox.Send(new CreateRoomRequest(settings, true, smartFox.LastJoinedRoom));
		}else{
			smartFox.Send(new JoinRoomRequest(roomName));
		}
	}
	
	 void OnApplicationQuit() {
        if (smartFox.IsConnected) {
            smartFox.Disconnect();
        }
    } 
}

It should look like this:

  1. Handling Information between Server and Client
    I want to show this based on my InventorySystem(it is not completely done but i will Update this small tutorial)

In the NetworkManager.cs i have added this code for picking up an item.

        /// <summary>
	/// Request for collecting Items
	/// </summary>	
	public void PickUpRequest(int id,string name){
		Room room = smartFox.LastJoinedRoom;
		ISFSObject data=new SFSObject();
		data.PutInt("id",id);
		data.PutUtfString("name",name);
		ExtensionRequest request = new ExtensionRequest("pickUp", data, room);// *1
		smartFox.Send(request);
	}

1* //<— this message with some data will be sended to the server. I have put the id and the name of the item to the data, but you can put in it what you like. Later the item will be checked(is this item movable, is my cmdLevel high enough for picking it up, and get its data like damage or quality from a database…) based on this data.

Now i have created a new c# script called ItemController.cs and put this script on every GameObject which can be picked up. Read the code to know what it does.

using UnityEngine;
using System.Collections;

public class ItemController : MonoBehaviour {
  	public Texture2D inventoryIcon;
	public int id; // the id should be generated, but for testing it is good enough

	// Use this for initialization
	void Awake () {
		gameObject.name = gameObject.name.Replace("(Clone)",""); //The name of the gameobject will be replaced i delete the "Clone".
	}
	
        //If the player clicks on the gameobject we will send the request to pickup the item.
	void OnMouseUp(){ 
		NetworkManager.Instance.PickUpRequest(id ,gameObject.name); 
	}
}

Now we need something on the server, what can get this request, do the checks and send an “ok” to the client. I am using eclipse to write the server code.

You can download it here.

Maybe i have to explain first the setup eclipse with the example FPS Demo:

  • if You have installed eclipse, create a new workspace.

  • click with the right-mouse-button to import a new project.

  • now import an existing project

  • click on next and brows the “SFS2XFPSextension” folder and the finish button
  • it should look like this:

Now you have done the setup and can start with coding.

Add a new Requesthandler to your FPSExtension. I have renamed them so it looks diffrent.

@Override
	public void init() {
		world = new World(this);  // Creating the world model

		// Subscribing the request handlers
		addRequestHandler("sendTransform", SendTransformHandler.class);
		addRequestHandler("sendAnim", SendAnimHandler.class);
		addRequestHandler("spawnMe", SpawnMeHandler.class);
		addRequestHandler("getTime", GetTimeHandler.class);
		addRequestHandler("pickUp",PickUpHandler.class);
		addRequestHandler("getInventoryList",InventoryHandler.class);
		
		addEventHandler(SFSEventType.USER_DISCONNECT, OnUserGoneHandler.class);
		addEventHandler(SFSEventType.USER_LEAVE_ROOM, OnUserGoneHandler.class);
		addEventHandler(SFSEventType.USER_LOGOUT, OnUserGoneHandler.class);

		trace("FPS extension initialized");
	}
  • Create a new java class and call it “PickUpHandler”.
public class PickUpHandler extends BaseClientRequestHandler{
	
	@Override
	public void handleClientRequest(User user, ISFSObject data) {
		World world = RoomHelper.getWorld(this);
		SigCharacter player=world.getPlayer(user);
		//Login to database and get item data
		//---
		SigItem item= new SigItem(data.getInt("id"),data.getUtfString("name"),new Transform(0,0,0,0,0,0),124);
		//---
		player.AddItem(item);
		world.useItem(player, item);
	}
}

Now you can get the information of the item you have sended. The information is in the ISFSObject data .
You can get the id :

data.getInt(“id”)

then log in to a database and pick the item and send the whole information of the item to the client.

(I am a hobby programmer so i do not know if this is the best method.)

  • then you can add this item to a List and you have got your inventory List.
  • now you can code a request to get the inventory List the same way.

Add a Request in the NetworkManager.cs

	/// <summary>
	/// Request for the InventoryList
	/// </summary>	
	public void InventoryRequest(){
		Room room = smartFox.LastJoinedRoom;
		ExtensionRequest request = new ExtensionRequest("getInventoryList", new SFSObject(), room);
		smartFox.Send(request);
	}

Send Request to the server

using UnityEngine;
using System.Collections;

public class InputHandler : MonoBehaviour {
	
	void Update () {
        // I: Inventory
        if (Input.GetKeyUp(KeyCode.I))
        {
           NetworkManager.Instance.InventoryRequest();
        }
		
	}
}

thanks Zerano

No Problem, it is good to read a thanks, because of no reply i thought nobody needs a tutorial like this and i wanted to stop it :smile:

Thanks for your dedication to write this tutorial., Zerano.

OMG!!!This tutorial appears exactly in the hour that I most need it:smile:Thank you buddy thanks very much:smile:

Nice, very useful tutorial :smile:

some new basic information…

I found this nice tutorial today:
http://games.anomsoft.com/wp-content/uploads/2011/05/smartfoxserver_guide.pdf

Nice Zerano !

Thumbs up

Thank you very much Zerano, this is a very wonderful tutorial. This and your work on the RPG starter kit have kept me very busy.

Keep up the good work!

Nemo

  • in the folder SFS2x you will find a new folder with the name extensions open the folder and put in it the folder from the FPS Demo called SFS2XFPSextension

What folder from what FPS Demo?
Your asking me to put the SFS2XFPSextension in the SFS2XFPSextension? What?
There was only UnityFPSDemo and two folders SFS2XFPSextension and SFS2XFPSTutorial.
So, I’m very confused by this step.

EDIT: I finally got what you mean, but what’s that last step with inputhandler?
No such script in Unity project I have

Thank you very much for this tutorial - this is exactly what I needed plus bonus stuff like the change of the login GUI. I’d better check out what else you’ve made (¨,)

/Jens

sorry to be a downer but I’m running into alot of errors with just LobbyGUI.cs
Its complaining about ArrayList on line 24 and SmartFoxConnection.IsInitialized on line 31 of LobbyGUI.cs and thats just the beginning, im now scared to strip the coding to find any more errors.