Need some help on Multiplayer FPS development

Hi all monkeys!!!



I’m posting here after a really hard search of resources about multiplayer game programming like many of you said me. The research results in a lot of questions that need some programming guru to be answered. I explain myself:



I’m trying to do a basic multiplayer FPS like UrbanTerror and many others and after some good lecture what I have to do is to implement an algorithm like this



Client



Handle user input and send it to the server

process all update messages arriving from server

render the new game state

repeat



Server



receives input from clients

process all inputs and update the game state

broadcasts all updates

repeat





Substantially this architecture is made of an authorative server that runs a physical simulation and sends the updates to the client, and those have only to render the game state and sample user input. The animations are executed on the server (because the simulation need to verify the position and collisions of every body part of a character, so i need to maintain the position of every anim-bone on the server) and together with special attivation effect and sound, are sent over the net with the update messagges.



This system have to include some other hard stuff like client side prediction and lag compensation. In many resources it is explained how to do some kind of lag compensation and the most used workaround is to interpolate the game state to make it be rendered abount 50 - 100 ms before the actual state, but the client side prediction is never (almost for what i’ve found) explained becuase all it is said is to assume that the client input is correct and instantly rendered. In a second moment all errors have to be fixed when the correct game state is received from the server but it is not explained how to do it. Another point that I’m not sure about is the input sampling, because i don’t know how to send it to the server and how to process it to instantly render the new game state to implement the client side prediction.



To clarify what i said i give some example:



CLIENT INPUT HANDLING

When a user press a button to move, for example, if I send it immediatly to the server (IMHO in TCP) i risk to not consider some bandwith and delay issues because in a second it is possible to send nearly 20 inputs that in tcp are obviously subject to delays. Another way to do it is to store a buffer of the buttun pressed and to send it to the server at a predefined rate, which results in an additional delay of the simulation.



Based on the above considerations, what is the best way to sample users input?



SERVER INPUT HANDLING

I think that the best way to process all users inputs is to store it in a buffer and process it at a fixed rate instead of enqueue every input and process it instantly in order to reduce the game state updating. The idea is: store input and update it just one time instead of update it multiple times.



What do you think about it?



CLIENT SIDE PREDICTION

Assum that I process all inputs like it is a local game, this can be true only for the local player, and what about enemies? The conseguence is that the local player is “forward” in the simulation time respect the other players resulting in an inconsistency of the game state… However, without considering the inconsistency, some kind of client side prediction requires the server to send a correct state of the game that fix the errors on clients. But i really don’t know how to do this because if i treat every message arriving from the server in a way that lets me do the lag compensation through entity interpolation, the fixing requires a special treatment for the update messages that made the entity be smoothed-position-fixed in a different way. Based on this i should have i cycle that interpolate the entity backword in the time, and a cycle that blends the position of an entity… I wonder what you would see in this case 0,o

Maybe i could assume that every update message simply correct the entity prediction only updating it’s state and doing the interpoltion but maybe in this way may happens some glitches…



What do you think about it??





Another thing that i don’t know how to implement is the interpolation:



Assuming that i have a system that include a SyncAppState that every update takes the most up-to-date message and interpolate it, i need a way to correct the case in which a syncmessage does not arrive (messages that update the game state are sent in UDP) otherwise when another message arrives it will interpolate the state in a way that causes a glitch of the before position to after position…



Those are really enough question so i’ll stop here for now XD.

I hope someone of you GAME-DEV-GURU can help me. Thanks a lot for your time monkeys!!! :slight_smile:



PS sorry my horrible english ahahahahahahhaha

@kazeshiro said:
PS sorry my horrible english ahahahahahahhaha


muHAUhauHAUHAUHAUHUHAUahu

Anyway, the MonkeyZone game might help you.

Monkeyzone doesn’t provide the aswer I need. It doesn’t consider things like lag compensation and entity interpolation

@kazeshiro said:
Monkeyzone doesn't provide the aswer I need. It doesn't consider things like lag compensation and entity interpolation

Yes it does, look again. There is a simple way for compensation of network lags, the input is delayed and then applied, lags within that time window are compensated. Also it uses physics on the client and server which provides for interpolation.

mmm I’m not sure I uderstand it…



The input is delayed? But is not the responsivness one of the most important thing ? if it is even more delayed it risks to feel strange for a player…



However, can you indicate me the parts that answare my question in MonkeyZone? I need something like:



The input is handled in this way …brief explanation… here ClassName (or ClassName1, ClassName2)



Lag compensation is done …brief explanation… here ClassName (or ClassName1, ClassName2)



Understanding everything alone without some explaination is really difficult and monkeyzone implements some other stuff like AI that make it harder to . What i need is something more specific becuse it is really diccult to find… And there aren’t other forums to ask advice on this topic becuase only you that use JME can understand what i’m talking about.



Maybe some guru can help me in order to pruce a good documentation about realtime multiplayer game development :slight_smile:



I’m sorry to sound pretentious, but I hope it is understood that my English does not allow me to be more polite XDXDXD

