SFS2X Docs / DevelopmentBasics / room-architecture
» Room architecture
The Room object is one of the most important building blocks in the structure of any multiplayer applications. It is responsible for grouping and connecting users together and make them interact with each other. From a developer's perspective it provides useful events that help building the application logic and each Room can be governed by a different server side Extension.
In this chapter we are going to dissect the many features provided by the Room object and the new powerful functionalities offered in the SFS2X framework.
» General architecture
We have introduced in other articles of this documentation a key element in SFS2X, the Room Groups:
The above diagram should clarify what these Room Groups are all about. As we can see Rooms are still all contained in the Zone and they look like they are at the "same level". This is actually the best way to represent the general structure of Room Groups: in fact a Group is just an extra ID applied to each Room which acts as a "category" thus allowing filtering and separation.
This feature allows clients to limit their local view of the entire Zone structure just to one or more groups, instead of the whole catalog. The use cases are countless: separating game Rooms of different types, creating different areas of the application, hiding certain Rooms for certain type of users, etc.
The advantages of Room grouping are that we can minimize the Room data that is transmitted to the clients and reduce the number of update events, making the application more efficient.
» Room types
SFS2X provides three types of Rooms: Regular, Game and MMO, each with a very high level of control. With the ability to set every minute detail of a Room, developers are enabled to quickly create many different behaviors, sophisticated interactions and complex structures for all kind of games.
Among the Room features in SFS2X we have the ability to rename, resize and lock/unlock each Room dynamically at runtime. Additionally we can select which events the Room will send to the clients and precisely control the Room life-cycle.
Room Variables are available to store custom data and the server side API offers advanced features to search Rooms by custom criteria, match making, challenges, invitations and lots more.
» Game Rooms
Game Rooms are a specialized type of Rooms with additional features:
- Automatic assignment of a Player ID to each player (particularly useful in turn-based games)
- Support for Players and Spectators, which are counted separately; spectators are not assigned a player ID
- By default the Game Room life cycle ends when all players leave the Room
» MMO Rooms
MMO Rooms extend the functionality of regular Rooms by adding an Area of Interest (AoI in short) to determine the range of the events that will be received by users. The AoI parameter represents the area within which users will affect each other, for example when sending public messages, updating User Variables, etc. MMO Rooms are particularly suitable for large virtual worlds where thousands of players are exploring and interacting on a vast map with minimal network overhead.
» Introducing the Room settings
In order to create a Room as described in this article, there are just a few mandatory parameters, all the others can be left to their default values if you are not interested in more advanced options.
Let's see all the available settings, which are all contained in the RoomSettings class (check the API documentation). All these settings are available on both client and server side, although on the client-side a few of them are limited to prevent malicious code from harming the server with spam or other nasty attacks.
» Basic settings
The following is the list of all the basic settings.
- name: the name of the Room, must be unique
- password: if a password is specified the Room becomes private (optional)
- maxUsers: the maximum number of users allowed in the Room (optional, default is 20)
- maxVariablesAllowed: the maximum number of Room Variables allowed in the Room (optional, default is 5)
- isGame: if the Room is going to be used for games this flag should be set to true (optional)
- maxSpectators: if this is a Game Room you should configure how many spectators are allowed inside (optional, default is 0)
- groupId: the name of the Group to assign the Room to (optional, default is "default"); check the Zone and Room architecture document for more information on Groups
» Advanced settings
The following is the list of the more advanced settings. More details are provided further on.
- autoRemoveMode: decides the life-cycle of a Room, in other words when it is going to be destroyed (optional)
- roomVariables: provide a list of Room Variables that will be added to the Room on creation (optional)
- extension: dynamically attach a server-side Extension to the Room, adding custom logic for your games (optional)
» Fine-tuning settings
The following is the list of some additional settings. More details are provided further on.
- roomSettings: allows to specify permissions and events used by the Room (optional)
- badWordsFilter: configures the bad words filtering options (optional)
- customPlayerIdGeneratorClass: allows to provide a custom class that handles the generation of playerId(s) for Game Rooms (optional)
» The Room advanced settings
» Auto-remove mode
The AutoRemoveMode option allows you to choose 4 different ways in which the Room life cycle can be handled.
- DEFAULT: this is applied by default if the setting is not provided. In this mode regular Rooms are removed when the Room is empty and it's creator is no longer logged in the Zone. Game Rooms are removed as soon as they are empty.
- WHEN_EMPTY: the Room is removed when empty.
- WHEN_EMPTY_AND_CREATOR_IS_GONE: the Room is removed when the Room is empty and its creator has logged out.
- NEVER: the Room is never removed.
NOTE #1
In order for the auto-remove feature to be active, the isDynamic flag of the Room must be set to true.
NOTE #2
The AutoRemoveMode setting is available only in the server-side API. On the client-side the DEFAULT mode is always used.
» Room Variables
Room Variables are a useful tool to store custom data in a Room to maintain application state. These variables are automatically synchronized between all users in the Room, making it a powerful tool to quickly change game states, scores and other values that are propagated to all players.
The SFS2X API also provide several settings to control the access, life cycle and visibility of each Room Variable. Let's see each property of a RoomVariable in detail.
- name: the unique name of the variable
- isPrivate: if set, the R.V. can only be modified or deleted exclusively by its creator (optional, default is false)
- isPersistent: by default a user created R.V. is removed from the Room when the user leaves it. If this flag is turned on, the R.V. will persist until the user logs out or disconnects (optional, default is false)
- isGlobal: by default R.V. updates are sent to all users in the Room. A global R.V. is also updated outside of the Room to all users in the same Room Group (optional, default is false)
- isHidden: if set the R.V. will be available on the server side only and never transmitted on the client side (optional, default is false)
- value: the value of the R.V. The following types are supported:
- Boolean
- Integer
- Double
- String
- SFSObject
- SFSArray
- Null (this is not a type of course, but it is worth mentioning it because it is used to delete a R.V; in fact when an R.V. is set to null it is removed from the Room)
On the client side, setting Room Variables in the currently joined Room is straightforward:
// Create a list of Room Variables List<RoomVariable> listOfVars = new List<RoomVariable>(); // Add some basic values listOfVars.Add(new SFSRoomVariable("bgImage", "coolBackground.jpg")); listOfVars.Add(new SFSRoomVariable("stars", 4)); // Add a nested object ISFSObject chatSettings = new SFSObject(); chatSettings.PutUtfStringArray("allowedFonts", new string[] {"Verdana", "Arial", "Times New Roman"}); chatSettings.PutIntArray("allowedFontSizes", new int[] {10, 11, 12, 13}); chatSettings.PutBool("isBoldAllowed", true); chatSettings.PutBool("isItalicAllowed", true); chatSettings.PutBool("isUnderlineAllowed", false); listOfVars.Add(new SFSRoomVariable("settings", chatSettings)); // Send the request to set Room Variables sfs.Send(new Sfs2X.Requests.SetRoomVariablesRequest(listOfVars));
// Create a list of Room Variables var listOfVars = []; // Add some basic values listOfVars.push(new SFS2X.SFSRoomVariable("bgImage", "coolBackground.jpg")); listOfVars.push(new SFS2X.SFSRoomVariable("stars", 4)); // Add a nested object var chatSettings = new SFS2X.SFSObject(); chatSettings.putUtfStringArray("allowedFonts", ["Verdana", "Arial", "Times New Roman"]); chatSettings.putIntArray("allowedFontSizes", [10, 11, 12, 13]); chatSettings.putBool("isBoldAllowed", true); chatSettings.putBool("isItalicAllowed", true); chatSettings.putBool("isUnderlineAllowed", false); listOfVars.push(new SFSRoomVariable("settings", chatSettings)); // Send the request to set Room Variables sfs.send(new SFS2X.SetRoomVariablesRequest(listOfVars));
// Create a list of Room Variables var listOfVars:Array = new Array(); // Add some basic values listOfVars.push(new SFSRoomVariable("bgImage", "coolBackground.jpg")); listOfVars.push(new SFSRoomVariable("stars", 4)); // Add a nested object var chatSettings:SFSObject = new SFSObject(); chatSettings.putUtfStringArray("allowedFonts", ["Verdana", "Arial", "Times New Roman"]); chatSettings.putIntArray("allowedFontSizes", [10, 11, 12, 13]); chatSettings.putBool("isBoldAllowed", true); chatSettings.putBool("isItalicAllowed", true); chatSettings.putBool("isUnderlineAllowed", false); listOfVars.push(new SFSRoomVariable("settings", chatSettings)); // Send the request to set Room Variables sfs.send(new SetRoomVariablesRequest(listOfVars));
On the server side it is possible to create Room Variables that are owned by the SmartFoxServer instance itself. This is like a "virtual user" that never leaves the system thus allowing to create Room Variables that are never removed. In order to do so you need to pass a null as the owner of the variable.
This is a quick example showing how to set Room Variables in a server side Extension:
private void setSomeVariables(Room room) { // Create a list of Room Variables List<RoomVariable> listOfVars = new ArrayList<RoomVariable>(); // Add some basic values listOfVars.add(new SFSRoomVariable("bgImage", "coolBackground.jpg")); listOfVars.add(new SFSRoomVariable("stars", 4)); // Add an hidden Room Variable RoomVariable hiddenVar = new SFSRoomVariable("isPremiumUsersOnly", true); hiddenVar.setHidden(true); listOfVars.add(hiddenVar); // Set the Room Variables getApi().setRoomVariables(null, room, listOfVars); }
As you can see the Room Variable called hiddenVar is marked as hidden and it will not be transmitted to the client. The server side code will be able to check it and see if the Room is for premium users only.
» Server-side Extension
A server side Extension can be dynamically plugged into the Room upon creation. This enables the developer to attach custom logic to the Room and control its usage. Typically this is used for running games, enabling advanced moderation controls, filtering messages and tons more.
For a full discussion on Extensions please make sure to consult the server side Extensions documentation for Java or JavaScript.
» The Room fine-tuning settings
» Permissions and Events
In SmartFoxServer 2X you have full control over the events fired by each Room.
This is an example from the Room configuration in the Administration Tool:
The above interface shows how you can fine tune each Room-level permission and event when creating a new Room. According to the above configuration users will be able to send public messages, while Room resizing (capacity change) and Room name and password changing will be denied. All available events will be notified too. In another Room you may want to configure these settings differently, suppressing some of the events and providing a different set of permissions.
Rooms provide two categories of settings: Permissions and Events.
Permissions indicate which Room-related operations can be executed at runtime:
- ROOM_NAME_CHANGE: toggles the ability of the Room creator to change the Room name at runtime
- PASSWORD_STATE_CHANGE: toggles the ability of the Room creator to add, remove or modify the Room password
- PUBLIC_MESSAGES: toggles the ability to send public messages
- CAPACITY_CHANGE: toggles the ability of the Room creator to resize the Room at runtime. It is possible to "shrink" the Room capacity so that maxUsers < users count: in this case nothing will happen to the "extra" users. As soon as clients will leave the Room the user count will get down to the new maxUsers value
Events indicate which events the Room will notify to the joined clients:
- USER_ENTER_EVENT: toggles the notification of a new user joining the Room (default is true)
- USER_EXIT_EVENT: toggles the notification of a user leaving the Room (default is true)
- USER_COUNT_CHANGE_EVENT: toggles the notification of user and spectator count for all Rooms in the subscribed groups (default is true)
- USER_VARIABLES_UPDATE_EVENT: toggles the notification of User Variable updates (default is true)
The USER_COUNT_CHANGE_EVENT event is one of the most bandwidth-eating notifications under heavy traffic. SmartFoxServer provides a couple of engine-level optimizations that reduce its impact by a large degree.
- Packet Priority: the SmartFoxServer 2X engine allows to specify a priority level for each packet, allowing low-priority responses such as the user count change event to be discarded if the client queue is getting too busy. This significantly reduces the dropped-messages problem when the client is using a slow connection.
- User Count Event Throttling: to further increase the level of control over this event SmartFoxServer 2X can be configured to "slow down" the pace at which these updates are sent by aggregating the messages and only sending the significant ones. In other words you are able to specify the interval of time after which the event should be fired. All updates between two intervals will be aggregated discarding the stale ones.
The default is real-time; in order to save bandwidth you might want to reduce these updates to 1 time per second or less. Check the Zone Configurator in the AdminTool for more on this.
NOTE #2
Turning off USER_ENTER and USER_EXIT events will stop Public / Private Messages from working correctly. You can still communicate via Buddy messages.
NOTE #3
The USER_ENTER and USER_EXIT events should always be used in conjunction. If you decide to turn one of them off the other should also be set in the same way as they are two sides of the same notification.
» Removal mode
Rooms have a way of defining their removal mode, which indicates if and when the Room should be auto-removed (destroyed). The following settings are available:
- Default: regular Rooms are removed when empty and the creator goes offline; game Rooms will be removed when empty
- When_Empty: the Room is removed when it is empty
- When_Empty_And_Creator_Is_Gone: the Room is removed when empty and its creator goes offline
- Never_Remove: the Room is never auto-removed
» Bad words filter
If a Words Filter is configured at the Zone level, developers are be able to apply it to public messages exchanged in the Room.
» Player ID generator
Finally, for very advanced game logic, developers can provide an alternative PlayerId Generator class that uses custom code to handle and distribute player IDs in the Room. The class is required to implement the com.smartfoxserver.v2.util.IPlayerIdGenerator class provided in the SFS2X server-side API.
» More resources
If you want to learn more details about the many aspects we have presented in this overview we suggest these articles: