AutoJoiner Extension

In this recipe we will see how we can create a simple Extension that automatically joins users in an available Room and creates more Rooms when the seats are all occupied.

Detecting which Room has currently available seats from client side is not always accurate because by the time a client chooses to join a certain Room other users might have joined concurrently.

To avoid errors and unexpected join failures we can move the joining logic on the server side. Our Extension will scan through the available Rooms, find one that has one or more free spots and join the client. If all Rooms are occupied the Extension will create a new Room and join the user subsequently.

Here is the code of the AutoJoiner extension:

import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

import com.smartfoxserver.v2.api.CreateRoomSettings;
import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.smartfoxserver.v2.exceptions.SFSCreateRoomException;
import com.smartfoxserver.v2.exceptions.SFSException;
import com.smartfoxserver.v2.exceptions.SFSJoinRoomException;
import com.smartfoxserver.v2.extensions.ExtensionLogLevel;
import com.smartfoxserver.v2.extensions.SFSExtension;

public class AutoJoinerExtension extends SFSExtension
{
	private final String version = "1.0.1";

	private final AtomicInteger roomId = new AtomicInteger();

	@Override
	public void init()
	{
		trace("Java AutoJoiner: " + version);
	}

	@Override
	public void handleClientRequest(String cmd, User user, ISFSObject params)
	{
		try
		{
			if (cmd.equals("joinMe"))
				joinUser(user);
		}
		catch(Exception err)
		{
			trace(ExtensionLogLevel.ERROR, err.toString());
		}
	}

	private void joinUser(User user) throws SFSException
    {
	    List<Room> rList = getParentZone().getRoomList();
	    Room theRoom = null;

	    for (Room room : rList)
	    {
	    	if (room.isFull())
	    		continue;
	    	else
	    	{
	    		theRoom = room;
	    		break;
	    	}
	    }

	    if (theRoom == null)
	    	theRoom = makeNewRoom(user);

	    try
	    {
	    	getApi().joinRoom(user, theRoom);
	    }
	    catch (SFSJoinRoomException e)
	    {
	    	trace(ExtensionLogLevel.ERROR, e.toString());
		}
    }

	private Room makeNewRoom(User owner) throws SFSCreateRoomException
    {
		Room room = null;

		CreateRoomSettings rs = new CreateRoomSettings();
		rs.setGame(false);
		rs.setDynamic(true);
		rs.setName("ChatRoom_" + roomId.getAndIncrement());
		rs.setMaxUsers(50);

		room = getApi().createRoom(getParentZone(), rs, owner);
		return room;
    }
}

The code will search through all available Rooms for a free slot and in case none is found it will create a new Room with 50 free slots.

From client side all we need to do is sending a “joinMe” Extension request, after having logged in. Like this:

// Tell the server to join me...
sfs.send(new ExtensionRequest("joinMe"));

where sfs is the client API instance.