<!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">
The client sends keys presses reliably to the server. It does not send,
for example, a fire event or some such thing. The server is responsible
for deciding what key does what.<br>
<br>
The server only has code to synchronize objects with the clients. In my
game I have a global ("global" as in it applies to all clients equally)
array which assigns each object a number. I also have an array of equal
size per client. These two arrays are compared to see which objects the
client has been notified about. It sends these messages (create,
remove) reliably. The rest of the time it just send data about these
objects unreliably. One thing to watch out for is to make sure the
client finds out an object exists before it gets updated. Other wise
things explode in such a way that is very hard to debug. On the same
token make sure a client does not get updates about an object that has
been removed.<br>
<br>
The down side of this system is that it can be <b>very</b> venerable
to latency <u>if not properly balanced and tested over different kinds
of connections</u>. I spent a week figuring out what worked and did not
work over cable connections, 10Gb fiber LAN, and my mobile phone. The
up side is that is it a very generic way to do things and allows me to
spend 100% of my time on the game; The server worries about when and
how to send updates without me handling special cases every time a
player sneezes. The client monitors an array object and blindly
displays what it finds. The server updates the client on a need-to-know
basis. Another up side is this can help keep cheating down in some
situations (IE the server does not send information about objects a
player can not "see").<br>
<br>
My game is a fast-paced, top-down shooter (speaking of generic...) so
the players never really stop moving if they want to have a chance at
survival. Once moving I use simple dead reckoning to keep them moving
until the next update. You could easily add some code that starts the
player object moving at a certain speed before the response is received
from the server and then continue normally (IE replace the object x, y
with what the server sent). I, however, did not find that necessary and
it would require the client being aware of more things (for example,
what key does what) than I am already doing in my project.<br>
<br>
As I implied, my client is virtually a dumb terminal with this system.
As a matter of fact, the stripped-down client code is something like
25% of the stripped-down, only required server code.<br>
<br>
Hope all this helps. It is not the most advanced system but it works
great for me and is an excellent entry-level exercise. Try to think
less in terms of what events should be sent reliably and unreliably.
"Bullet fired" and "player moved" are just abstractions that make a
machine that does lots of math look like pretty, coherant images.
Instead focus on the flow of data and what experimenation leads you to
and the code will write itself.<br>
<div class="moz-signature"><br>
<hr style="height: 1px;">
<p><span style="font-weight: bold;">Nicholas J Ingrassellino<br>
<a style="text-decoration: none;"
 href="http://www.lifebloodnetworks.com/" target="_blank">LifebloodNetworks.com</a></span>
|| <a style="text-decoration: none;"
 href="mailto:nick@lifebloodnetworks.com">nick@lifebloodnetworks.com</a></p>
<p style="font-size: 75%;">"<span style="font-style: italic;">The idea
that I can be presented with a problem, set out to logically solve it
with the tools at hand, and wind up with a program that could not be
legally used because someone else followed the same logical steps some
years ago and filed for a patent on it is horrifying.</span>"<br>
- <span style="font-weight: bold;">John Carmack</span> on software
patents</p>
</div>
<br>
On 11/24/2010 09:27 PM, Philip Bennefall wrote:
<blockquote cite="mid:F3BE05F1013449BDB760EE69414221A2@chicken"
 type="cite">
  <meta content="text/html; charset=ISO-8859-1"
 http-equiv="Content-Type">
  <meta name="GENERATOR" content="MSHTML 8.00.6001.23067">
  <div><font face="Arial" size="2">Hi <span style="font-weight: bold;"><font
 face="Times New Roman" size="3">Nicholas,</font></span></font></div>
  <div><font face="Times New Roman" size="3"><span
 style="font-weight: bold;"></span></font> </div>
  <div><font face="Times New Roman" size="3"><span
 style="font-weight: bold;">So you send key presses reliably, and then
