Match-making with Firebase
Did you just build your board game for Android? Want to get it online? You are at the right place - let's build it together!!!
We are going to implement match-making with the Firebase Realtime Database in this article. For that, you need Firebase setup in your Android project here.
Firebase users - here, we are assuming you were able to login your user into Firebase using any method. This is necessary to identify who to communicate with after the match-making is finished.
Gradle Dependencies - Add these to the
dependenciesblock in your app module's grade file.
implementation 'com.google.firebase:firebase-core:16.0.6' implementation 'com.google.firebase:firebase-auth:16.1.0' implementation 'com.google.firebase:firebase-database:16.0.6'
You aren't done after implementing match-making . That's cause you've only found two players that will play - but haven't implemented how their moves will propagate over the network. Check out the article on game communication.
We will use a node in the Firebase database called the game room which will store all the active challenges that users have pushed. Each user will search for existing challenges within the game room and will accept the first one found. Otherwise, the user will upload his own challenge and wait until someone accepts the challenge.
You will be able to add more features in your match-making implementation like matching based on similar performance ratings, friends, regional-bias, etc.
How the heck are we gonna implement that?
I've divided our problem into three objects:
Matcher: Finds any existing matches in the game room.
SelfChallengeManager: Manages the challenge a user uploads if Matcher fails to find any one.
SelfChallengeCanceller: Cancels the match-making process if this user doesn't wanna play anymore.
In addition, we will require a "Challenge" object that has two properties - communication node reference and the challenger's user ID (get why we need to login to Firebase now?). This object will be uploaded into the game-room by
Writing our components first
Before writing our three components, we need to understand what a Firebase transaction is. We don't want two users accepting the same challenge at the same time - which would corrupt our database and make our precious users angry. Transactions come to the rescue by prevent concurrent operations on a node in the database (which will be the game room).
How does that relate to our components? - Our components will be modeled as transactions as inner classes in our 'FirebasePlayerMatchMaker' class.
We use two callback interfaces -
OnMatchMadeCallback and internally
OnFailCallback. The factory method takes a
OnMatchMadeCallback which is called whenever a match is made. The
OnFailCallback is invoked whenever MatchMaker fails to find a match.
findMatch runs on a separate thread and creates an
Matcher doesn't find a match. In that case, we have to create a
SelfChallengeManager and run it as a transaction.
doTransaction()method iterates over all the children of the game room node and searches for a
Challengethat is compatible for our user. By default,
true, but you can change that by adding additional constraints like ratings. The first compatible challenge is then stored and the challenge node is deleted (by setting the value to
null) in the database. Note that by deleting the node, the other player will be notified of the acceptance.
doTransactionmethod adds a child node to the
GAME_RECORDnode in our database. This is where the game moves will be communicated after the match-making. It then uploads a
Challengeto the game room and adds itself as a
ValueEventListener. Whenever another user accepts the request, they will delete this node and this user will get notified as we are listening.
Our code just deletes the node created in by
SelfChallengeManagerby iterating over all the game room and finding our challenge. BUT ITS INCOMPLETE!!! You (optionally) should add a feature where the this user automatically resigns from the game if the match was accepted already.
OnMatchMadeCallback you provide to
FirebasePlayerMatchMaker.newInstance, you must initialize the game communication to be done in the node (by path)
Yo, you've done it. Now read the article on game communication to finish up.
3.4K+ developers have started their personal blogs on Hashnode in the last one month.
Write in Markdown · Publish articles on custom domain · Gain readership on day zero · Automatic GitHub backup and more