What should I use for a Client/Server Multi-player survival game? Java

2.1k views Asked by At

I am making a game in java and it is going well. I want to early on implement multi-player so I build on it instead of porting the entire game to multi-player when it has a ton of different features.. I would like to make it a Client / Server application. Now I'm now sure how or what to implement the multi-player. I have read the java tutorials about sockets and everything, I tested them and made a successful connection (in a test project). I am not sure where to go from here. I don't know how would I transfer for example where different players are on the map or even just if there ARE any player at all.. I don't know if to use a library or do it my self or what... If anyone could please either give me some kind of guideline on how would I transfer player data or anything like that though a TCP connection or maybe give me a library that makes it simpler..

3

There are 3 answers

0
esaj On

This is pretty wide question and there are multiple ways to do things, but here's my take on it. Disclaimer: I am the server system architect of a mobile multiplayer gaming company. I don't consider myself an expert on these things, but I do have some experience both due to my work and hobbies (I wrote my first "MMORPG" that supported a whopping 255 players in 2004), and feel that I can poke you in the right direction. For most concepts here, I still suggest you do further research using Google, Stackoveflow etc., this is just my "10000 feet view" of what is needed for game networking.

Depending on the type of game you are making (think realtime games like first person shooters vs. turn-based games like chess), the underlying transport layer protocol choice is important. Like Matzi suggested, UDP gives you lower latency (and lower packet overhead, as the header is smaller than TCP), but on the downside the delivery of the packet to the destination is never guaranteed, ie. you can never be sure if the data you sent actually reached the client, or, if you sent multiple packets on a row, if the data arrived in correct order. You can implement a "reliable UDP"-protocol by acknowledging the arrived data with separate messages (although again, if the acknowledgements use UDP, they can also get lost) and handling the order by some extra data, but then you're (at least partially) losing the lower latency and lower overhead. TCP on the other hand guarantees delivery of the data and that the order stays correct, but has higher latency due to packet acknowledgements and overhead (TCP-packets have larger headers). You could say that UDP packets are sort of like "separate entities", while TCP is a continuous, unbreaking stream (you need some way to distinguish where one message ends and another begins).

There are games that use both; separate TCP-connection for important data that absolutely must make it to the client, like player death or such, and another UDP-connection for "fire and forget" -type of data, like the current position of the player (if the position does not arrive to another client, and the player is moving, there's not much point of sending the data again, because it's probably already outdated, and there's going to be another update in a short while).

After you've selected UDP and/or TCP for the transport, you still probably need a custom protocol that encodes and decodes the data ("payload") the TCP/UDP packets move around. For games, the obvious choice is some binary protocol (vs. text-based protocols like HTTP). A simple binary protocol could for example mark the number of bytes in total contained in the message, then type of data, data-field length and the actual data of the field (repeat for the number of fields per message). This can be a bit tricky, so at least for starters you could just use something like just serializing and deserializing your message-objects, then look at already existing protocols or cook your own (it's really not that hard). When you get the encoding and decoding of basic data types (like Strings, ints, floats...) working and some data moving, you need to design your own high-level protocol, that is actually the messages your games and server will be using to talk with each other. These messages are the likes of "player joined game", "player left game", "player is at this location, facing there and moving this way at this speed", "player died", "player sent a chat message" etc.

In real-time games you have some other challenges also, like predicting the position of the player (remember that the data the client sent could easily be hundreds of milliseconds ago when it arrives to another players client, so you need to "guess" where the player is at the time of arrival). Try googling for things like "game dead reckoning" and "game network prediction" etc., also Gamasutra has a pretty good article: Dead Reckoning: Latency Hiding for Networked Games, there are probably loads of others to be found.

Another thing that you need to think about is the concurrency of the server-side code. Many people will tell you that you need to use Java NIO to achieve good performance and using thread per connection is bad, but actually at least on Linux using Native Posix Thread Library (NPTL, pretty much any modern linux-distribution will have it out of the box), the situation is reverse, for reference, see here: Writing Java Multithreaded Servers - whats old is new. We have servers running 10k+ threads with thousands of users and not choking (of course at any given time, the sheer majority of those threads will be sleeping, waiting for client messages or messages to send to client).

Lastly, you need to measure how much computing power and bandwidth your game is going to need. For this, you need to measure how much load a certain (server?) hardware can take with your software and how much traffic your game causes. This is important for determining how many clients you can support with your server and how fast network connection you need (and how much traffic quota per month).

Hope this helped answer some of your questions.

0
Eric Grunzke On

For communication between VMs, it doesn't get much simpler than RMI. With RMI you can call methods on an object on an entirely different computer. You can use entire objects as arguments and return values. Thus notifying the server of your move can be as simple as server.sendMove(someMoveObject, somePlayerObject, someOtherObject).

If you're looking for a starting point, this could be a good one.

2
Matzi On

First of all, multiplayer games use UDP for data transfer. There are a lot of reasons for this, for example lower lag and such. If your game contains intensive action, and need fast reactions then you should choose something based on UDP.

Probably there are solutions for gaming on the web, but it is not so hard to write your own implementation either. If you have problems with that, you probably will have problms wih the rest of the game. There are non-game oriented libraries and solutions on the net or even in java, but they are mostly not designed for something that fast as a game can be. A remote procedure call for example can contain costly serializations and generate much larger package, than you really need. They can be convenient solutions, but have poor performance considering games and not reglar business applications.

For example if you have 20 players, each have coordinates, states, and of course moving object. You need at least 20 updates per second to not have much lag, this means a lot of traffic. 20*20 incoming message with user input, and 20*20 outgoing message containing a lot of information. Do the math. You must compress all the players and as many object data into one package, as you can, to have optimal performance. This means you probably have to write small data packages which can be serialized into bytestream quite easily, and they must contain only viable information. If you lose some data, it is not a problem, but you need to take care of important informations to ensure they reach the destination. E.g. you don't want players miss a message about their death.

I wrote a reliable and usable network "library" in C#, and it is not a huge work, but it's recommended to look around and build it good. This is a good article about this topic, read it. Even if you use external library it is good to have a grasp on what it is doing and how should you use it.