wait for the server to respond back with a new state? What happens if a
player fires their weapon, for instance, is this sent reliably? I guess
my main confusion is what should and what should not be reliable
traffic. It would make sense to me that gunshots were reliable, where
as individual movement steps could be sent unreliably as you say. Now
let's say that the client takes a step, do you then render the movement
animation immediately before you get the response back from the server
and then correct it if the server refuses, or do you wait for the
server to accept the move? If the former, what happens if the client
moves but he's not allowed to, do you just silently bounce him back? If
the latter, wouldn't there be a noticeable delay between the key press
and the actual movement since we need at least one roundtrip for that?</span></font></div>
  <div><font face="Times New Roman" size="3"><span
 style="font-weight: bold;"></span></font> </div>
  <div><font face="Times New Roman" size="3"><span
 style="font-weight: bold;">Kind regards,</span></font></div>
  <div><font face="Times New Roman" size="3"><span
 style="font-weight: bold;"></span></font> </div>
  <div><font face="Times New Roman" size="3"><span
 style="font-weight: bold;">Philip Bennefall</span></font></div>
  <div><font face="Times New Roman" size="3"><span
 style="font-weight: bold;"></span></font>----- Original Message ----- </div>
  <blockquote
 style="border-left: 2px solid rgb(0, 0, 0); padding-left: 5px; padding-right: 0px; margin-left: 5px; margin-right: 0px;"
 dir="ltr">
    <div
 style="background: rgb(228, 228, 228) none repeat scroll 0% 0%; font-family: arial; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none; -moz-background-clip: border; -moz-background-origin: padding; -moz-background-inline-policy: continuous;"><b>From:</b>
    <a moz-do-not-send="true" title="nick@lifebloodnetworks.com"
 href="mailto:nick@lifebloodnetworks.com">Nicholas J Ingrassellino</a> </div>
    <div
 style="font-family: arial; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"><b>To:</b>
    <a moz-do-not-send="true" title="enet-discuss@cubik.org"
 href="mailto:enet-discuss@cubik.org">Discussion of the ENet library</a>
    </div>
    <div
 style="font-family: arial; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"><b>Sent:</b>
Wednesday, November 24, 2010 6:23 PM</div>
    <div
 style="font-family: arial; font-style: normal; font-variant: normal; font-weight: normal; font-size: 10pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"><b>Subject:</b>
Re: [ENet-discuss] Best practises for synchronizing states</div>
    <div><br>
    </div>
I question if the lag is as bad as you are expecting it to be. Some
connections and/or rural areas are worst than others but I am not sure
it will be as bad as you think. For example, if you look back at the
last few e-mails I sent to this list you will see my current project
treats the client as a dumb terminal-- only key presses are send and
object information is back unreliably 20 times a second. There is some
dead reckoning (the object speed and direction are sent to the client
and the client does that work while waiting for the next update) and I
do not have an issue even on my mobile phone.<br>
    <br>
My point is you should run a number of tests to see what you get. Make
sure to play with the rate the "server" (or in your case client to
client) sends data vs bandwidth usage. Make sure you do not flood the
line with too many tiny packets and that you process all packets in a
while loop (vs an if) to make sure you processes everything as fast as
possible. Another note on my project is that I do not wait on an timers
to process network events (as opposed to my log and display code that
only happens 60 times a second).<br>
    <br>
I think you may surprised yourself with what you can pull off in terms
of latency.<br>
    <div class="moz-signature"><br>
    <hr style="height: 1px;">
    <p><span style="font-weight: bold;">Nicholas J Ingrassellino<br>
    <a moz-do-not-send="true" style="text-decoration: none;"
 href="http://www.lifebloodnetworks.com/" target="_blank">LifebloodNetworks.com</a></span>
|| <a moz-do-not-send="true" style="text-decoration: none;"
 href="mailto:nick@lifebloodnetworks.com">nick@lifebloodnetworks.com</a></p>
    <p style="font-size: 75%;">"<span style="font-style: italic;">The
idea that I can be presented with a problem, set out to logically solve
it with the tools at hand, and wind up with a program that could not be
legally used because someone else followed the same logical steps some
years ago and filed for a patent on it is horrifying.</span>"<br>
- <span style="font-weight: bold;">John Carmack</span> on software
patents</p>
    </div>
    <br>
On 11/23/2010 10:00 PM, Philip Bennefall wrote:
    <blockquote cite="mid:E61F0244375C45C380DD8F39A8BAD8F7@chicken"
 type="cite">
      <meta name="GENERATOR" content="MSHTML 8.00.6001.23067">
      <style></style>
      <div><font face="Arial" size="2">Hi all,</font></div>
      <div> </div>
      <div><font face="Arial" size="2">This is a fairly lengthy email,
so I apologize in advance.</font></div>
      <div> </div>
      <div><font face="Arial" size="2">I am relatively new to ENet. I
have integrated it in my game engine and have successfully written a
game which is working perfectly. It is one of those finger twitching
action games where speed is of the utmost importance and delay is the
most evil thing in the world. The way I do it is to keep sending the
entire state for a player to the other party unreliably. The other
client then works out the events that "must" have occured by looking at
the differences between the last known state and the new one. This is
far from a perfect solution as it neither scales well nor provides for
very readable code. Here's a summary of how I'm handling things:</font></div>
      <div> </div>
      <div><font face="Arial" size="2">The game is a shooter where you
run a round on a 1d grid firing rocks at your oponent's palace. When a
rock hits a square on the other side it'll quickly begin piercing its
way through until that section of the wall crumbles. During that time,
the other player may use their hammer to defend the section.</font></div>
      <div> </div>
      <div><font face="Arial" size="2">I wrote an internal layout
