<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
  <meta content="text/html;charset=ISO-8859-1" http-equiv="Content-Type">
  <title></title>
</head>
<body bgcolor="#ffffff" text="#000000">
What are you babbling about? Games like Unreal don't send input?...
weird... so how does the server know how the client moves? Yeah...<br>
<br>
Can anyone answer the question? What happens when the clients drops to
a low frame and tries to send input? Lee? I mean come on...<br>
<br>
Don't mean to sound like an ass but come on i asked a simple question.<br>
<br>
Looks like i'm on my own again..... like always<br>
<br>
<br>
Steve Williams wrote:
<blockquote
 cite="mid:668C245C6BB6D84594549A1A418E598A0EDC6E608C@ms-exch2.kromestudios.com"
 type="cite">
  <pre wrap="">Games like Unreal and many other FPS games do not generally send inputs over the network.  They send a requested position update, which the server processes, then the server sends back the actual position (after taking into account the requested position updates of all clients and AI characters).  The client takes the actual position, moves its player to that position, and continues.

Client prediction involves the client assuming that the server will agree with what the client thinks might happen, so while the server is processing the requested position update, the client is moving its player to where it thinks it will end up.  When the actual position is received from the server, the client adjusts its players position to match the position the server said it was supposed to be.

This also allows dropped network packets to be handled correctly.  You may see the player jump or snap to the actual position as given by the server after a dropped packet or two, but the positional updates take care of missed packets.

--
Sly


-----Original Message-----
From: <a class="moz-txt-link-abbreviated" href="mailto:enet-discuss-bounces@cubik.org">enet-discuss-bounces@cubik.org</a> [<a class="moz-txt-link-freetext" href="mailto:enet-discuss-bounces@cubik.org">mailto:enet-discuss-bounces@cubik.org</a>] On Behalf Of Jacky J
Sent: Monday, 17 March 2008 11:56 AM
To: Discussion of the ENet library
Subject: Re: [ENet-discuss] fps networking

Hey Lee i appreciate all the info.  I'm still a bit confused about the
client timestep:

For simplicity, let's say we have a game that has only 8 directions (no
mouse, jumping, etc).

Does the client timestep contain just one move command or does it
contain multiple?  "move command" meaning one of 8 directions that are
applied during a frame.  So for example our game runs at 60 fps, and
we're sending at 20hz. If the server wanted to exactly recreate a
sequence of moves that the client does, it would have to know all of the
directions that were applied at every frame.  That means in our example,
in an ideal world, each client-&gt;send() function would send 3 directions
with it. Does this sound right?

Now of course if the client frame rate dropped to 20 fps, it would only
be sending one direction per timestep. But the client wants to be
traveling as much distance as it would if it were running at 60fps, so
locally it would apply some physics update multiple times to make up for
the lost frames.  How does the server account for this?

It seems like in this article they do one move command per timestep:
<a class="moz-txt-link-freetext" href="http://unreal.epicgames.com/Network.htm">http://unreal.epicgames.com/Network.htm</a>

Do you have any good examples of source code i could look at?  I looked
a cube but it seems like it was doing the client-side physics method
rather than client/server cosimulation (correct me if i'm wrong).

Thanks again.


Lee Salzman wrote:
  </pre>
  <blockquote type="cite">
    <pre wrap="">FPS is a spectrum of things you can do, more than a set way. The ways,
however, are far different from, say, a MMORPG where latency is just
usually accepted by players: in a twitch FPS game, latency must be
destroyed at all costs - latency is totally evil, no exceptions. But
even within the spectrum of FPS networking, each  way comes with its own
trade-off. They more or less boil down to the following:

Trade-off #1: fixed rate physics, or variable rate physics. You need to
select a rate at which to run the physics simulation, i.e. 50 Hz, 100
Hz, etc. Now if  the rendering FPS is higher than the physics rate,
then you will need to interpolate between two physics steps to have the
game  not  look all jerky, since if the game is rendering at 100  FPS
and physics is only simulated at 50 Hz, your view point is only changing
50 times a second, so half of those 100 FPS are going to waste. If you
use variable rate, you still choose a minimum rate at which to run the
physics, but if the FPS happens to be higher,  then you run physics at a
higher rate. For example, say, you settle on 50 Hz, meaning each physics
step is 20 milliseconds. If one frame of rendering took up, say, 102
milliseconds, then you would do 5 physics steps, and if doing fixed rate
physics, you would bank those 2 leftover milliseconds for "credit" on
the next frame. If you are doing variable rate physics, you just go
ahead and do an extra time step using those leftover 2 milliseconds
immediately. Fixed rate is probably better if you can just afford to run
the physics at a high rate these days, and variable rate kinda requires
the client to be authoritative on physics simulation.

Trade-off #2: co-simulation, totally client-side physics, or lock-step
simulation.

- In a lock-step simulation, you would just send player input reliably
to the server, the server would simulate physics, and tell the player
where everything is at. This is a great evil that should never EVER be
used in an FPS game because everything requires a silly round-trip that
destroys twitch gameplay on even modest pings. I only mention it because
you should NEVER use it. ;)