I think I get it, I might take a closer look at these ideas for my own game. There is a sliding window used to delay messages being applied on the client, and since physics is calculated on both server and client, interpolation is practically enabled because the interval between updates is short (since these can be performed locally).



But it doesnt interpolate between messages received from the server though? Does it still look okay?

My own application simulates the world only on the server to maintain an authoritative architecture. The only thing that is processed on the client is the prediction of the local player, rather the local camera movement to immediatly show the view-result.



It is true that interpolation is pratically enabled but to maintain more consistency i need to interpolate all entyties explicitly a further delta where delta is calculated on the client and is equal to → delta = (medium_latency) / 2 .



Medium latency is calculated in this way:



medium_latency = arithmetic_mean(messsage_from_server_time_travel * 2)



To calculate messsage_from_server_time_travel i put a timestap of the server time on each message (it is needed by many things).

The client stores the most up-to-date message timestamp and subtract it from the next message timestamp. In this way I have an average travel time (also knowing that my server sends an update state message 30 times per seconds)



To tell the true, i don’t know if this system works well because the delay in my home is about ~1 ms so i can’t try a delay of 100ms.



But i’ve made some research on the way industrial games do this job. In many forums it is never referred to any kind of interpolation or client side prediction because the master servers hava a max delay of 50 ms that is acceptable to a user experience. Obviously servers accept connections arriving only from the same continent in facts games like Vindictus has 3 big areas that are North US, Europe, east Asia. Another thing that i noticed is that the entire game is made of party-instantiated-rooms where the server runs on a party member machine called Leader.



After many tests i’ve understando that nothing like entity interpolation is done. Assuming that a tcp packet spends 25 ms to travel from west to east the north America, maybe this kind of optimizations are not still required because it will riks to increment only the delay a user can feels.



What do you think about that??

This thread was too long to read to catch up on so I don’t know if you mentioned having read these before. I consider them required reading for real-time multiplayer game programming:



http://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

http://developer.valvesoftware.com/wiki/Latency_Compensating_Methods_in_Client/Server_In-game_Protocol_Design_and_Optimization

Good times of head-shots :smiley:



@pspeed



Yes, i read those documents and after the third time ( XD ) i’ve understood how to implements many things.

But the problem, like i said before, is that i don’t know how to test the system performance because in my LAN there is about a ms of delay.



However I started this topic with much question that are not treated; one example is how to sample user input.

Another thing that is not mentioned is the prediction of not-local players because predicting the local player implies that all other player are somewhat backward in the simulation.



Paul, can i ask you how you made this feature in your game? i’m sure you have breaked your mind a lot on this thing, maybe you can help a newby XD

I predict local player movement but it is still rendered at the same delay as everyone else. I use a delay of 150 ms… so whatever the “simulation time” is, the visualization is rendering 150 ms ago. There is a render delay just like in those articles. And right now, I 100% trust the clients which will change in one of the next releases.



For testing, no matter what you do you will need to have real world test. That’s ultimately why I put out my recent network test. Having real users from around the world give me performance metrics has been hugely useful. What I can offer from that so far is that for anything under 200 ms round trip ping (through spidermonkey with UDP), 100% of the packets seem to make it. And from there, the ping times seem to go up to nearly a second or more and 50% or more packet loss.



I have not seen a “middle ground” so far. I put another test out recently to see if adjusting some parameters can improve the worst connections but so far none of those testers has retested.



For my own testing, I have parameters that I can use to randomly drop packets and/or add random delay (best on the receive side, by the way)… but it’s no substitute for the real world. It can just help me find the threshold where things get too bad to play.

Ok, assuming a delay of 100 - 150 ms ago, can you tell me the best way to implement the interpolation? Obviously i’ve seen the transforme.interpolate() but i don’t know well when to use it. For example:



I have a message buffer that stores all update messages arriving from server.

Is it good to make something like this in a AppState?



[java]

while(there are messages){

newTransform = Transform.interpolate(actualTransform, messageTransform, 100ms)

if(is last message){

player.setTransform(newTransfomr)

break;

}

actualTransform = newTransform

}

[/java]



I think that this way isn’t the correct way…



CLIENT PREDICTION:



I have an input sampler that handle player inputs and put those in a buffer and at a prefixed rate it does something like:



[java]

while(there are inputs){

newTransform = process input(actualTransform)

if(is last input){

player.setTransform(newTransfomr)

break;

}

actualTransform = newTransform

}[/java]



but i don’t know how to correct the prediction based on the server because when a message arrives i just do the interpolation…

And also if i can chek if a message refers to the local player would not know how to correct the player state becuase the only thing that I can do is to correct the state simply updating it…



player.setTransform(messageTransform)





Help me pleaseeee!!! XD

It’s hard to explain exactly what I do but as the network messages come in (and as my local prediction simulation is occurring) I add the location+orientation+time to a buffer for each object. The time is simulation time as set by the server (and my local time and server time are synched by the current latency).



So then the rendering loop looks in this buffer to get the two location+orientation that spans the current rendering time (simulation time - frame delay) and interpolates between them to set the location+orientation on the spatial.



That’s it from a high level, anyway.

Well!!

Now, the only thing that i have to handle is the user input because i have to know how to send it to the server.

