Post feature RSS Crusher Chronicles #8: How the Online Co-Op Works

Our programmer, Ilkka, explains how the recently released MCE Online Co-op mode works. Long story short: it's complicated!

Posted by on


Hello, readers. I am the programmer responsible for Mushroom Crusher Extreme (from now on referred to as MCE) and my name is Ilkka Hyyryläinen. You can thank me for the numerous bugs in the game. Before the holidays, we launched Online Co-Op mode for MCE and just recently we released patch 0.96.0 with many improvements and bug fixes to the netcode. In this article I’ll explain how the Online Co-Op mode works in MCE’s code. Keeping introductions short, let’s get on to the actual content of this post.

Online play in MCE works through a central server hosted by Photon Unity Network. Players connect to the server when beginning an online game and form a game session called 'Room'. When players are connected to the same Room, all data sent between the players goes through the server. The benefits of doing things this way is allowing players to play online without having to mess with their routers’ firewall and port settings. The only drawback to this is the increased time lag between the players, compared to when they are connected to each other directly.


This time lag is what causes the biggest challenges in making online games. In any online game you play, your actions will not be immediately realized by other players due to the physical limitations of technology. All chat messages, Spell casts and character movements are always seen by others few milliseconds late. Many games have systems in place to try to predict to certain extent what is going to happen in hopes that it matches with what is actually happening.

In MCE, I first tried to make a way for the enemies’ movements to be predictable. The idea was to have enemies decide where they would be moving to next, ¼ seconds before doing so. Leaving the game with 250 milliseconds to update this information to the other player, who would then, based on their current ping, determine exactly when the enemy would start moving into the given position. This fell apart when I also had to consider that players can interrupt or alter enemies movement with various Trinkets and Spells effects. I also couldn't figure out any good ways to make any other elements of the game reliably predictable, so I decided to not bother. I imagine at worst the time lag would be for most people no worse than 80 ms, which will cause hardly any issues playing the game.

But considering that both players can interact with various elements in the game at any time, I had to take into account every possibility that players might end up causing conflicting situations in the game. Take for example movable boxes in the levels. Both players can push them around with wind Spells. Let’s imagine that players push the same box at the same time in two different directions. Neither player has yet received data from the other, so to both of them it looks like they pushed the box first and the game will start moving the box in the determined direction. But the box cannot exist in two places at the same time and it has to be on the same spot for both players. In this case the Host player, who created the Room in the server will take priority over the Client player who joined him. So when the Host player receives data from the Client that the box has been moved, his game will check if he has moved the box first locally. If this is the case, then the Host will not update the box. Instead the Client player receiving data from the Host will concede and move the box in his screen where the Host dictated it to be.


Of course, if the Client doesn't make his moves at the same time as the Host, then the Host will see no problems with using the data the Client has sent.

Another part where this kind of an issue can happen is when defeating enemies. In this case the Host player again has the advantage over the Client player, which helps him to progress in Accomplishments better. At least, hit detection between players’ Spells and enemies is handled on the side of who cast the Spell. Meaning the Host will handle hit detection for the Host player’s Spells and enemies’ Spells, while the Client will handle hit detection for the Client player’s Spells.

Damage and healing, however, is handled on the Host side again, to make sure that damage bonuses’ and elemental resistance values’ effects remain consistent and to save on bandwidth, as we won't need to share these stats over a network. If the Client player hits an enemy with a Spell, his game will send a message to the Host player with information of how much damage he is causing and what Spell he is using. The Host will then determine how much damage is caused to the enemy, go through any Trinkets’ special effects that are triggered by the hit and send a message back to the Client with the results, so his game can update the affected enemies information and progress his Accomplishments accordingly. Same goes for damage caused to the Client player as well.


Since the Host handles all damage calculation, then the Host also handles all damage-related events. This means that any Trinkets with special effects relating to dealing or receiving damage can only be triggered on the Host side, which becomes a problem when the Client player is using them. I had to make special cases for various Trinkets for these events, where the Host handles all of those events for the Client’s Trinkets and sends updates to the Client to keep the Trinkets synced. Surprisingly, about 50-60 % of all of the Trinkets’ special effects work without having to sync them between the players since Trinkets on both players systems have exactly the same stats and behaviour.

This was my first time ever making an online game. The biggest lesson I learned from this experience is that if you're not planning the game for Online mode from the very start, you're going to run into a lot of problems. I had to rework some systems regarding Spells and status effects’ damage and event tracking in order to have it sync up between two players over the network without having to send huge amounts of data. I would still like to add a way for players to join each other directly, assuming they know the Host’s IP address and have their port settings in order. This way more tech-savvy gamers can benefit from lower time lag and play the game even if Photon servers are down for maintenance. I think the game could still save a lot of bandwidth with some smarter netcode.

In case you have any problems with the current state of Online Co-Op, let us know on our Steam forums.

Thanks to Ilkka for this issue Crusher Chronicles! Follow us on Twitter or Facebook (or, what the heck, both!) for hot MCE news.

Post a comment
Sign in or join with:

Only registered members can share their thoughts. So come on! Join the community today (totally free - or sign in with your social account on the right) and join in the conversation.