While studying in Sunny, Dundee, Scotland I built Loch Monsters as part of the Networking for Online Games class. Loch Monsters is a multiplayer Slither.io clone. It uses a client-server architecture because I wanted to be able to expand it to support many clients. The server is built-in Kotlin with Java Sockets and the client is Unity with C#.
The game is called Loch Monsters because both Vermont and Scotland share a lake monster myth. Both Champ and his famous cousin Nessie are purported to swim in our dark waters to this day. In Loch Monsters you can customize your serpent and join a lake. Grow by eating food and killing other serpents.
I decided to build my server using Java Sockets instead of the WinSock API because I wanted to create something that would be cross-platform and expandable. Since many servers run Linux instead of Windows, using WinSock felt like it would cause problems later on. Java Sockets have many advantages. They work well with Cloud Services such as AWS and can easily be set up with a CICD pipeline using Jenkins. During my time at Dealer.com, I saw that Java was widely used in industry due to its great documentation, and wide support.
Java does not expose raw pointers which can be an advantage in some cases. Playing with pointers is a little like setting off roman candles in the backyard. It’s great fun right up until you blow your fingers off.
Direct memory access is dangerous. It is certainly useful in many cases, but it is still a risk that should be considered and managed. Tiny mistakes can cause large security vulnerabilities. A simple buffer overflow could put your whole enterprise at risk. Java makes big security vulnerabilities less likely by limiting access to low-level features and using exception handling. For Loch Monsters, the faster and safer development possible with Java won out over the speed and control of C++.
“Ok, I see why you used Java Sockets, but why on earth did you muck around with that weird new Kotlin?”
The answer to your question, hypothetical reader, is that I am simply more comfortable with Kotlin. I learned Java almost 4 years ago at Vermont Tech and haven’t used it much since, however, I spent all summer falling in love with Kotlin. This language is everything you’ve ever secretly wished that Java was: clean, modern and helpful. Even the most ardent Java lover must admit that it is at times verbose to the extreme. Kotlin, in contrast, cuts down on boilerplate, making code more readable and less error-prone.
I wanted to build something beautiful but I still needed to meet deadlines which is why I used Unity on the client-side. Unity streamlines gameplay development allowing me to get core features up and running fast. It uses C#, another modern memory managed language, and one of my personal favorites. .NET sockets are also cross-platform meaning that friends on Linux and Mac (you know who you are) can join in the fun.
Getting Java and C# to play nice was a headache at first but once I got my networking protocol ironed out everything went smoothly. At first, I had issues sending data as bytes and spent many long nights losing my mind over endianness, the size of chars and string encoding before discovering that I was simply not flipping my byte arrays before sending them on the server. (Facepalm). Another time I wondered why my game completely broke when running on different computers but worked fine on the localhost. Short answer: don’t trust clients about time. It turned out the internal clock on the client computer was 5 seconds behind the server. Making the server authoritative about time fixed the issue. In the end, you learn more from fixing broken code then the kind that runs perfectly the first time and I learned plenty in this project.
I’ve attached my presentation which further explains my design decisions and includes Gifs of my game in action.
You can see the source code for my server and client on GitHub.