Assuming a player does 15 inputs / second (for example) and those are stored in a buffer, then this buffer have to be sent to the server.

IMHO inputs are very important to a good gameplay so it have to be sent in TCP but it can generate a traffic of something like 10 -15 messages per second and it can slow down the responsiveness of the system, in facts update messages from server are sent in UDP in order to avoid this.



How do you handle this issue?



PS Thanks a lot for your help :wink:

I don’t remember exactly and don’t have the code in front of me at the moment… and I haven’t touched it since April (though I’m about to rewrite a bunch of it soon).



But as I recall, I keep a state and position buffer that is updated with the physics tick of 60 FPS or so… and I send this 20 times a second to the server. So each message to the server will have 3 state “records” in it. I could be sending more often, I can’t remember… in which case there will be fewer messages. Ultimate round trip latency will ultimately be very important to me but isn’t so much at the moment.



Right now my server completely trusts the client so the position part is the only part that I pay attention to, but the state records also have flags for the current input state so that I can do proper physics calculations on the server when I need to. I could drop the position completely at that point, I guess but it seems like it could be useful for debugging for a while.

Mmmm, ok.



Our systems works differently because mine is full server controlled. Can you give some advice on how to handle messages of “button pressed” to send to the server?

@kazeshiro said:
Understanding everything alone without some explaination is really difficult and monkeyzone implements some other stuff like AI that make it harder to . What i need is something more specific becuse it is really diccult to find..

Basic examples are too few, a project is too much.. You gotta start somewhere eh? The compensation code is in the NetworkManager class..

It’s not really about button presses but movement state. When the player presses ‘W’ then the “move forward” flag is set. This is the same thing the client-side physics thread is using to predict the player’s movement. Flag is on, move forward. Flag is off, stop moving forward. These are the inputs to acceleration basically. I think I keep five different bits right now, I can’t remember for sure.



…so in sync with the physics tic, I snatch a copy of the current flags and buffer them for sending to the server. That way the server physics thread has exactly the same information that the client’s predictive physics thread had. The tricky part is when the server and client will differ and the client has to somehow be resolved to reality… and there are a few ways to handle that. I still have to play around with that and have a few different strategies that I will attempt.



I trust location now just because it was easier to get something running. Eventually the server will compute client position from state + orientation… so I’ve designed for that.

@normen

Basic examples are too few, a project is too much.. You gotta start somewhere eh?


Normen, you have wasted a lot of words since i started asking information about multiplayer development.
Nobody forced you to answer my question and everytime you did it seemed to be a nuisance for you, and many times I felt teased by your words. And all this has happened only because you didn't write:

The compensation code is in the NetworkManager (PhysicsSyncManager) class..


There is much between TestChatClient/Server and MonkeyZone especially for a JME newby. I think that a reverse engineering on MonkyZone is not so much easy as you think and certainly I'm not stupid. Don't I know much about multiplayer development? Absolutly
Am I not be an experienced programmer? Sure. But i'm learning like everyone in this forum.

I am not criticizing JME, you work or just you. I'm criticizing you approach in helping other people. For example when i asked why after installation of JMP there were something that didn't work, you told me: "RDFM" and the problem whas that i didn't enable nightly updates.
You take for granted that everyone works with JME for years when i've only forgot to eneble the nightly.

From here on now, when i will ask something in the forum if you want to help me, well. I'm very happy when someone spends it's time helping me, but if you are bored please, let other people write something useful and don't waste posts on the forum.

Thanks


@pspeed

It’s not really about button presses but movement state. When the player presses ‘W’ then the “move forward” flag is set. This is the same thing the client-side physics thread is using to predict the player’s movement. Flag is on, move forward. Flag is off, stop moving forward.

so in sync with the physics tic, I snatch a copy of the current flags and buffer them for sending to the server. That way the server physics thread has exactly the same information that the client’s predictive physics thread had.


This is exactly what i've tried to say XD however my problem is that i don't know which way to use to send it to the server because maybe there are too messages that have to be sent and a TCP manner risks to slow the entire communication system. However sending it in UDP does not garatee that the message arrives and is processed. How have to be resolved this issue???

Thanks a lot for your help
1 Like

I’m pretty sure that I send client state updates to the server as TCP. They are small. Since I’m already buffering the state, the other option is to keep resending some period of time until I get information from the server that it has received up to a certain time. When the client is no longer trusted, I may have to do that to keep latency down.



In that case, when the server sends my client back state information it would somehow include the time of the last message it received from me. I can then clear my buffer up to that point. If the buffer gets too deep then the connection is really bad and I’d have to resynch everything or if it happens often, boot the player or something. Given that the server will be sending the client a position that is vastly different than where the client thinks it is… it may be ok to just cut off the earlier state for this buffer when it gets older than a second or two.



It’s possible to pack many many many seconds worth of client state information into a message before exceeding MTU. I’ve gotten the necessary state information down to 7 bytes or so + the message overhead. And since if the state is old enough it becomes completely useless then TCP may be problematic and it’s probably better just to send some redundant state each time. I’m liking the idea even more now that I’ve typed it. :wink: