Our server consists of a single zone. This zone contains one (auto join) room (we call it the main lobby) in which all users are joined and serves for general tasks such as private chat between users, private messages, ... Beside this room we have several other rooms. These rooms are represented as lobbies for each game. So for example if we have 10 games, we will have 11 rooms - 10 rooms for each game lobby and 1 room for general tasks. I hope I made myself clear up till now
So the basic idea is that user is always joined in main lobby room. He can also be joined in only one game lobby room. Here is an excerpt from our code, that handles expected behavior.
First the main lobby extension (zone extension):
Code: Select all
public class MainLobby extends AbstractExtension
{
private SmartFoxServer sfs;
private ExtensionHelper eh;
private Zone zone;
private HashMap<String, Lobby> lobbies;
@Override
public void init()
{
sfs = SmartFoxServer.getInstance();
eh = ExtensionHelper.instance();
zone = sfs.getZone(getOwnerZone());
lobbies = new HashMap<String, Lobby>();
lobbies.put("game1", new Lobby("game1",zone,eh));
lobbies.put("game2", new Lobby("game2",zone,eh));
}
@Override
public void handleRequest(String cmd, String params[], User u, int fromRoom)
{
JSONObject jso = getJSON(params[0]); // this method is not essential for this example, so it's not included in the code
String command = jso.getString("c");
JSONObject data = jso.getJSONObject("o");
if(command.equals("joinLobby"))
{
String name = data.getString("name");
Lobby lobby = lobbies.get(name);
responseObj = lobby.addUser(u);
}
else if(command.equals("leaveLobby"))
{
String name = data.getString("name");
Lobby lobby = lobbies.get(name);
responseObj = lobby.removeUser(u);
}
}
@Override
public void handleInternalEvent(InternalEventObject ieo)
{
String eventName = ieo.getEventName();
System.out.println("[MainLobby] :: internal event:" + eventName);
if(eventName.equals(InternalEventObject.EVENT_LOGIN))
{
User user = null;
try
{
user = sfs.canLogin(nick, pass, chan, zone);
}
catch(LoginException e)
{
e.printStackTrace();
}
// Auto join room
if(user != null)
{
try
{
eh.joinRoom(user, -1, this.zone.getAutoJoinRoom(), false, null, false, false);
}
catch(ExtensionHelperException e)
{
e.printStackTrace();
}
}
}
}
}
Game lobby class (creates new room):
Code: Select all
public class Lobby
{
private String name;
private Zone zone;
private Room room;
private ExtensionHelper eh;
public Lobby(String name, Zone zone, ExtensionHelper eh)
{
this.name = name;
this.zone = zone;
this.eh = eh;
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("name", name);
params.put("maxU", "1000000");
params.put("isGame", "false");
params.put("isLimbo", "true");
params.put("xtName", name+"Ex");
params.put("xtClass", "lobby.extensions.LobbyExtension");
try
{
room = this.eh.createRoom(zone, params, null, true, true);
}
catch(ExtensionHelperException e)
{
e.printStackTrace();
}
}
public void addUser(User u)
{
try
{
eh.joinRoom(u, u.getRoom(), room.getId(), false, null, false, true);
}
catch(ExtensionHelperException e)
{
e.printStackTrace();
}
}
public void removeUser(User u)
{
eh.leaveRoom(u, room.getId(), true);
}
}
Extension for room, created in Lobby class:
Code: Select all
public class LobbyExtension extends AbstractExtension
{
@Override
public void init()
{
}
@Override
public void handleRequest(String cmd, ActionscriptObject ao, User u, int fromRoom)
{
System.out.println("[LobbyExtension] :: handleRequest(XML)");
}
@Override
public void handleRequest(String cmd, String params[], User u, int fromRoom)
{
System.out.println("[LobbyExtension] :: handleRequest(RAW)");
}
@Override
public void handleInternalEvent(InternalEventObject ieo)
{
String eventName = ieo.getEventName();
System.out.println("[LobbyExtension] :: internal event:" + eventName);
}
}
So now, where the problem is... When user logs in, he is automatically joined in the main lobby room. After that, he sends the joinLobby command, to join the game lobby. In the Lobby class he is joined in the room, that was created in that class. So far, so good. But when user sends the leaveLobby command to leave the game lobby, he is removed from the room created in Lobby class. But... userExit event is dispatched both in MainLobby and LobbyExtension classes! Besides that userLost event is dispatched in MainLobby class, so user is logged out (logout procedure is not included in the code).
I would expect that if user is removed from the room in Lobby class, userExit event would be dispatched only in LobbyExtension class and not in MainLobby class. So can someone please help me with this problem and how to solve it so that SFS would behave as expected?
Kind regards!