So I made an MMO in 48 hours

About LudumDare

So this is about a game I made for LudumDare 48.

LudumDare is a game jam where you need to create a game in 48 hours. That is in case you work alone and from scratch, like I did. There is also an option to go 72 hours with a team.

This is my 4th time I participate in it, and it is always a lot of fun.

About the game

When the jam starts, a theme is being announced and you can start working. This time the theme was “Deeper and Deeper”. I tryed to not spend too much time thinking about the theme, so I went for the obvious - making players dig.

So the game is basically a huge chunk of stone that you mine out (and then also build with the blocks) and can get treasure from sometimes. Deeper you dig, more valuable the treasure chest is. And so you have money you can show off on the leaderboard.

So, leaderboard. This means I need to store something somewhere. A server. Well, why not make a multiplayer game then, right? Right. So that’s what I did. Besides, after the developing phase is finished there is play and rate time when other people play your game. It is always cool to see your game being played, so being able to interact with other people when they play is even cooler.

In fact, here’s my game’s trailer which is a compilation of different streamers playing it:

When you start a game you spawn in the singleplayer world (in case server is down), and you travel to the server using the train.

Multiplayer being my main focus, it made sense to make character customizer too, right? Right. So this is another thing that I did.

If you think that making multiplayer and character customizer is not worth it a 48 hour jam game, you are probably right. The gameplay is too simple and not interesting because too much time was spent on those unneeded features. But this is what I want to be better at so I would say it was worth it. Out of those 48 hours, only 20 hours were spent on development, 4 of which spent on multiplayer part. But now I’m pretty sure that I can make it in much less time next time.

Here’s all 20 hours of development in just 1 minute timelapse:

Art and sounds

This time I used an iPad with a pencil to draw all the art. I am not good at drawing, so I went for doodles, but I really like how the game looks in the end anyway.

For sounds I used a microphone and my mouth. Same for music, I recorded whistling and guitar, and I know it is not good and I want to get better sometime, but I think it fits well with the game’s art style.

Technical details

The game is made using Rust programming language with my own game engine (very raw). The engine makes sure everything works on all platforms including the web, but does not have much features.

Multiplayer is done via websockets (since I need to be able to run on the web). The client and the server both maintain a whole game model in memory. When client wants to do something (like move their character or break/place a block), they send an event to the server. The server handles that event by updating the model and possibly generates more events (like spawning an item when a block is broken), and then sends these events to all the clients so that the game state is synchronized.

There is one downside to that logic - the whole model should be downloaded first when the client connects. But it was fine for this game - although I reduced initial world size from 4000x2000 to 400x200 tiles so that it is less than a megabyte.

Dupe mechanics (not a bug, totally planned)

Every good MMO suffers from glitches, like item duplication. So you can do it in my game too. When picking an item up, client sends an event to remove the item from the world, but gives your player that item instantly. This means that when two players want to pickup same item at the same time, both will have it in the end - because the events will reach the server not instantly, but after a short time period. Easiest way to dupe is to have two players with 1 item spaming drop and pick up buttons.

Since the character does not have any inventory but can only hold 1 item in hands, this is actually good for building, since it is a bit too tedious to build something by going back and forth always.


Every good MMO suffers from hackers. So this is what happened couple days before the game jam finished:

One of the commenters on my game showcased my game on their stream and uploaded it to youtube

You may notice that when he joined the server he said hello to a random person without a passport.

This dude was just sitting there near the moneymaker pretending to be doing nothing.

Several days later I also joined another person on stream who played Ludum Dare games, including mine. Unfortunately their VOD was not saved, but I was there when it happened.

At first I did not even notice, since they blended well into the environment, but the suspicious guy was still present on the server in the same exact spot doing something suspicious.

And well, right during the stream while I was playing with the streamer, we noticed that our characters stopped synchronizing.

And this was it. I looked up on the server, and indeed, the hacker has done it! The server has been crashed!

May 17 07:23:10 kuviman bash[10744]: memory allocation of 838860800 bytes failed
May 17 07:23:10 kuviman systemd[612]: ld48-server.service: Main process exited, code=killed, status=6/ABRT
May 17 07:23:10 kuviman systemd[612]: ld48-server.service: Failed with result 'signal'.
May 17 07:23:20 kuviman systemd[612]: ld48-server.service: Service hold-off time over, scheduling restart.

The server has an autorestart tho so you can still play the game (unless I have turned it off manually), but it does not save anything to disk, and keeps all the world in memory. So that means that everything that was built by all other players - houses, ladders to the hell and to the sky, LD48 sign, all the swear words and statues - are gone now. The server has been wiped. F

I was going to make a save of the world with small changes in the client, but that is now impossible. Anyway, I made a screenshot of the world at some point near the beginning, and that is how it looked:

The server was up since the beginning of ludumdare and and that point, 1 and a half day before the results, this was the first incident.

How could this happen?

For message serialization when talking between client and the server, I am using bincode format. When deserializing collections, they first read collection’s size, then allocate the memory for it and then read the data. So if someone was to put some random bytes in the serialized data the server would allocate a random amount of memory. This is most likely what happened. Apparently this can be fixed by specifying maximum message length for bincode.

More game jams

Participating in game jams is good practice and fun times, so I plan to do more of those.

In fact, I made another tiny game for a Mini Jam last weekend with by brother.

Mini Jam takes place every other week so I will probably try to participate in it more.

Next big jam is GMTK, and next Ludum Dare is in 6 months.

When I participate I will be streaming on twitch, so you can follow if you are interested.

See you next time!


Get LD48 - Dig World

Leave a comment

Log in with to leave a comment.