FAQ

Table of Contents

 

About Firebase

What is Firebase?

Firebase is a multiplayer game server. You write your game against the API and then you deploy it to the server much like you would do with a web application and a web server.

What languages do I have to know?

The server side part is based on Java and you will be interfacing towards a Java API. But you can also use scripting languages such as Ruby, Groovy, Python etc. On the client side we have network API's for Java, Flash (AS3), C++ and C#. Not all API's are published on the site at the moment, if you are interested in a missing API then please send us a message and we will try to publish it asap. 

How does Firebase compare to SmartFox and ElectroServer?

Both SmartFox and ElectroServer provides socket server side frameworks that supports game development. The main difference stems from the background. Firebase is primarily built for multiplayer games. The platform was also designed from the business cases for games that handles real money and apart from pure performance we also offer a transactional context for all events executed on the Table if desired. We have also focused on integration patterns and offer deployable services for easy and isolated external integrations.

Besides that, none of the other two offer free, open sourced version.

How does Firebase compare to Project Darkstar?

Firebase and Project Darkstar are fundamentally different. Project Darkstar aims to solve scalable MMO's by providing a novel approach to a homogeneous but distributed model. Firebase partitions the world (through the concept of Tables). Of course there is some overlap, but generally speaking a game will naturally be a best match for one of the two.

What is the different between Firebase CE and Firebase EE.

Firebase CE (Community Edition) does not include some functionality that Firebase EE (Enterprise Edition). The most noticeable is clustering, high availability (i.e. fail over) and built in encryption support. Firebase EE is only available under a commercial license.

What type of games can I do?

Anything! 

Well, truth to be told, some games is a better match then others. Firebase was originally designed for casual and social games, which are usually turn based (e.g. poker, backgammon etc). In other words, event driven games are typically a better match than game loop based games.

However, the latency throughout the server is very low and we have successfully ported and played the incredible tense shooter Duke Bean'em (http://jsolutions.se/DukeBeanEm/) on Firebase without any noticeable lag. 

What is a Table and why do you call it that?

A Table is an isolated part of the world and what players join to play or collaborate in any fashion. It should really be called a Room (or something similar), but when we initially named all our resources we were in many ways still building a poker server, thus the name Table from a poker table.

Where can I see games running on Firebase?

Well, here is one with a Flash based client. And here is one with a C++ based client.

License

What is AGPL?

AGPL refers to the Affero GPL. You can read more about it on the Free Software Foundation site.

For all practical purposes it means that if you use our software which is under an open source license, you must under certain conditions release your software under an open source license.

Do you offer any other licenses?

We also offer a commercial license which is for developers who do not want to share the source code with others or otherwise comply with the terms of the Affero GPL license.

If you are interested in a license that does not entail AGPL, please contact us.

Where can I ask questions?

Excellent question! The forum is probably a good place to start. 

Game Development

How do I intercept players at a table?

You can allow/deny players from joining, watching or leaving a table using a so called table interceptor.

  • Implement a TableInterceptor
  • Let the Game itself implement TableInterceptorProvider
  • Return your interceptor from the game

Have a look at the manual.

Can I control table creation?

Yes. Firebase uses a concept of 'activators' to control and create tables. In short:

  • Implement a GameActivator, which schedules (using an internal thread pool) checks for tables via the table factory (available from the context), and creates/destroyes tables as needed.
  • Configure your game.xml to include "[classname]".

The manual section is here.

How do I schedule things on the server?

There's a scheduler available on each Table. Scheduled events will be delivered as game object actions to your game processor. Relevant manual section, here.  

How do I custmize login?

By writing a login handler and deploying it. Explained here.

Exactly when do I get a NotifySeated when logging in?

When you login you will get NotifySeated for table qhere you were seated, provided:

  1. You have recently been sitting at the table
  2. You have not been unseated while away
  3. Your session has not been timed out while away

For tournament tables, it gets a bit more complicated, see below.

Why don't I get a NotifySeated for my tournament tables?

You only get NotifySeated for table where you have actually occupied a seat. Consider the following:

  • A player registers for a tournament, takes his seat when the tournament start, and disconnects. Will he get a NotifySeated when he logs in? Yes, provided the restrictions above.
  • A player registers for a tournament but disconnects before the tournament starts. While he is away the tournament starts and he is allocated a seat. Will he get a NotifySeated when he logs in? No, there is a seat reserved for him, but as he has not claimed it he will get not notification.

So, how should the client handle tournament tables when connecting if it wishes to automatically open tables where the user is sitting? The answer lies in the NotifyRegistered packet which the client receives for each tournament. Then it goes something like this:

  • For each NotifyRegistered received:
    • Ask the tournament for a table and seat if the tournament is "running" (this is an implementation specific request, Firebase does not support it).
    • Given a running tournament and table and seat, check if that table is already opened (remember, you may have received a NotifySeated for this table).
    • If the table is not already open, go right ahead.

I call "destroyTable" but the table is not removed?

Tables are destroyed using the TableFactory in the game activator. This factory contains two methods:

public boolean destroyTable(int tableid, boolean force);

public boolean destroyTable(LobbyTable table, boolean force);

These methods only return true if the table was indeed removed. Note that the table will not be removed if the lobby attribute "_SEATED" in non-zero and the "force" parameter to the destroy method is false. Ie. if the factory suspects that someone is sitting at the table (indicated by the "_SEATED" lobby attribute) it will not remove the table unless explicitly told to do so by the "force" attribute.

I get "join denied" on table but the interceptor is not called?

Before the interceptor is called, the seating rules are invoked to allow/disallow the request. The default seating rules checks the following when a join request is received:

  1. Is the requested seat ID within the range of legal seat IDs, or -1?
  2. Is the player already seated, and in such case, may he reclaim the seat or take another seat?
  3. Are there any free seats?
  4. If the requested seat is not -1, is that seat vacant?

If any of the above questions can be answered "no" than the request will be denied by the seating ruls and the interceptor will never be called.

How do I read and/or write to a database?

You can either use a JDBC data source and write SQL code directly to a database. Or you can deploy a persistence archive and use JPA interfaces to serialize your data. How to deploy datasources and persistence archives is described in the development references. You get a reference to a data source like this:

Class key = DatasourceServiceContract.class; 
DatasourceServiceContract service = services.getServiceInstance(key);
DataSource ds = service.getDataSource("my_data_source_name");

If you want to use JPA you must first deploy a datasource and deploy a persistence archive. The persistence archive can either be separate (.par) or within your game archive (.gar). You can then fetch an entity manager by calling the persistence service like this:

Class key = PublicPersistenceService.class;
PublicPersistenceService service = services.getServiceInstance(key);
EntityManager em = service.getEntityManager("persistence_unit_name_here");

Currently Firebase uses Hibernate as its JPA implementation.

How do I get hold of the service registry?

Make your game implement the InitializableGame interface. Through it you'll get access to the game context through the init() method. This context contains, among other things, the service registry (GameContext.getServices()).

If you extend GameSupport you cannot implement InitializableGame. But as a replacement you can implement the interface ContextHolder, if so you will get a GameContext object injected. This context will contain an access point for the service registry (context.getServices()).

What is this serialization and transient stuff?

Every game is constantly replicated to one or more nodes in the cluster so we can provide fail over if a server should crash and burn. The data is (currently) serialized over a channel. Serializing involves the Table and everything in it including the game state. Therefore, the game state you use on the table must be serializable and be recoverable through deserializing.

Non-serialized classes (e.g. Loggers) and instances that are not absolutely needed for keeping the state of the game should be declared transient. Note that if you use GameSupport, then everything within your game is used as game state.

TODO: Explain about the default contructor and transient members.

Can I keep references to tables between events?

The short answer: No. The longer answer: No.

Tables are short-lived objects that only exists when an event is processed. Keeping, and in particular, accessing, references kept after event invokation results in unpredicted behaviour. The data kept by the tables is managed by the platform. There is currently no way of accessing it outside the events for games or services.

How can I verify that the client and the server are using the same version of the protocol(s)?

This is simple and can save you a lot of time when developing games, that would otherwise be wasted figuring out why the client or server is going crazy.

First, check the protocol manual. There, you will find Version Packet. Send this from the client (on connect) with the protocol parameter set to the version of the protocol the client is using. The version number can be found in ProtocolObjectFactory.version(). Firebase will answer with a packet with the protocol parameter set to the version that Firebase is using. Make sure to indicate clearly that something is wrong if the versions do not match. During the development, the client should probably stop immediately in this case.

Secondly, send a Game Version Packet with the game parameter set to the game id of the game in question. Firebase will return a string containing the value set by the game in the game.xml file's version tag. This must be specified by the customer and it is strongly suggested that an automatic build process is put in place that will update the version as soon as the protocol changes.

Service Development

I'm getting NoClassDefFoundError on startup. Why?

This error occurs when a class definition is not available to the class loaders at runtime. First, in order to understand class loading issues in the Firebase server, please review the developer reference as well as the export section of the service development manual.

Please keep the following in mind:

  1. If a class is exported, all of its dependencies must either be (1) exported as well; or (2) loaded in the "system" class loader (in other words, be packaged in JAR files and placed in the "lib/common" folder). This includes all method parameters and return values, as well as extended contract interfaces etc.
  2. All non-exported dependencies of a service implementation not found in the system classloader must be packaged in JAR files and placed in the 'META-INF/lib' folder of the SAR archive in order for the class loader to find them.

The best tip for avoiding this kind of confusion is this:

  • Be stringent: Export as little as possible.

Limit exporting to specialized interfaces and their helper classes only. If in doubt, place the service contract in a separate package to the implementation and use dependency checking tools at build time to enforce that classes in the service contract package must not depend on any classes outside its own package.

"java.sql.SQLException: Connections could not be acquired from the underlying database!"?

If you get the above error it's probably because of a snag: You must place your database driver JAR, for example the MySQL connector JAR, in "lib/common". This is because JDBC connections must be loaded by the system class loader.

"You have more than one version of 'org.apache.commons.logging.Log' visible, which is not allowed"? 