- Totally client-side physics. Each client just runs its own physics,
and broadcasts its position at a fixed rate to all other clients (either
P2P or by sending it through the server which just broadcasts it - the
server is just a dumb simple broadcaster in this case), i.e. you send
out your position to other clients say 20 times a second as unreliable
data. You don't really care if the position gets lost at all, since
another one is coming behind it right away. On the receiving end, each
client needs to smooth out the positions it is receiving from other
clients, since it is much less the rendering FPS. You can do this by
either buffering one or two steps worth of positions, and interpolating
between them - i.e. you wait till you've gotten at least two position
updates from a client, then over some time period (say 50 milliseconds
if updates are happening at 20 Hz), you interpolate the position between
them. Another approach is to just send necessary physics simulation data
(like player velocity), and keep simulating the client locally starting
from the last position/velocity update you got. These two things can be
combined, for instance just always simulate the player locally from the
last time you got an update, however when an update comes in, record the
different in between the update and the current position (the "snap"),
and instead of applying the snap immediately, smooth it out over the
next 50 milliseconds or so. Keep in mind clients are authoritative, so
you need to take care of cheating by non-technical means (i.e. player
moderator system).

- Co-simulation. The server and client each run their own corresponding
loosely coupled simulations. The client runs on the ASSUMPTION its
simulation is always right i.e. when I shoot, the client assumes I hit
what I actually did, or if I try to move, the client just moves locally.
For EACH client time step the client is sending all the input (i.e.
player movement directions and mouse look) to the server, so the server
can exactly recreate each time step. This should be done via delta
compression of an unreliable packet stream to avoid the cost of reliable
packets. First choose a fixed rate, i.e. 20 Hz. Now every time step is
numbered, so they form an ever-continuing sequence. So when you send a
time step to the server, the server knows the sequence number of the
last time step it got. It sends this sequence number back as a periodic
ack (unreliable, of course, but best piggy-backed on other
server-&gt;client updates) so the client knows the last sequence number the
server received (or at least some sequence number less than that in case
the ack gets lost in transit). Every time the client sends an update to
the server, it sends all time steps starting at the last sequence number
the server verified receiving (via that ack the server sent to the
client), up to the most current time step.  So the client must buffer
all time steps it is sending to the server, until it has verified the
server has received them, and is basically just sending this buffer at a
fixed rate (again i.e. 20 Hz) to the server, removing stuff from the
front of the buffer as it gets verification the server actually got it.
If this buffer grows unreasonably large (i.e. some threshold like a few
KB or more where sending it 20 times a second until the server gets it
becomes stupidity), you can just "bail out" at the cost of a possible
round-trip timeout stall by sending the client-&gt;server update as a
reliable packet, and just clearing the buffer (since you know the update
will get there). You just don't want to use the bail out option on every
packet, since you want to avoid the latency of reliable traffic at all
costs. Smart encoding of a time step with a simple run-length scheme and
you can get the average size of a time step in transit down to only a
few bits since you may only have one of 8 compass directions, 2D mouse
coords, and maybe some boolean modifiers like jump/crouch, and certain
aspects like the direction don't change very fast. Various events like
shooting , picking up items, etc. should be properly sequenced into this
same stream as well (but encoded via some exceptional means/special
prefix since they are uncommon). You just put these in a server-side
queue for each player, which the server dequeues and runs for each
player at each of its time steps. If it doesn't have any time step info
for a client at a particular server time-step, you can either keep the
client moving in whichever direction he was going, or just have him
stand there - whatever seems most reasonable, but you give the client a
"credit" for that time step, so that when more time steps come in over
the net, you apply them immediately so long as the client has credits.

