Showing posts with label SmartFoxServer. Show all posts
Showing posts with label SmartFoxServer. Show all posts

Wednesday, 15 December 2010

SmartFoxServer 2x and Hibernate

I've been looking at using Object/Relational Mapping (ORM) to link my database and server extension in SmartFoxServer since reading the SmartFoxServer white paper on developing an MMO. Hibernate is one I've heard of, so I've been starting with that.

An ORM tool basically abstracts out connecting your objects to the database. It's possible to do all of this in SmartFoxServer using the in-built database manager, but not without some fairly intricate and repetitive code-wrangling. Hibernate should (in theory) take out a lot of the CRUD work.

To configure the connection between Hibernate and the database, you create a hibernate.cfg.xml file. This goes in the root of the src folder for the project, and includes all the settings for the connection, including which driver, which database etc. This clearly supersedes the information set up in the SFS2X database manager, so we could probably not bother setting that up.

Each object in the model that gets saved out to the database needs an xml file mapping the tables and columns in the database to the types and objects in the class. I'm putting these xml files in the same packages as the classes themselves. The hibernate.cfg.xml requires the full mapping to these files, including the package path. (e.g. <mapping resource="uk/ac/sussex/model/User.hbm.xml" /> not just <mapping resource="User.hbm.xml" />)

All of the xml files get included when I package up the .jar file for the extension.

To get the system up and running I needed to include the following jars:
antlr-2.7.6.jar
commons-collections-3.1.jar
dom4j-1.6.1.jar
hibernate-jpa-2.0-api-1.0.0.Final.jar
hibernate3.jar
javassist-3.12.0.GA.jar
jta-1.1.jar
slf4j-api-1.6.1.jar

These all needed to be included in the same folder as my extension (so {wherever}/SFS2X/extensions/gameBackend) NOT in the __lib__ folder of my extension (so {wherever}/SFS2X/extensions/__lib__) . When I put them in there hibernate then couldn't find the hibernate.cfg.xml unless I put that file separately into the root of my SFS2X installation, rather than leaving it in the extension jar. That would mean that I couldn't use separate hibernate configurations for each extension, which would be a bit ridiculous.

The server needed restarting once all of the jars had been put in place. I still haven't got the log4j stuff up and running correctly - I think SFS2X already uses log4j, so there's probably something in the configuration somewhere that needs changing, but I've not really looked into it yet.

Setting the project up like this also means that I can write JUnit tests for my model objects, provided that I include all of the same jars in the build path. The database connection does not depend on having SmartFoxServer running, so the objects are more server-independent (although now reliant on Hibernate! Swings and roundabouts I guess.)

Thursday, 25 November 2010

Linking SmartFoxServer and MySQL

How to get a zone set up to use a specific database is actually rather well covered in the documentation. Here's my set up after doing that:
The important bits to change are the connection string, which will need the right port for the MySQL instance that you want, and the database name (test_db in the example above). The username and password are for the database. I have used the oh-so-insecure root with no password, but normally you would want to create a specific user with a strong password who only has access to that database.

The test SQL is used by the server when it sets up the zone to check that the server connection is good. If your test SQL is broken it will refuse to connect, but it doesn't really matter what the result of your test is. Short and sweet might be good! It will need to be specific for each database.

The code side of talking to the database is more convoluted and we will probably end up wrapping some of our common actions. It is dealt with in the server-side code. It relies on us having access to the Zone object,  which has a DBManager property that can access the database using the connection settings above.

