I have spent about a week reading about how can I make a game server for a MMO type game. The majority of content that I find ends with “don’t do it”. This is not particularly constructive. It’s clear that it will be a lot of work and it will make a good long term project for sure.
After a good amount of reading, I’ve decided to try and make it from scratch, the main reason is that I didn’t find many templates available and the ones that I did find were not that great.
As you can see from my profile, I am a web developer, rather than a game developer. So I will also be learning a lot on this journey and documenting my findings as I go.
Note that Unreal Engine dedicated server and Unity in-built networks will have great features, but its just simply not scalable for a MMO type genre. If you’re looking to make a game that doesn’t require too many users, let’s say up to 100, you should definitely check tutorials for utilizing their in-built server features.
I will write the server in Java, though the majority of existing servers are written either in C++ or C#.
Note that I don’t think Java is the best option here, but I think its viable with some of the advancements that it had. It’s also a language I am comfortable in writing so I think it will just be more efficient for me.
I will jump straight into it;
I am planning on creating the ‘front end’ client with Unreal Engine 4. I will be learning as I go, but the main concepts that I will need to do are:
- have a player object rendered on the screen
- user presses keys which are sent to the server
- keys are processed in the server and the results are sent back to client
- the result is rendered in form of movements etc
The client simply does just the drawing this way, this has to be the case in order to avoid hackers and similar.
The most difficult aspect I see here is synchronising the environment of the front end with the server.
In theory I think if we create a height-map space within server, we can import it as landscape in UE. There will be a lot more to think about when we start including extra objects, like trees or rocks etc. We need to make sure that the server is aware of the ‘obstructions’. Also we’d have to implement things like physics, i.e. if you jump there’s got to be some gravity to pull you down. Unity and Unreal provide this out of the box for you, but they’re not going to be available on our custom server.
Each post will look to implement a small feature of the server/client so stay tuned.
Server framework
I will be starting the project with micronaut
. Here’s some interesting info about it:
Due to the Micronaut framework’s compile-time, reflection-free approach to DI and AOP, you can natively compile a Micronaut application into a GraalVM native image, allowing the application to start up in milliseconds while consuming only a fraction of the memory of a regular Java application running on the JVM.
https://micronaut.io/2018/09/30/micronaut-1-0-rc1-and-the-power-of-ahead-of-time-compilation/
This will allow us to be flexible in the future with how we process each request. I have not settled 100% on the scalability plan as I have a few, one of which may even include spinning up a tiny micro-service for each player that signs to process their specific requests, all synchronised with the use of either Redis or MongoDB.
I will tackle scalability when there’s a bit of a need for it, but I will always bear it in mind as I am developing.
To get started, download and install micronaut.
Once you have the CLI you can create a new project using:
mn create-app mmo_server
If you’re not sure which IDE (editor) to use, I’d suggest downloading Intellij Community edition which is free to use and has a lot of great features.
Open the project, you should see something similar to this now:
Now we will start by making some simple package and controller.
First, let’s see some useful commands from micronaut CLI:
mn --help
Usage: mn [-hvVx] [COMMAND]
Micronaut CLI command line interface for generating projects and services.
Application generation commands are:
* create-app NAME
* create-cli-app NAME
* create-function-app NAME
* create-grpc-app NAME
* create-messaging-app NAME
Options:
-h, --help Show this help message and exit.
-v, --verbose Create verbose output.
-V, --version Print version information and exit.
-x, --stacktrace Show full stack trace when exceptions occur.
Commands:
create-app Creates an application
create-cli-app Creates a CLI application
create-function-app Creates a Cloud Function
create-grpc-app Creates a gRPC application
create-messaging-app Creates a messaging application
create-test Creates a simple test for the project's testing framework
create-client Creates a client interface
create-websocket-server Creates a Websocket server
create-websocket-client Creates a Websocket client
create-job Creates a job with scheduled method
feature-diff Produces the diff of an original project with an original project with
additional features.
create-bean Creates a singleton bean
create-controller Creates a controller and associated test
We will want to make some basic HTTP requests, so lets get started with that:
mn create-controller player.player
This will create the following for you:
If your CLI is not working, here’s the code snippet to copy:
package player;
import io.micronaut.http.annotation.*;
@Controller("/player")
public class PlayerController {
@Get(uri="/", produces="text/plain")
public String index() {
return "Example Response";
}
}
This does no computation, but it handles all of the networking of the application for you.
If you run the application now, you will see something like this:
To test the endpoints, I would highly recommend something like Postman.
Let’s make a simple request:
That’s great, in a matter of minutes we have a working web server.
Note that the server is running on: http://localhost:8080
as you could see from the terminal output.
The controller specified endpoint of:
@Controller("/player")
And that’s how we get the GET http://localhost:8080/player
endpoint.
Now that we have the base application setup, let’s create some processing functionality.
In the next chapter we will look to create:
- PlayerService – will handle player requests and send them to be processed in correct locations
- Motion DTO (Data Transfer Objects) – Simple objects that hold data about (player) motion
- Connect controller to player service with basic requests/responses.
- Connect the basic move forward/backward API with unreal (possibly chapter after as this will be chunky I assume)