SFS2X Docs / AdvancedTopics / buddy-list-api
» The Buddy List API
SmartFoxServer 2X provides a set of client and server API specifically designed for managing Buddies and Buddy Lists including persistence, custom states, ability to go online/offline in the Buddy system, runtime and persistent Buddy Variables, server side events and more.
» Features
The following is a rapid overview of the features in the framework:
- Online status: the online state is completely under the control of the developer. Any user can go online and offline in the Buddy system while still being logged in a Zone. Additionally the online state is persistent, so the next time a user will log in again he will be in the same online/offline status as when he left during the previous session.
- Custom states: states are custom Strings that are defined in the Zone configuration and can be used to notify the current Buddy "mode". Examples could be: "Available", "Chat with me", "Play with me", "Occupied", "Be right back", etc. These states should be configured from server side. They will be sent to each client together with the initial BuddyList, after sending an InitBuddyListRequest from client or server.
- Nickname: an additional nickname is supported by the Buddy List for every Buddy. This is handled via Buddy Variables and stored persistently.
-
Buddy Variables: Buddy Variables represent data attached to buddies; they support different data types (Bool, Integer, Double, String) as well as nested objects (SFSObject/SFSArray) just like the other User/Room Variable counterparts.
Buddy variables support persistence via a simple naming convention. Any variable name starting with a dollar sign ($) is automatically persisted via the configured storage mechanism (default = local file system). All persistent variables are available to other buddies even when the owner is offline. - Buddy Messages: instead of using private messages, buddies can use a new specific type of message called the BuddyMessage. This is better integrated in the Buddy List system and embeds the logic for handling blocked Buddies... without "polluting" the generic public/private message which are Buddy agnostic. It is strongly recommended to use Buddy Messages for any communication between Buddies.
-
Temp Buddies: temporary Buddies have been introduced to handle the following common scenario:
- User Gonzo adds User Piggy to his buddy list
- Gonzo sends a message to Piggy
- Piggy receives the message but she knows nothing about Gonzo.
- Gonzo is then added as temp Buddy in Piggy’s list. This means that the Buddy will be transient and it won't be saved, unless Piggy goes ahead and calls addBuddy(‘Gonzo’).
- Server side events: the Buddy API provides many useful new events on the server side that can be used in your Extension to handle specific situations: BUDDY_ADD, BUDDY_REMOVE, BUDDY_BLOCK, BUDDY_VARIABLES_UPDATE, BUDDY_ONLINE_STATE_UPDATE, BUDDY_MESSAGE, BUDDY_LIST_INIT.
» Buddy List Client API
Adding Buddies
Adding a new buddy to the current User is pretty straightforward (sfs is the SmartFox class instance):
... // Add buddy-related event listeners during the SmartFox instance setup sfs.AddEventListener(SFSBuddyEvent.BUDDY_ADD, OnBuddyAdded); sfs.AddEventListener(SFSBuddyEvent.BUDDY_ERROR, OnBuddyError); ...
private void SomeMethod() { // Add Kermit as a new buddy in your buddy list sfs.Send(new Sfs2x.Requests.Buddylist.AddBuddyRequest("Kermit")); }
private void OnBuddyAdded(BaseEvent evt) { Console.WriteLine("Buddy added: " + (Buddy)evt.Params["buddy"]); } private void OnBuddyError(BaseEvent evt) { Console.WriteLine("BuddyList error: " + (string)evt.Params["errorMessage"]); }
... // Add buddy-related event listeners during the SmartFox instance setup sfs.addEventListener(SFS2X.SFSBuddyEvent.BUDDY_ADD, onBuddyAdded, this); sfs.addEventListener(SFS2X.SFSBuddyEvent.BUDDY_ERROR, onBuddyError, this); ...
function someMethod() { // Add Kermit as a new buddy in your buddy list sfs.send(new SFS2X.AddBuddyRequest("Kermit")); }
function onBuddyAdded(evt) { console.log("Buddy added: " + evt.buddy.name); } function onBuddyError(evt) { console.warn("BuddyList error: " + evt.errorMessage); }
... // Add buddy-related event listeners during the SmartFox instance setup sfs.addEventListener(SFSBuddyEvent.BUDDY_ADD, onBuddyAdded); sfs.addEventListener(SFSBuddyEvent.BUDDY_ERROR, onBuddyError); ...
private function someMethod():void { // Add Kermit as a new buddy in your buddy list sfs.send(new AddBuddyRequest("Kermit")); }
private function onBuddyAdded(evt:SFSBuddyEvent):void { trace("Buddy added: ", evt.params.buddy.name); } private function onBuddyError(evt:SFSBuddyEvent):void { trace("BuddyList error: " + evt.params.errorMessage); }
Setting Buddy Variables
Buddy Variables can be set as follows:
... // Add buddy-related event listeners during the SmartFox instance setup sfs.AddEventListener(SFSBuddyEvent.BUDDY_VARIABLES_UPDATE, OnBuddyVarsUpdate); ...
// Set two Buddy Variables BuddyVariable bVar1 = new SFSBuddyVariable("avatarPic", "kermit-avatar,jpg"); BuddyVariable bVar2 = new SFSBuddyVariable("color", "green"); List<BuddyVariable> bVars = new List<BuddyVariable>(); bVars.Add(bVar1); bVars.Add(bVar2); sfs.Send(new Sfs2x.Requests.Buddylist.SetBuddyVariablesRequest(bVars));
private void OnBuddyVarsUpdate(BaseEvent evt) { Buddy buddy = (Buddy)evt.Params["buddy"]); bool isItMe = (bool)evt.Params["isItMe"]; List<string> changedVars = (List<string>)evt.Params["changedVars"]; if (isItMe) { Console.WriteLine("I've updated the following Buddy Variables:"); for (int i = 0; i < changedVars.Count; i++) { string bVarName = changedVars[i]; Console.WriteLine(bVarName + " --> " + sfs.BuddyManager.GetMyVariable(bVarName).Value()); } } else { string buddyName = buddy.Name; Console.WriteLine("My buddy " + buddyName + " updated the following Buddy Variables:"); for (int i = 0; i < changedVars.Count; i++) { var bVarName:String = changedVars[i]; Console.WriteLine(bVarName + " --> " + sfs.BuddyManager.GetBuddyByName(buddyName).GetVariable(bVarName).Value()); } } }
... // Add buddy-related event listeners during the SmartFox instance setup sfs.addEventListener(SFS2X.SFSBuddyEvent.BUDDY_VARIABLES_UPDATE, onBuddyVarsUpdate, this); ...
// Set two Buddy Variables var bVar1 = new SFS2X.SFSBuddyVariable("avatarPic", "kermit-avatar,jpg"); var bVar2 = new SFS2X.SFSBuddyVariable("color", "green"); sfs.send(new SFS2X.SetBuddyVariablesRequest([bVar1, bVar2]));
function onBuddyVarsUpdate(evt) { var isItMe = evt.isItMe; if (isItMe) { console.log("I've updated the following Buddy Variables:"); for (var i = 0; i < evt.changedVars.length; i++) { var bVarName = evt.changedVars[i]; console.log(bVarName + " --> " + sfs.buddyManager.getMyVariable(bVarName).value); } } else { var buddyName = evt.buddy.name; console.log("My buddy " + buddyName + " updated the following Buddy Variables:"); for (var i = 0; i < evt.changedVars.length; i++) { var bVarName = evt.changedVars[i]; console.log(bVarName + " --> " + sfs.buddyManager.getBuddyByName(buddyName).getVariable(bVarName).value); } } }
... // Add buddy-related event listeners during the SmartFox instance setup sfs.addEventListener(SFSBuddyEvent.BUDDY_VARIABLES_UPDATE, onBuddyVarsUpdate); ...
// Set two Buddy Variables var bVar1:BuddyVariable = new SFSBuddyVariable("avatarPic", "kermit-avatar,jpg"); var bVar2:BuddyVariable = new SFSBuddyVariable("color", "green"); sfs.send(new SetBuddyVariablesRequest([bVar1, bVar2]));
private function onBuddyVarsUpdate(evt:SFSBuddyEvent):void { var isItMe:Boolean = evt.params.isItMe; if (isItMe) { trace("I've updated the following Buddy Variables:"); for (var i:int = 0; i < evt.params.changedVars.length; i++) { var bVarName:String = evt.params.changedVars[i]; trace(bVarName, "-->", sfs.buddyManager.getMyVariable(bVarName).getValue()); } } else { var buddyName:String = evt.params.buddy.name; trace("My buddy " + buddyName + " updated the following Buddy Variables:"); for (var i:int = 0; i < evt.params.changedVars.length; i++) { var bVarName:String = evt.params.changedVars[i]; trace(bVarName, "-->", sfs.buddyManager.getBuddyByName(buddyName).getVariable(bVarName).getValue()); } } }
» Buddy List Server API
The server side API offer a very similar interface to manipulate buddy lists.
Getting the Buddy API
All Buddy List-related commands are found in the ISFSBuddyApi object.
SmartFoxServer sfs = SmartFoxServer.getInstance(); ISFSBuddyApi buddyApi = sfs.getAPIManager().getBuddyApi();
Adding Buddies to a User
This simple example will add a Buddy to the User and notify the client:
// This will add the User "Piggy" in the list of buddies for User "Kermit" buddyApi.addBuddy(getParentZone(), "Kermit", "Piggy");
Setting Buddy Variables
Now let's see how to set a Buddy Variable:
// 1. Get a reference to the Owner of the BuddyList User owner = getParentZone().getUserByName("Kermit"); // 2. Create a list of variables List<BuddyVariable> vars = new ArrayList<BuddyVariable>(); vars.add( new SFSBuddyVariable("$avatarPic", "kermit-avatar.jpg") ); vars.add( new SFSBuddyVariable("color", "green") ); // 3. Set the variables and dispatch a client side event buddyApi.setBuddyVariables(owner, vars);
Notice how the first variable name starts with a dollar sign ($) marking the variable persistent. This means that "$avatarPic" is stored locally and available across multiple sessions while the "color" variable exists only until the current user session ends (i.e. upon disconnection).
For more details about the BuddyAPI we recommend consulting the server side javadoc.
» Buddy List persistence
The Buddy List persistence is delegated to an implementation of the BuddyStorage interface found under the com.smartfoxserver.v2.buddylist.storage package. This is the skeleton of the interface:
void init(); void destroy(); BuddyList loadList(String ownerName) throws SFSBuddyListNotFoundException, IOException; void saveList(BuddyList buddyList) throws IOException; List<BuddyVariable> getOfflineVariables(String buddyName) throws IOException; BuddyListManager getBuddyListManager(); void setBuddyListManager(BuddyListManager buddyListManager);
The init() and destroy() method are called upon creation and destruction of the class, while the BuddyListManager getter/setter is used to maintain a reference to the BuddyListManager object that governs the Buddy Lists in the current Zone. The remaining methods represent the core of the persistence mechanism, which is very simple.
- loadList(String ownerName): loads the Buddy List for the specified Buddy name.
- saveList(BuddyList buddyList): saves the passed Buddy List in the storage system.
-
getOfflineVariables(String buddyName): retrieves the offline Buddy Variables for a specific Buddy. This method is needed in the following scenario:
- User Fozzie logs in the system and loads his Buddy List
- For every Buddy in Fozzie's list that is not online we will need to load their persistent variables directly from the storage system
- For every offline Buddy the Buddy List Manager will call this method
You will be able to provide your custom implementation by simply dropping your .jar file in the SFS2X lib/ folder and specifying the fully qualified name of the storage class in the AdminTool (Zone Configurator -> Buddy List tab).