userExit event dispatched in too many extensions

Post here your questions about Actionscript and Java server side extensions development.

Moderators: Lapo, Bax

LeperMessiah
Posts: 6
Joined: 19 Oct 2011, 07:55
Location: Slovenia
Contact:

userExit event dispatched in too many extensions

Postby LeperMessiah » 19 Oct 2011, 09:00

Hi all :) I'm new to this forum and I have a problem with java extensions in SFS.

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! :)
Sarevok
Posts: 75
Joined: 12 Apr 2011, 22:12

Postby Sarevok » 19 Oct 2011, 10:24

Is main lobby extension a zone level extension? There was similar discussion in the following thread: http://www.smartfoxserver.com/forums/viewtopic.php?t=12472.

You can read it near the end of page 1. Seems like server forward all events to the zone level extension. So if you use zone level extension to manage your lobby, it will get events from other extensions.

You can avoid this by setting your lobby extension to be on room level, not on zone level. For example, zone level extension will only process user login, and it will join user into Main lobby, which is managed by MainLobbyExtension that is set as room level extension.

Try if that works for you. I am not 100% sure that it is default server behavior to sent all events from other extensions to zone extension, but you are the second person with that problem in just a few days :)
Sarevok
Posts: 75
Joined: 12 Apr 2011, 22:12

Postby Sarevok » 19 Oct 2011, 10:37

p.s. I just saw you are from Slovenia, and your lobby layout reminds me a lot on igrajmo.se game portal. Any connection or it is just coincidence? :P
LeperMessiah
Posts: 6
Joined: 19 Oct 2011, 07:55
Location: Slovenia
Contact:

Postby LeperMessiah » 19 Oct 2011, 11:30

No coincidence, it is igrajmo.se. Props for noticing it! :D

Thanks for your answer. Your solution seems worthy of trying :) Though I would still prefer if there is an option to prevent forwarding those events to the zone level. Any idea how to do that?
Sarevok
Posts: 75
Joined: 12 Apr 2011, 22:12

Postby Sarevok » 19 Oct 2011, 12:01

I am not sure if it is possible to prevent that. The only way that I know of limiting event triggering in SFS 1.6.9 is by using certain type of rooms. For example you use limbo room if you don't want user join/exit events to be received.

But I am not sure how did you set up your config file. For example, lets say you have Main Lobby room of limbo type defined in the config.xml, and you have extension named MainLobbyExtension defined as zone level extension in config file. You probably could attach MainLobbyExtension to Main lobby room in order to try to prevent getting user join/exit events, since main lobby is limbo room. But the question now is whether smartfox will have two ZoneExtension instances now (one associated with main lobby, and another "general" one), or just one? If there are two of them, you are again at beginning :)

Aside from that, I think it is better design to separate MainLobby extension from user logging task. It is more natural if MainLobbyExtension is responsible only for what is going on in MainLobby room. That is why I think it should not be zone level extension. That would give you better separation of your object responsibilities and would solve your problem at same time :)

Zone level extension would just have "think" about user login tasks, and even if it receives all kind of events from server, you just ignore them :)

If there is a way to prevent forwarding events to zone extension, I am not aware of it, and would like to know the answer as much as you :)
LeperMessiah
Posts: 6
Joined: 19 Oct 2011, 07:55
Location: Slovenia
Contact:

Postby LeperMessiah » 19 Oct 2011, 12:37

You have a point there :) Thankfully the server I'm working on is still in the design phase, so it doesn't require much effort to redesign it a bit, to try any new solutions. Thanks for your replies, they were much appreciated! :)

Return to “Server Side Extension Development”

Who is online

Users browsing this forum: No registered users and 46 guests