description for myself before I started coding, which I then followed
to ensure proper handling of all possible situations.</font></div>
      <div> </div>
      <div><font face="Arial" size="2">---Start of Internal
Description---</font></div>
      <div><font face="Arial" size="2">The way in which this game
communicates over the network is fairly simple. The two players have a
direct connection established between one another, and they send out
their player state roughly 30 times a second. This player state
contains the current x position, the current throwing position which is
-1 if nothing is being thrown, and then a list of all the squares on
that player's side. For each square, two values are stored. The first
is the current resistance which is 20 on max, and 0 if the square is
destroyed. The second one is crumbling speed which is 0 if the square
is not currently crumbling, and a value in milliseconds otherwise. This
value is used to measure if two or more rocks have been thrown on the
same square.</font></div>
      <div> </div>
      <div><font face="Arial" size="2">When a new state is received
from the remote player, we have to analyse this information in order to
determine what changes that have occured and if we need to take any
action.</font></div>
      <div> </div>
      <div><font face="Arial" size="2">If a new x position is received,
we simply move the player's local variable to this square and play a
footstep sound.</font></div>
      <div> </div>
      <div><font face="Arial" size="2">If the new throwing position is
different from our old one, we can take a few actions depending on its
value:</font></div>
      <div> </div>
      <div><font face="Arial" size="2">1. If the new one is greater
than -1 and the old one is -1, the remote player threw a rock at us. we
play the throwing sound in the appropriate location, but take no other
action.</font></div>
      <div> </div>
      <div><font face="Arial" size="2">2. If the new one is -1 and the
old one is greater than -1, we can assume that the remote player hit us
and start the crumbling sequence for that square on our end. Naturally
if our square is already crumbled, the remote player will not get any
hit notifications from us. </font></div>
      <div> </div>
      <div><font face="Arial" size="2">3. If they both are greater than
-1, we can assume that the remote player hit us and so we activate that
sequence as above. We can also assume that the remote player made a new
throwing attempt in another location and that we didn't see the -1
state that came prior to it probably because of lag, and so we play
another throwing sound in the new location.</font></div>
      <div> </div>
      <div><font face="Arial" size="2">After this, we go on to scan the
game board and do the following for each square:</font></div>
      <div> </div>
      <div><font face="Arial" size="2">If the new resistance is greater
than the old one, the remote player hammered and so we play that sound.</font></div>
      <div> </div>
      <div><font face="Arial" size="2">If the new resistance is lower
than the old one, we can take four actions.</font></div>
      <div> </div>
      <div><font face="Arial" size="2"><br>
1. If the new resistance is 0 and the old resistance is greater than 0,
the square just broke so we play the appropriate sound and forget about
it.</font></div>
      <div> </div>
      <div><font face="Arial" size="2">2. If the old crumbling speed is
the same as the new one, this was a normal crumbling step and so we
play the appropriate sound.</font></div>
      <div> </div>
      <div><font face="Arial" size="2">3. If the old crumbling speed is
0 and the new one is greater than 0, this was a new hit so we react
accordingly.</font></div>
      <div> </div>
      <div><font face="Arial" size="2">4. If the old one is greater
than the new one and the new one is greater than 0, this was a new hit
on the same square.<br>
      </font><font face="Arial" size="2">---End of Internal
Description---</font></div>
      <div> </div>
      <div><font face="Arial" size="2">I realize that this is a lot of
very game specific information, and that's exactly my point. This all
seems like a very dirty hack to me, and I was wondering if any of you
can suggest a better and more scalable way of doing this while still
keeping latency to an absolute minimum?</font></div>
      <div> </div>
      <div><font face="Arial" size="2">Thanks in advance for any help!</font></div>
      <div> </div>
      <div><font face="Arial" size="2">Kind regards,</font></div>
      <div> </div>
      <div><font face="Arial" size="2">Philip Bennefall</font></div>
      <div><font face="Arial" size="2">P.S. I should perhaps mention
that this is a game for the blind; entirely based on sound, which is
why sounds are mentioned all over the place rather than graphics.</font></div>
      <pre wrap=""><fieldset class="mimeAttachmentHeader"></fieldset>
_______________________________________________
ENet-discuss mailing list
<a moz-do-not-send="true" class="moz-txt-link-abbreviated"
 href="mailto:ENet-discuss@cubik.org">ENet-discuss@cubik.org</a>
<a moz-do-not-send="true" 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>
  </blockquote>
  <pre wrap="">
<fieldset class="mimeAttachmentHeader"></fieldset>
_______________________________________________
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>
</body>
</html>