This is an example of the code that could be used in a request handler class that extends the BaseClientRequestHandler:

    SFSExtension parentExtension = this.getParentExtension();
    Zone parentZone = parentExtension.getParentZone();
    IDBManager dbManager = parentZone.getDBManager();
    try {
        dbManager.executeUpdate("INSERT  INTO log VALUES ('"+sender.getName()+"',     
        'input two numbers to add')");
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
That will successfully write data to the table in the database linked to in the zone manager when that request handler is fired. 

Thursday, 18 November 2010

Client-side code for SmartFoxServer

At the moment, we're writing our client-side code in ActionScript 3.0. How to access the libraries in your swf is covered in a different blog post.

I'm intending to wrap the calls to the SmartFox client API in a set of local classes. This is a bit of insurance, so that if we decide to change our server part way through most of our code will be left unchanged.

What I've done is create a server class, that has functions such as login and sendRequest that can be accessed by the main game. Behind the scenes, this class then deals with connection and all the SmartFox classes. It then dispatches custom server events as required. These can be listened for in the rest of the game, with no dependancy on the SmartFox events.

The other part of this is to dress up the request parameters so they can be sent in the required format. I've defined a RequestParam class, that holds a name, a type (e.g. Int, String etc) and a value. The server class can then interpret these to add them to the proper SFSObject and send them to the server. I've actually started creating subclasses of the RequestParam class for each type of parameter, so initially there's a RequestParamInt. This sets the type of the parameter automatically, and hopefully keeps the code pretty clear and a bit more free of constants than otherwise.

Logging in
To create a connection to the SmartFoxServer, the game creates an instance of Server.as, starts listening for the ServerEvent.LOGIN_SUCCESSFUL event, and calls server.login with the appropriate parameters.

The server class checks to see if the client is already connected to the server, and if so it performs the login. If the client is not connected to the server it calls the connection code, listens for the connected event, and when that event happens successfully triggers the login code again.

When the response to the login is received, if that login was successful the Server class dispatches the ServerEvent.LOGIN_SUCCESSFUL event that the game is listening for, and the game can carry on with whatever it needs to do next.

Extension Requests
Sending an extension request is similar. Walking through the add example given in the Server side extension doc  the client creates two instances of RequestParamInt. One has a name of 'n1' and an integer value (e.g. 3), the other has a name of 'n2' and an integer value (e.g. 4). These are added to an array. The client calls on the server object to sendRequest. SendRequest takes a string parameter of 'add' as the request name (which matches the string name given in the server-side extension when the request handler is added) and the array of parameters.

Even if there is only one parameter, the server object is still expecting an array!

The server class goes through the array of parameters and adds them to an SFSObject, using the type parameter to work out which of the SFSObject methods to call (e.g. putInt, putString etc.) and creates a new request which is an instance of ExtensionRequest. This uses the request name and the SFSObject as parameters. This request is then sent to the server and we wait for a response event that gets bubbled up to the main game structure.

Server Responses
The request that comes back includes a params object. Each type of event uses the params object slightly differently, and a full description can be found in the Client API Javadoc under com.smartfoxserver.v2.core -> SFSEvent. I think we might want to set up some kind of response handler structure for the Extension responses in a similar way to the server side does - each response is sent back with a command name to allow different things to happen with the results, so it may be useful to use that.

This structure will get added to, as needed!

Setting up SmartFox server-side extensions

SmartFoxServer provides a client API (we'll be using the AS3 API) and a set of classes to create server-side extensions in Java. The server is set up with a series of zones, each of which acts as a separate application. A client is configured to connect to a particular zone by name. The details of which IP address, port and which zone are all kept in an XML file, and read by the client code the first time the client is asked to connect to the server. 

The diagram below is a really crude picture of what happens when the client sends a request to the server. 


The client packages up the name of the request it's trying to call, and the parameters needed for that call. Then it effectively lobs them over to the server in a bundle, along with the information about which zone it is supposed to be talking to. The server then uses the zone set up information to call the extension, which is set up with a list of RequestHandler classes. It uses the name request name passed through from the client to work out which RequestHandler class should be called, and passes the parameter data through to that class. 

That request handler can then use as much or as little extra backend code as you like, and optionally passes a response back to the client. The client can be a single user object (which can either be the generic SFS user object or a custom one that extends that object), or a list of users to alert. The client needs to use the events supplied with the client API to be notified of any responses, as the connection is asynchronous. 

Setting up the extension for the zone is pretty straightforward. Using the inbuilt Zone Configurator (is that really a word?), go to the tab labelled 'Zone extension'. The name field contains the folder that the extension jar is in within the extensions folder on the server. The type field defaults to Java, which is what we're using. And the file is the class within your jar (package included) that extends the SFSExtension class.

I haven't tried adding Room Extensions yet, but I suspect that will work along the same lines. 


There are other features that might become handy, such as multi-handlers which would allow us to break our code down into smaller chunks - ie. a list of requests for each area in a separate handler, rather than a long list of request handlers for everything in the first class. If/when we use them I'll revisit!

Wednesday, 17 November 2010

SmartFoxServer 2X - Enabling Remote Access

To allow remote access to SFS edit, first add the server IP address to the server socket addresses:
  1. Navigate to http://localhost:8080/admin.
  2. Login to the admin tool.
  3. Select "Server Configurator" from the Administration Modules menu.
  4. Under the "General" tab add the server IP address to the Socket Addresses.
  5. Restart the server.
NB The configuration file {install-dir}/SFS2X/config/server.xml can also be edited directly.

Secondly, open the appropriate ports on the server firewall. By default these are TCP port 9933 ( incoming and outgoing traffic) and TCP port 8080 (if access to the server webserver is required).

Client machines must also have their firewalls suitably configured. For clients in secure client environments, the BlueBox extension (which wraps the SFS protocol in HTTP packets) may be required.

Thursday, 11 November 2010

SmartFoxServer 2X Server Side Extensions - Eclipse Setup

To create server side extensions for SFS 2X several libraries must be added to the project build path. The main archive files required are sfs2x.jar and sfs2x-core.jar. If logging features are needed log4j-1.2.15.jar, slf4j-api-1.5.10.jar and slf4j-log4j12.jar should also be added as external jars. All files are located under the {install-dir}/SFS2X/lib folder.

When writing java files you'll need to include various import statements such as:

import com.smartfoxserver.v2.extensions.SFSExtension;
import com.smartfoxserver.v2.entities.*;
import com.smartfoxserver.v2.core.*;


and the like. Also add "extends SFSExtension" to the declaration of classes that will call the API methods and classes.

http://docs2x.smartfoxserver.com/AdvancedTopics/server-side-extensions

Flash Developer - SmartFoxServer 2X Flash API Setup

The API for Actionscript 3 support is distributed as a single .SWC library (SFS2X_API_AS3.swc) that needs to be added to the development environment. The file is located under the {install-dir}/Client/API/ folder.

In Flash Developer select Edit->Preferences.
Under the "ActionScript" category select "ActionScript 3.0 Settings..."
Add the SWC folder path to the Library Path.
Click OK to exit the Settings Window & OK again to exit the Preferences window.

Tuesday, 9 November 2010

SmartFoxServer

SmartFoxServer is a socket server for multiuser applications and games. It’s designed primarily for Adobe Flash, with APIs for Actionscript 2.0 & 3.0. Other APIs include Java, .Net/Unity3D, iPhone and Android.

SmartFoxServer comes in 3 flavours – Lite, Basic and Pro - with a new "2X" version at the RC stage. The Lite provides basic functionality and supports only Actionscript 1.0 & 2.0; Basic has increased functionality and supports Actionscript 3.0 – it is suitable for the development of multiplayer applications that don’t require server side coding; the Pro version supports server-side extensions, database access, clustering and includes an embedded web server. This table compares the versions:

http://www.smartfoxserver.com/products/

The Lite version is free; Basic costs between 200€ (100 users) and 800€ (unlimited); Pro costs between 500€ (100 users) and 2000€ (unlimited). “Trial” versions of Basic and Pro products can be used to a maximum of 20 users. The trial versions are full-functional, the license is not time-limited and the servers can be used commercially.

The 2X version is a major redesign of the original server and is claimed to to be simpler to use, more versatile and offer higher performance than its predecessor. Current price is 750€ for 500 concurrent users though the server can be used with up to 100 users at no charge.

Installation is fairly straightforward though with Vista and Windows 7 it is best to avoid installation in C:/Program Files as you won’t be able to modify the configuration & example files without Administrator privileges. However choose a location on a local disk as the installer complains if you try to install on a network drive. Once installed you can set the server to run as a service (Basic and Pro versions only).

SmartFoxServer has a useful Admin Tool that enables you to start/halt the server, keep track of performance, manage zones, extensions and banned user lists.


Java and other APIs can be downloaded here:

http://www.smartfoxserver.com/labs/API/

I installed the Java API, following these instructions:

http://www.smartfoxserver.com/docs/index.htm?http://www.smartfoxserver.com/docs/docPages/sfsPro/javaExtensions.htm

I also had to download nanoxml-2.2.3.jar from here:

http://www.codecase.cn/Code/Jar/MNOPQR/Downloadnanoxml223jar.htm

though was unable to find "it.gotoandplay.utils.net.xmlsocket" for the Java client code.