2
\$\begingroup\$

I've got a 2D java game with an infinite generating world with a player and other entities. I wish to make this game multiplayer and have done my research. I read this article multiple times and is what I want to implement.

In short: Client acts as terminal sending input to server. Server is authoritative and controls the game, deciding the result of the input from the client and sending back the relative info. Maintaining performance the server each 100 milliseconds keeps a list of all received input from the client and only then processing it. Client predicts its own game state by its input and when it received the processed state from the server it validates if the state is correct, otherwise corrected by the server.

E.g. Player pressed D -> client sends 'move right" input to server -> client predicts its own location to avoid choppy movement -> server finishes 100ms wait and processes all received input -> server decides new location of player by received input -> server sends the decided location to client -> client validates its current predicted location by the server received one, corrects the client if neccessary.

My question: How do I properly send all the inputs to the server and in what format? And how to receive different kinds of output back?

I shouldn't just send the entire player object (which has all inputs such as if WASD keys are held down), should I? Seems way too bandwidth and CPU intensive. Also seems overkill since most properties at each update will be false. Server only needs to be aware of what happened, not what didn't happen. Can I somehow only send single commands to the server? No strings with switch statement please.

How to receive different kind of information from the server? Player needs new world chunks when it moved. Needs to validate its own world position against the server. Needs to check if client inventory is same as server.

\$\endgroup\$
0
\$\begingroup\$

You certainly could send the whole Player object to the server. Java makes that quite easy with ObjectOutputStream. But as you recognized yourself, this is usually a quick&dirty method, because it sends a large amount of redundant and irrelevant data.

A good network protocol should only send changes. That means you send one message when a player starts doing something and another message when they stop doing it. How exactly such messages look is up to you.

One option would be to make each message a byte[] where the first byte says what kind of message this is (for more complex games which need more than 256 message types you might have to extend this to two bytes) and the following bytes are a message-dependent payload where the size depends on the message type. For example, a "I start walking" message might be structured like this:

  • 1 byte saying that is a "I start moving" package
  • 1 byte telling you the direction (assuming you have just 8-directional movement. When you allow movement in any direction, 256 possible angles might not be enough)

The reply from the server could then be:

  • 1 byte saying that this is a "Something started moving" package
  • 2 bytes Object Id
  • 8 bytes start coordinates (to make synchronization more reliable)
  • 1 byte direction

All messages which occur during the same game tick should be collected and then sent over the socket together at the end of the tick. When you don't do this, then the messages might end up in individual IP packets, and each IP packet has a fixed overhead which might then be more data than your actual payload.

\$\endgroup\$
  • \$\begingroup\$ Sending the object thanks to your suggestion i have figured out how im going to implement it. But im puzzled on the server return obj. You mention using an ID too. But then in the client how do I recognize the object? using a switch statement? Is there someway of recognizing the objects and passing them to their constructor or defined method? Thank you very much for the answer, it was helpful. \$\endgroup\$ – Krijn van der Burg Nov 27 '17 at 20:15
  • \$\begingroup\$ @KrijnvanderBurg When the server tells the client that some object did something, the server needs to tell the client which object it is. An easy way for that is to assign incrementing ID numbers to every object spawned on the server. The server would tell the clients the ID number when it informs them about the existence of that object. For fast lookup on the client, you could use a HashMap<Integer, GameObject>. When your game creates objects but rarely if ever removes them, you could also use an ArrayList where the index corresponds to the object ID. \$\endgroup\$ – Philipp Nov 27 '17 at 20:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.