In this new article we are going to a take a closer look at a simple concept, that of MatchExpressions within the SmartFoxServer SDK, and discuss why they are useful and how they can simplify our life when developing multiplayer games.
» What is a MatchExpression
MatchExpressions are used to create conditional statements that can be applied as filters in various operations. For example searching for Users or Rooms in the server, with any number of parameters, akin to a SQL statement for filtering records from a database.
Interestingly, when we filter Rooms or Users via a MatchExpression we can not only use the default fields exposed by these objects but also apply it to any user-created variable, such as RoomVariables for Rooms and UserVariables for Users.
Let’s see a practical example. Suppose we have any number of game Rooms with these custom RoomVariables attached to them:
- country (String) -> indicates a game for a specific country / language
- type (String) -> indicates the game type
- level (int) -> indicates the player’s level required to play (e.g. 0 = beginner, 1 = pro, 2 = veteran)
We want to search for a game of type “Chess”, in the country of Japan for a beginner player. This is how we could build our expression:
final int LEVEL_ROOKIE = 0; final int LEVEL_PRO = 1; final int LEVEL_VETERAN = 2; MatchExpression exp = new MatchExpression('type', StringMatch.EQUALS, 'Chess') .and('level', NumberMatch.LESS_THAN, LEVEL_PRO) .and('country', StringMatch.EQUALS, 'Japan')
When can then pass this expression to the SmartFox’s API and obtain a list of all Rooms matching these conditions:
List<Rooms> roomList = sfsApi.findRooms(zone.getRoomList(), exp, 0);
» MatchExpressions as Room gateways
Another interesting use of Match Expressions is to filter out users that want to join a certain Room. The SmartFoxServer’s SDK provides a class of Rooms called SFSGame which allows to specify a custom MatchExpression for both players and spectators.
This means that SFSGame Rooms will automatically deny a client JoinRequest from every User that doesn’t match the criteria provided in those expressions.
The MatchExpressions can be attached to any SFSGame at creation time. For example:
CreateSFSGameSettings settings = new CreateSFSGameSettings(); ... ... // Prepare MatchExpression MatchExpression playerExp = new MatchExpression('country', StringMatch.EQUALS, 'Japan').and('level', NumberMatch.GREATER_THAN, 0); // Attach it to Room definition settings.setPlayerMatchExpression(playerExp); // Create Room sfs.getAPIManager().getGameApi().createGame ( getParentZone(), settings, null );
We highly recommend this approach to add custom join filtering to a Room without the need to add any extra server side logic or intercepting specific server calls. Additionally these MatchExpressions can be setup from both client and server side.
» Additional fields beyond Variables
In the examples presented so far we have shown MatchExpressions targeting custom RoomVariables or UserVariables. Sometimes, however, we will need to query specific properties of a Room or User that are not stored as Server Variables.
For instance we might want to query the size of a Room, the number of spectators in it, if it’s private or public etc… Similarly we may want to check if a User is a player or spectator, or if his name matches a certain pattern etc…
For this task we can use two convenient classes (available from in both server side and client API) called UserProperties and RoomProperties, which contain fields such as:
and lot’s more. This is an example for finding all empty game Rooms for the game type ‘Poker’.
new MatchExpression('type', StringMatch.EQUALS, 'Poker') .and(RoomProperties.USER_COUNT, NumberMatch.EQUALS, 0);
Here’s a more advanced example filtering all public game Rooms with free player slots for the game type ‘Chess’:
new MatchExpression('type', StringMatch.EQUALS, 'Chess') .and(RoomProperties.HAS_FREE_PLAYER_SLOTS, BoolMatch.EQUALS, true); .and(RoomProperties.IS_PRIVATE, BoolMatch.EQUALS, false);
» More usages and documentation
The usage of MatchExpressions doesn’t end here. We can use them in conjunction with the Game API to perform a QuickJoin, where the user is sent to play in the first Room matching the provided Expression.
Also we can use “dot syntax” to dig into complex nested SFSObjects and SFSArrays stored as variables in Users and Rooms. For example:
new MatchExpression("europe.italy.capital", StringMatch.EQUALS, "Rome")
will search into a Room/User Variable called “europe”, containing a field called “italy”, containing a field called “capital” and match it against the provided parameter.