This occurs because the commons logging utilizes the thread context class loader, which is not currently supported by Firebase. Please refer to this Wiki page for more information.

Development Environment

When running the maven plugin in eclipse it is warning me that it is not running inside a JDK?

The dialog suggests that you have not installed a JDK and that you need to insert the vm path inside the eclipse.ini file. Please do make sure that the installed java in eclipse is a JDK however, this will most likely not fix the issue. The only working work around we have found is to include the vm flag directly when starting up eclipse.

E.g. in my windows environment I have edited the shortcut to start eclipse to look like this (target):

C:\Java\eclipse\eclipse.exe -vm C:\Java\jdk\jdk1.6.0_07\bin\javaw.exe

Firebase Administration

I'm getting OutOfMemoryExceptions on startup?

This can happen if you have large deployed archives and have customized you memory allocations in the VM. This seems to be a problem with the VM in that it fails to allocate memory fast enough during startup if the old generation size is specificly set. 

This should only occur for version 1.4.4 or earlier of the "xec-se-commons" library in the commons folder. Version 1.4.5 of the same is a drop in replacement which fixes the issue. Ie:

  1. Open the "lib/commons" folder and check what version of "xec.se-commons" you have.
  2. If you have 1.4.4, remove it and download 1.4.5 to use in it's place.
  3. If this isn't an option, please contact us for release information.

If you keep getting an OutOfMemoryException before the the server has even started try the following two startup flags. You can force Firebase to make a short delay between loading JAR files, which may help the garbage collection to keep up. This is set with the flag below, where "20" is the millisecond delay between files, which can be customized:

-Dcom.cubeia.firebase.server.deploy.forceAllocationDelay=20

You can also force the startup to do request an explicit garbage collection between each archive:

-Dcom.cubeia.firebase.server.deploy.forceAllocationGC=true

Should neither of these steps work, please contact Cubeia.

How do I start Firebase on Mac OS X?

You need to edit the "conf/config.sh" file by un-commenting and editing the two following properties:

export JAVA_HOME=/Library/Java/Home
export DISABLE_EPOLL="YES"

After which you should be able to start normally. 

This JMX thing, can you give me hints about what I ought to monitor?

Certainly, here's a primer.

Can I start several servers at the same time?

No, currently the cluster startup is required to be linear, one server at the time. Cubeia is working on making it possible to start servers in parallel but has not yet been able to put it on the road map.

My startup script only returns after 90 seconds athough the server start much quicker, why?

The default startup scripts in an installation has a "MAX_WAIT" variable set in the "config.sh" file which defaults to 90 seconds. This is the timeout after which the script will continue irregardless if it thinks the server has started or not. The script uses a notification via the log files, if the log configuration have been changed this may cause the script to misbehave, please see this page for the details.

Do I need to synchronized the time over a cluster?

In short: Yes.

Some cluster-wide functionality in Firebase use timestamps to determine timeouts and schedules. For this it is important that all involved machines have approximately the same time. We recommend that NTP/SNTP is installed on the server machines in both development and deployment environments.

Can I perform rolling updates of a cluster?

In short: Yes.

The long answer is this: Updates to a cluster can be made one server at the time, provided that the serialized form of involved Java classes have not changed. In other words, if the change involved only logic you can perform rolling updates. However, it is recommended that you try it carefully in you staging environment first.

What is configured in which file?

Firebase use two config files, "cluster.props" and "server.props". Of these "cluster.props" should only exist on designated master nodes, ie. the primary and secondary masters; It will be propagated to all other nodes from the primary master. The "server.props" file must exist on all server nodes but is kept to a minimum. Given this knowledge the following rules apply:

server.props - Main cluster comm channel (mandatory) and bind NIC/port for services (game object space, system state and message bus).
cluster.props - Everything else you can think of, node config and glubal service config.
config.sh - Startup script configuiration (linux/unix)

In other words, all the "server.props" file usually does is pointing to the main cluster comunication channel and keeping non-global service configuration such as which NIC a particular service should bind to.

How can I use JPA when running offline?

JPA's persistence.xml is usually attached to the suns online xsd. If you want to run Firebase offline with JPA you need to specify another location for the xsd. One solution is to change the persistence.xml header like below...


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence persistence_1_0.xsd"
version="1.0">

... and place a copy of the persistence_1_0.xsd in the working directory when starting the server.

I am running on Linux and get: "java.net.BindException ... /127.0.1.1 is not a valid interface"

On some Linux systems Firebase (>1.3) refuses to start and throws the following exception:

Caused by: java.net.BindException: bind_addr myhostname/127.0.1.1 
is not a valid interface

One known cause of this is the default ip configuration on Debian based systems (Ubuntu). Change the /etc/hosts file from...

127.0.0.1       localhost
127.0.1.1 myhostname

To...

127.0.0.1       localhost myhostname
127.0.1.1 myhostname

I getting FATAL ClusterConnectionService - Failed to open shared connection! 

If you are running on Linux, you must add -Djava.net.preferIPv4Stack=true as a VM argument.

 
RocketTheme Joomla Templates