In the last blog, I briefly mentioned my system architecture which included an orchestrator to spawn game servers and a matchmaker to match players. For this entry, I’ll be formally reintroducing you to them as the Chungustrator a.k.a. the orchestrator and Matchmaker a.k.a. the normal guy named John. You’ll be meeting a new service named the Chungusway a.k.a. the gateway that connects the system to the game server and Chungusmod which is my fork of spaghettimod for Cube 2.
I’ll be going into detail about the sequential flow of this backend system, starting from the matchmaker to the game server, while using the problem and solve of player verification as the ship and sail. If you haven’t read the first blog, I encourage you to do so before continuing!
Player Verification?
Today, most games are played through launchers and platforms such as Steam that provide built-in player authentication for multiplayer games through their backend services. They use session tickets that are automatically generated for the client, then handed to a game server, which sends the ticket to Steam’s backend to verify the client’s identity and authority to be in the game. This lets the game server confidently say that you are the real John Halo from Steam in my competitive Aztec match on Counter Strike 2! Neat! You can play the game I guess.

The problem is, how do my multiplayer servers know that the player that joined the game is who they say they are? I’m not using Steam, Cube 2 predates Steam’s authentication backend! There’s no concrete way to authenticate players, and I can’t tell if someone joined my game server through my matchmaker or found it in the public server browser.

Player Verification!
Initially, I knew that implementing session tickets wasn’t the solution: I could implement session tickets but I don’t want to. I would have to modify the Cube 2 open source client, go deeper into the server code, and ultimately make the backend service more bloated and confusing for myself. Yuck. I want to optimize for people playing the game with the official game client than for them to download a game client that I modified.
I also knew Cube 2 natively uses ENet to connect to the outside world, which is a UDP library that basically wraps over UDP, so there had to be something there.
After a while, I came up with another solution that’s more simple: verification codes, kinda like the ones you get through email, but this time using ENet for the the backend system.
My plan with verification codes is that they will be directly given to players and redeemed in-game by them to verify their identity, therefore uphold match integrity and prevent the problem of imposters among us. For the game server to recognize these codes, I hacked it in such a way that these codes are generated by the matchmaker, passed to the orchestrator, gateway, and then finally land in the game server. The transportation process is kind of like an assembly line.
Since the verification codes are figuratively signed and literally created by the Matchmaker, there’s no need to double-check in the backend like the way Steam does.

Matchmaking to Game Server
Since this is the first time going over my system, I’ll give a brief rundown of how it works including the transportation of verification codes starting from the Matchmaker to the game server:
Matchmaking. The player joins queue through websocket holding data such as their chungID, which is my version of the SteamID. Once a match is made, unique verification codes are generated for each player, and the matchmaker sends a message to the Chungustrator through gRPC saying spawn a game server for me please. Also, here’s the players’ chungIDs and verification codes!

Chungustrator. Once the message is received it spawns a game server. After the game server is successfully created, the orchestrator returns a message to the Matchmaker including the address and port of the game server that was requested. The orchestrator also sends a message through gRPC to the Chungusway saying can you send these verification codes to this game server I just made? Here’s its address and port, thanks!

Matchmaking. With a response from the Chungustrator, the matchmaker notifies each match-made player through websocket, detailing the game server to join, including the game server’s address and port, and their own unique verification code to input in-game.

Chungusway. Receives message from Chungustrator, initializes an ENet client, makes an ENet connection to the game server using the address and port it has received, stuffs the mapped chungIDs and verification codes into a packet, and sends the packet to the game server on a channel exclusively for Chungusmod.

Chungusmod. The game server detects an incoming packet on the exclusive Chungusmod channel, unwraps the packet, and sends it across the bridge to Chungusmod. Once crossed, the game server now knows who is supposed to be joining and what verification codes each player needs to use to be verified and authenticated! Neat!

From here, players initially join the game server as spectators and will need to input their unique codes given to them by the Matchmaker with this command in their in-game console \code <verification_code>. If the code is correct, they will be able to spawn in and play, along with being linked to a chungID.
There you go.
Here’s a video showcasing you this process working.
Possible Issues
It works, but it’s not fleshed out.
Technically, as of now, a mischievous player can run their own ENet client using the same address and port to send packets to this Chungusmod channel which could be exploited. I haven’t thought of making it secure yet as this stage of the project, but there’s always a solution.
Thoughts, Packing It Up
Honestly, I think the addition of the Chungusway was a neat solution. It’s simpler than session tickets and gets the same job of verification and authentication done. There’s no need to think of scale for this project, it’s a toy project, and even in prod I doubt there will be thousands knowing how old and unpopular this game is. Optimistically, I hope there’ll be like ~5 players playing every couple months. All I care about is that it works.
This also solves some future issues such as name changing. In Cube 2, anyone can make their name anything and change it at anytime. Mapping a chungID to a player by using verification codes will allow players to use any name they want. Their stats at the end of the game will always be linked to their chungID.
This was my first time using gRPC. I initially implemented the communication between the Matchmaker and the Chungustrator over HTTP just to get something down for MVP. Protobufs are really cool actually, especially with gRPC. With that said, I do have one service still using HTTP, and that’s the game server itself.
Future Works
Right now I have the game server make a request to a service called the Server Query Client (SQC), which grabs player data from the game server at end of the game, and sends it to the player database. It uses a open source library specifically made for Cube 2 with abstracted methods to query data from the game server. This was the fastest way to get to MVP without going deep into the server’s networking. To prevent blocking the game threads and lagging the game, I made the request fire and forget. This works smoothly but it doesn’t sound or feel clean still.
Now that I’ve gone deep enough into the server source code thanks to verification codes, I’ll be revisiting this. An ENet server isn’t always a server, it can be a client too. With this information, what will be built? Real time/live player statistics? Another gateway for player stats? Who knows? I actually don’t know
I don’t know, there’s a lot of mysteries about this project that I haven’t publically revealed, and a lot more problems to solve like graceful shutdown of the game server and PvP bots. Who knows what I’ll write-up or implement next?
Feedback and Comments
If you’ve read up to this point, thank you! I hope reading about this problem was interesting to you as it was for me.
This is my second dev blog, if you have any qualms about it, please let me know.
Here’s the Twitter thread for further discussion. Project’s Github