Served: The Server Server Part II
Previously on The Blog, we talked about my initial forays into networked game development. I was a hotshot who could make a mean chat application. Then I made a pretty cool little game with Node.js and Socket.IO. I was unstoppable. So I began working on a platform agnostic, reusable server framework for peer-to-peer networking. What could possibly go wrong?
I'm poking fun at myself here, but it's worth stating that what I actually wanted to create wasn't so unreasonable, it was just misguided. Ignoring all the buzzwords, my goal was simply to create a system similar to that of games like Minecraft. A system that allows single player or multiplayer, opening up a single player game to network connections, or running a standalone server. Oh, and I also didn't want my system to be tied to any platform or engine. Whether the client was built in Unity, C++, Javascript, or whatever else, I wanted this system available. It certainly was ambitious, but it was possible. The problem is I had very little idea what I was doing.
Through my networking course, I had only ever built a back end with Node.js. Naturally, that made it the perfect fit for my system. After that well informed decision, the first obstacle was figuring out how I could distribute apps without users needing to install Node. Great start, I know. I initially looked into how I could get an application to run a Node app. Surprisingly, I couldn't find much information on the topic. Oh well, on to Plan B: Build the Node app into a standalone executable. It seemed like the perfect solution, since being able to run a server standalone was also one of my requirements.
I had a lot more success in building an executable. In fact, I actually had some options to choose from. Of note, I tried out Electron and nexe. Both worked, but I settled on nexe. The build time was faster and the executable's file size was much smaller than the one created by Electron (Plus I didn't actually need any of what Electron provided, beyond the ability to create an executable). Opening the executable from a client was easy enough, and I could send some arguments so the server would know if it was standalone or not. Everything was coming up Milhouse. Or at least it was until I tried out my new nexe-built executable and was greeted by all the errors. I intended to use Socket.IO for my system, but nexe and Socket.IO had some issues that they just could not work out. It's been a while now, so I don't actually recall the issue(s), but it was enough of a blocker that I decided I had to ditch Socket.IO. That was a tough call to make, Socket.IO made networked communication so much easier, but it was alright because real games use UDP, right?
I think I'm going to stop there. The project continued on, but slowed significantly at this point. I did do a bit of research into UDP hole punching for connecting clients, but the further I got, the more I realized I was out of my depth. I all but abandoned the project until recently. Out of nowhere, the project got a second wind in a brand new form. We'll talk about that next time.
I'm poking fun at myself here, but it's worth stating that what I actually wanted to create wasn't so unreasonable, it was just misguided. Ignoring all the buzzwords, my goal was simply to create a system similar to that of games like Minecraft. A system that allows single player or multiplayer, opening up a single player game to network connections, or running a standalone server. Oh, and I also didn't want my system to be tied to any platform or engine. Whether the client was built in Unity, C++, Javascript, or whatever else, I wanted this system available. It certainly was ambitious, but it was possible. The problem is I had very little idea what I was doing.
Through my networking course, I had only ever built a back end with Node.js. Naturally, that made it the perfect fit for my system. After that well informed decision, the first obstacle was figuring out how I could distribute apps without users needing to install Node. Great start, I know. I initially looked into how I could get an application to run a Node app. Surprisingly, I couldn't find much information on the topic. Oh well, on to Plan B: Build the Node app into a standalone executable. It seemed like the perfect solution, since being able to run a server standalone was also one of my requirements.
I had a lot more success in building an executable. In fact, I actually had some options to choose from. Of note, I tried out Electron and nexe. Both worked, but I settled on nexe. The build time was faster and the executable's file size was much smaller than the one created by Electron (Plus I didn't actually need any of what Electron provided, beyond the ability to create an executable). Opening the executable from a client was easy enough, and I could send some arguments so the server would know if it was standalone or not. Everything was coming up Milhouse. Or at least it was until I tried out my new nexe-built executable and was greeted by all the errors. I intended to use Socket.IO for my system, but nexe and Socket.IO had some issues that they just could not work out. It's been a while now, so I don't actually recall the issue(s), but it was enough of a blocker that I decided I had to ditch Socket.IO. That was a tough call to make, Socket.IO made networked communication so much easier, but it was alright because real games use UDP, right?
I think I'm going to stop there. The project continued on, but slowed significantly at this point. I did do a bit of research into UDP hole punching for connecting clients, but the further I got, the more I realized I was out of my depth. I all but abandoned the project until recently. Out of nowhere, the project got a second wind in a brand new form. We'll talk about that next time.