Skip to content

Custom Room Storage

The Room Persistence API provide a file-based and a database-based storage mechanism that can be used to save the state of multiple active Rooms. However the API also allow to plug in custom storage systems as well.

In this short article we’ll demonstrate how to create a custom storage class to save Room state in your own format.

The basics

In our introductory article we show how to initialize the API in your Extension’s init() method:

@Override
public void init()
{
    //Initialize Persistence API
    getParentZone().initRoomPersistence(RoomStorageMode.FILE_STORAGE, new FileRoomStorageConfig());

    //...
}

It’s a simple one-line call to the Zone’s initRoomPersistence() method, where we provide the RoomStorageMode and relative configuration object.

RoomStorageMode provides the following options: - FILE_STORAGE - DB_STORAGE - CUSTOM

The latter allows us to use a custom implementation of the IRoomStorage interface.

Three simple steps

To get started with the development of a custom storage class we need three elements:

  • an implementation of the IRoomStorage interface
  • a configuration object extending BaseStorageConfig
  • one line in the Extension’s main init() method to set it all up

Implementing IRoomStorage

The interface looks like this:

void destroy()
void init(Zone zone, BaseStorageConfig cfg)

void saveRoom(Room theRoom) throws SFSStorageException
void saveAllRooms() throws SFSStorageException
void saveAllRooms(String groupId) throws SFSStorageException
CreateRoomSettings loadRoom(String name) throws SFSStorageException
List<CreateRoomSettings> loadAllRooms() throws SFSStorageException
List<CreateRoomSettings> loadAllRooms(String groupId) throws SFSStorageException

void removeRoom(String name) throws SFSStorageException
void removeAllRooms() throws SFSStorageException
void removeAllRooms(String groupId) throws SFSStorageException

Essentially there are an init() and destroy() method that manage the life cycle of the object, allowing to create and dispose of useful resources. Then we have the load, save and remove methods each with three variants, depending if we're dealing with a single Room, a selection of Rooms or all the Rooms.

Create a configuration object

Next we need a configuration object that can be populated with settings for our Storage logic. For instance if we were to read and write from a database we’d need a connection string to reach the DB server and probably a database name and table name.

The base class for our configuration object is called BaseStorageConfig and comes pre-populated with a few global settings:

public class BaseStorageConfig
{
    public boolean storeInactiveRooms = false;
    public boolean storeRoomVariables = true;
    public boolean skipStaticRooms = true;
    public String customStorageClassName;
}

Continuing with the example of a DB-based storage here’s how one could extend the class:

public class MyDBStorageConfig extends BaseStorageConfig
{
    public String connectionString;
    public String driverName;
    public String databaseName;
    public String tableName;
}

Please Note

Keep in mind that your custom Storage logic should honor the settings contained in the base class. In other words it should check the values of the base class’ flags and filter out the relative data accordingly.

Putting it all together

In order for SmartFoxServer to load the custom classes they will need to be visible in the system Class Loader. To do so we'll need to make a jar file of the custom Storage classes and deploy it under server/lib/extra/

Next we move in our Extension and initialize the Room Persistence API as follows:

public class CustomRoomStorageExtension extends SFSExtension
{
    @Override
    public void init()
    {
        MyDBStorageConfig config = new MyDBStorageConfig();
        config.param1 = ...
        config.paramX = ...
        config.customStorageClassName = "my.sfs3.game.MyRoomStorage";

        getParentZone().initRoomPersistence(RoomStorageMode.CUSTOM, config);
    }
}

Notice the customStorageClassName property: we must provide the fully qualified name of the IRoomStorage implementation.

A complete example

To help you build a custom Room Storage class we have included the source code for our file-based Room Storage so you can look at an existing implementation.

Download the FileRoomStorage class