Now the tricky part. The server then runs its simulation at whatever
fixed rate you decided along with the client. The server must then send
out server-&gt;client updates on positions/velocities of other clients in
the world. You can do this by jumping through hoops to do the whole
delta compression of each other client's input stream to get it from the
server-&gt;client, but this just becomes stupidly complex and hoggish of
bandwidth (call that Trade-off #3). You are better off just sending out
the updates from server-&gt;client much as you would in the "totally
client-side" case, i.e. just a simple unreliable update containing the
positions/velocities of everything, again at some fixed rate like 20 Hz.
If the update gets lost in transit, you don't care since another one is
coming soon. However, you want to tag each of these server-&gt;client
updates with a sequence number. So when the client gets an update, it
knows the sequence number of the last one it got. The client just
locally moves the physics ahead using its own fixed rate simulation
(that hopefully works in the same way as the server's, unless the client
is cheating by modifying it). Now when the client interacts with an
object, i.e. aims at it and shoots it, it can tell the server ("Okay, I
shot player Bob, who was at the position stated in server-&gt;client update
#42, from 60 milliseconds had elapsed since that updated, so I had moved
Bob ahead locally 3 time steps from that position.") The server must
buffer the results of each time step of its simulation up to a
reasonable amount of time (say 1 second). So when the server receives
your shot request, it looks in its buffer for physics update #42 (or if
this is a time step &gt; 1 second old, just takes the oldest from the
buffer instead), find Bob's position in this buffered physics update,
predicts him ahead 60 milliseconds/3 time steps in the SAME EXACT WAY
the client would have had it got no more updates during those 60
milliseconds, and then applies your shot to Bob at that position. If you
are quantizing/truncating numbers to send them from server-&gt;client in
the updates, you must simulate this on the server when pulling Bob's
position out of the update as well. This way aiming/shooting is
completely WYSIWYG, no disgusting having-to-lead-your-shots-ahead type
of gameplay like in various Quakes.

Now there can be some small round-off differences from processor to
processor, so the simulation between the client and server may drift
over time. So every  so often the client must either send  what position
it is at, or the server sends what position it has the client at to the
client. In either case, you check if they differ by a substantial
amount, and if so the server sends all the raw/unquantized physics info
needed to the client for them to sync back up (causing an ugly snap, of
which the only sane way to hide is interpolation). If you can manage to
implement the physics entirely without floating point such that there
will never be any drift and hence no snaps, go for that instead (but
seems largely impossible in this day and age with more complicated physics).

Hopefully this all adequately confuses you. :)

Lee

Jacky J wrote:

    </pre>
    <blockquote type="cite">
      <pre wrap="">I'm having a hard time getting my head around some concepts used in
first person shooter style games, namely sending user input.  I
understand pretty much everything else: client side prediction, object
replication, etc.

So here are my questions and thoughts:

1. The client continuously sends its input to the server.  This is a
packet that might have a bit field for each button or key. For example
WASD might take 4 bits, and another few for jump or fire.
So how often do i send these packets? Is it on a timer or do i send it
as much as the clients presses those buttons?

2.  My biggest concern: What if the client is bogged down to 5 fps,
meaning in the best case, the server is receiving those inputs every 200
ms.  Surely the server needs to update the client based on the client's
own framerate, because if you're moving the player 1 unit per input, the
player will move a lot slower if it's updating less per unit time.

My initial thought was to send some sort of lastsendtime to scale the
player's input, but then it seems like you could cheat and just send
really large values to make it seem like you're running at a low fps.

What all should i be sending to the server, and what actions should the
server be taking based on those inputs?

I have a simple techdemo/game setup using enet called godmode.
Everything is pretty much set up except for sending client inputs
correctly.

<a class="moz-txt-link-freetext" href="http://code.google.com/p/godmode/">http://code.google.com/p/godmode/</a>

Thanks
_______________________________________________
ENet-discuss mailing list
<a class="moz-txt-link-abbreviated" href="mailto:ENet-discuss@cubik.org">ENet-discuss@cubik.org</a>
<a class="moz-txt-link-freetext" href="http://lists.cubik.org/mailman/listinfo/enet-discuss">http://lists.cubik.org/mailman/listinfo/enet-discuss</a>



      </pre>
    </blockquote>
    <pre wrap="">_______________________________________________
ENet-discuss mailing list
<a class="moz-txt-link-abbreviated" href="mailto:ENet-discuss@cubik.org">ENet-discuss@cubik.org</a>
<a class="moz-txt-link-freetext" href="http://lists.cubik.org/mailman/listinfo/enet-discuss">http://lists.cubik.org/mailman/listinfo/enet-discuss</a>

    </pre>
  </blockquote>
  <pre wrap=""><!---->
_______________________________________________
ENet-discuss mailing list
<a class="moz-txt-link-abbreviated" href="mailto:ENet-discuss@cubik.org">ENet-discuss@cubik.org</a>
<a class="moz-txt-link-freetext" href="http://lists.cubik.org/mailman/listinfo/enet-discuss">http://lists.cubik.org/mailman/listinfo/enet-discuss</a>




This message and its attachments may contain legally privileged or confidential information. This message is intended for the use of the individual or entity to which it is addressed. If you are not the addressee indicated in this message, or the employee or agent responsible for delivering the message to the intended recipient, you may not copy or deliver this message or its attachments to anyone. Rather, you should permanently delete this message and its attachments and kindly notify the sender by reply e-mail. Any content of this message and its attachments, which does not relate to the official business of the sending company must be taken not to have been sent or endorsed by the sending company or any of its related entities. No warranty is made that the e-mail or attachment(s) are free from computer virus or other defect.

_______________________________________________
ENet-discuss mailing list
<a class="moz-txt-link-abbreviated" href="mailto:ENet-discuss@cubik.org">ENet-discuss@cubik.org</a>
<a class="moz-txt-link-freetext" href="http://lists.cubik.org/mailman/listinfo/enet-discuss">http://lists.cubik.org/mailman/listinfo/enet-discuss</a>
  </pre>
</blockquote>
<br>
</body>
</html>