Flock Basics
- About, Events
- Server & Testserver
- Matchmaking
- Security & Performance
- Anonymous & Authenticated Sessions
- User Authentication & Registration
- User Attributes & Data Storage
- Participant Objects of a Session
- FlockActivity
- Statistics
- Facebook API
About
Flock is an event-driven multiplayer engine which connects to a fast, redundant server infrastructure hosted across various Amazon datacenters. This document covers the basics and underlying concepts for developers new to the framework. You can help us improving it by providing feedback, questions and ideas via mail to support@flockengine.com.
This is an overview of the general architecture:
Commonly Used Terms
Lobby | Waiting room until enough participants with the same settings are found (groups and maxPlayersPerGame). After FlockEvent.CONNECTION_ESTABLISHED , before .SESSION_STARTS . |
Session | An active game after waiting in the lobby. Multiple participants exchange messages. After FlockEvent.SESSION_STARTS |
Participant | A player inside a session. Accessible via Flock.getAllParticipants() , which returns an array of Participant objects. |
Connecting
The following steps are required in order to connect clients to a session:- Set an event-listener to receive callbacks from the engine
- To use the testserver, set
Flock.setTestServer(true)
- Decide whether you want anonymous or authenticated sessions (info).
- If anonymous: set
Flock.setAnonymousSession(true)
and an username withFlock.User.setUsername(String username)
. - If authenticated: Create an account with
Flock.User.createAccount()
or authenticate withFlock.User.authenticate()
orFlock.User.authenticateWithFacebook()
- If anonymous: set
- Call
Flock.connect(String groups, int players_per_game)
. All clients with same group and max-players qualify to be matched for a session (see matchmaking).
The socket connection is handled by a background service, which allows you to connect different Activities to the same socket connection. Useful for starting a second Activity when the session starts (in-game screen). Have a look at the examples to see it in action.
Events
The last Activity which set an event-listener receives notifications about status changes, such as CONNECTION_ESTABLISHED
,
SESSION_STARTS
or NEW_MESSAGE
(full list).
These events include the sender-id (-1 for the server, 0..n for other participants) and possibly a message-string (the
sender-id matches the array index of Flock.getAllParticipants()).
There are two basic ways of creating the listener:
- Have the Activity implement
FlockEngine.FlockEventCallback
and usingFlock.setOnEventListener(this)
public class YourActivity extends FlockActivity implements FlockEventCallback { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Flock.setOnEventListener(this); } public void onFlockEvent(FlockEvent event, int sender_id, String msg) { Log.v("", "new event: " + event + ", sender=" + sender_id + ", msg=" + msg); switch (event) { case SESSION_STARTS: Toast.makeText(this, "Game Starts", Toast.LENGTH_SHORT).show();; startActivity(new Intent(YourActivity.this, Game.class)); break; } } }
-
Manually creating the listener without
implements
:Flock.setOnEventListener(new FlockEventCallback() { public void onFlockEvent(FlockEvent arg0, int arg1, String arg2) { } });
Activity FlockEngine Server | | || | connect() | || |----------------------->| || | |<---------------->|| | CONNECTION_ESTABLISHED | || |<-----------------------| || | | || | | || | | || Opponent | | || | | SESSION_STARTS |<-----------------||---------------->| |<-----------------------| || | | | || | | | ||<----------------| Opponent sends message | NEW_MESSAGE |<-----------------|| | |<-----------------------| || | | | || | | sendMessage(String) | || | |----------------------->| || | | |----------------->|| NEW_MESSAGE | | | ||---------------->| | | || | | | || | | | ||<-------X--------| Opponent quits Activity | PARTICIPANT_QUIT |<-----------------|| | |<-----------------------| || |
Server & Testserver
Testservers are available for immediate testing of the engine. The testserver accepts anonymous as well as identified sessions, and behaves exactly as a regular server with a few exceptions:
- Accepts all developer-ids
- Maximum of 10 simultaneous connected clients
- Authentication is always encrypted, but on the testservers in-game messages are exchanged unencrypted for increased performance. You can set SSL encrypted message exchange on private gameservers remotely via the web interface.
For your Activity to use the testservers, simply set Flock.setTestServer(true)
in all Activities dealing with Flock (authenticating and connecting, but also in-game and highscore Activity).
Changing to a private gameserver later on is hassle-free: set it up via the web interface and remove setTestServer()
.
Matchmaking
Matchmaking is the process of matching the best opponents which wait in the lobby for a new game.
Developers can specify multiple groups when calling Flock.connect(groups, maxPlayersPerGame)
.
The parameter groups is a colon separated list of group-names (eg. "beginners,experts").
If in one of the requested groups enough players were found, a new game starts and the players
are removed from the lobby. At receiving FlockEvent.SESSION_STARTS, the callback parameter msg
is the group in which the players were found.
Security & Performance
Flock implements SSL/TLS and AES-256 encryption methods to provide full confidentiality of all user-related information. Connecting to a gameserver always initiates a sequence of connections. The first is always encrypted with SSL/TLS, authenticates the user for the first time and receives ip and port of the target instance. Developers can choose between using SSL/TLS connections for the subsequent game-connection (including in-session messages), or only to encrypt authentication tokens with AES and to transfer the messages in plain text.
Encrypting the messages requires additional cpu processing time at the clients and reduces the maximum throughput, and many games want faster exchanges than possible over a SSL tunnel. In this case you can disable encryption for in-session messages remotely via the web interface the clients automatically adjust to it.
Pings and Delays
Our first measurements resulted in an average relay-time for messages from one participant to all other participants of 0.02 secods for ethernet/wifi networks, and up to 0.2 seconds for clients using 3G networks. More comprehensive benchmarks coming soon!
Anonymous & Authenticated Sessions
You can choose to use anonymous as well as authenticated sessions. Default is authenticated,
to enable anonymous sessions use Flock.setAnonymousSession(true)
.
Here is an overview of the differences:
Anonymous
- Users don't need to create accounts, logins will never be rejected
- Set username with
Flock.User.setUsername(String)
- Multiple participants can have the same username
- Profile attribute storage is not available
Authenticated
- Users have an account with an unique username (see also Flock.User.createAccount() and Flock.User.authenticate())
- User Attributes
- Store up to 250 arbitrary attributes per user in the global database (eg. points, level, achievements). See also the class UserAttributeSyncer.
- Attributes can be automatically available for all participants when the game starts. See Flock.requestUserAttributeNumber() and Flock.requestUserAttributeString().
- Retrieve highscore and other datasets from the Datastore-API in HTML or JSON (class DBQueryBuilder)
User Authentication & Registration
Only required for authenticated sessions.
Each user is identified by a unique username and a password, which is verified with the user-database.
Authentication and registration is done in a Thread in the background; the responses are received via the onFlockEvent
callback (see Events).
Developers can use the same user database across multiple games.
User-accounts can be created by using Flock.User.createAccount()
or Flock.User.createAccountWithGui()
. If an account is succefully registered, the user is also authenticated. The status-events after creating an account can be:
CREATEACCOUNT_SUCCESS ........ Account successfully created (always followed by AUTH_SUCCESS)
AUTH_SUCCESS ................. User authentication successful
CREATEACCOUNT_FAILED ......... Network problem
CREATEACCOUNT_USERNAMETAKEN .. Username already taken
Signing into an existing account can be done with Flock.User.authenticate()
or Flock.User.authenticateWithGui()
. Possible status events:
AUTH_SUCCESS ......... User authentication successful
AUTH_FAILED .......... Technical problem on server side
AUTH_REJECTED ........ Username/Password combination invalid
User Attributes & Data Storage
For authenticated users Flock provides a persistent key-value storage system for up to 250 attributes for every user for every game (since a user-database can be used for multiple games). The attributes are saved to a global, redundant database and can automatically be requested for all participants when the game starts (useful to "auto-load" common attributes such as "points" and "level" for every participant of a game).
The attributes are key-value mappings with Strings and Numbers. You can save attributes for the user to the global databse with the UserAttributeSyncer. Possible responses via status events:
FlockEvent.ATTRIBUTEUPDATE_SUCCESS
FlockEvent.ATTRIBUTEUPDATE_FAILED
If one of the participant updates it's attributes, all other participants receive FlockEvent.NEW_ATTRIBUTE
.
As always the sender_id of the event maps to the array-index of
Flock.getAllParticipants()
To automatically load certain attributes for all participants joining a session, request them with
requestUserAttributeNumber(String, long)
or requestUserAttributeString(String, String)
calling Flock.connect()
.
See also the example "Dice Full".
Accessing user attributes outside a game
Since version 0.3.0 you can retrieve the local users attributes outside a game with Flock.User.retrieveAttributes():
Flock.User.retrieveAttributes(new UserAttributesCallback() { public void onAttributesReceived(Mapattributes) { if (attributes.isEmpty()) { log("Empty attributes map"); } else { Iterator i = attributes.entrySet().iterator(); Map.Entry me; while (i.hasNext()) { me = (Map.Entry) i.next(); log("Attribute '" + me.getKey() + "': " + me.getValue()); } } } });
Participant
Objects of a Session
The Participant object is a simple representation of every player within a session. You can retrieve an array
with all participants of this session with Flock.getAllParticipants()
after
receiving FlockEvent.SESSION_STARTS
. This
array also includes participants which have already quit, in order to keep the array index mapped to
the sender-id of events.
Important methods of the Participant object:
String Participant.getUsername() int Participant.getUserId() // 0..n boolean Participant.isActive() // false if user has quit String Participant.getAttributeNumber(String key, long defValue) String Participant.getAttributeString(String key, String defValue) HashMap<String, String> Participant.getAttributes()You can retrieve the Participant object of the local user with
Flock.getLocalParticipant()
.
See also Participant in the API Reference.
FlockActivity
FlockActivity is a helper class with the aim to simplify using the engine. It is just a normal Activity which additionally instantiates FlockEngine as this.Flock, unbinds the background service at onDestroy, and notifys the client activity as soon as the connection to the service is established.
Read more: FlockActivity
Statistics
Developers have access to web-based visualizations of the status of the gameserver instances, the history of logins and games played and many other things. All statistics can be grained down to an hourly overview and details about any single player. Furthermore you can choose to receive daily reports by mail, including all informations and statistics about the activity of your application.
Facebook API
To use the Facebook API you need to register your app at facebook and supply your app id to
Flock.User.authenticateWithFacebook(String app-id).
After the user signed in with Facebook, you can access the API via the class Flock.User.Facebook
.
You can register your app here: http://developers.facebook.com/setup/ (be sure to format your url like this: http://flockengine.com/ (no www., with trailing slash))
See also:
If you have questions or feedback please send us a mail to support@flockengine.com.