Closed RowanHarley closed 8 years ago
Ok, after debugging slither.io a bit, I've found that the first array sent has the first 2 byte's set to 0. Is that the same with every message sent
After debugging again, I found the 'g' packet had the first byte set to 0 and the 2nd byte set to 34. Is there a set number for these or what?
Those two bytes are one int16-value, most of them less than 10, the highest I've seen in ~2 minutes testing was 224. How are you debugging? Why do you think for 'g'-packets 34 could be a fixed number?
Well I noticed that the 'W' and 'F' packet were all set to 0 so I thought that they could be fixed numbers
But why does it matter what number the first 2 bytes are given. Is that for lag simulation or something
No, they are not all set to 0. Play for a few minutes and print out all values that are greater than 0 in W and F packets and you will get at least a few lines.
Also something else to try out: take the original client, modify it so that it sets the first two bytes to 0 for every incomming message and connect to an official server. The game will be a mess.
I don't know what these two bytes do, but you can just take a look at the original client code:
var c = b[0] << 8 | b[1], e = cptm - lptm;
0 == lptm && (e = 0);
etm += Math.max(-180, Math.min(180, e - c));
Then just track these values (etm, cptm, lptm) across the code to see what they do.
I've been looking at the client code but it doesn't seem to do much. Give me a sec. I'll have another look and tell you exactly what they do
Ok, so I looked up the variable's but the only one I could find matches with was etm
. This is what I found: etm *= lag_mult;
, etm *= Math.pow(.993, vfrb);
, t = etm / 8 * f.sp / 4;
, lagging && (etm *= lag_mult, lagging = !1);
and t = etm / 8 * f.sp / 4;
One of the first lines in ws.onmessage
:
lptm = cptm;
cptm = Date.now();
So lptm
is the time of the last message (Last Point in Time Message?), cptm
the time of the current message (Current Point in Time Message?).
So e
is the time between the two messages (0 for the first message) client-side.
Then etm
gets increased by e-c
(but max by 180, min by -180).
It's interesting that etm
never gets reset to 0
, but instead multiplied by 0.993
so that it will be lowered over time.
etm
is then used in t = etm / 8 * f.sp / 4;
for snake- and prey-movement-packets to move the snake/prey just a little bit further (server says the snake is at x=100 but the packet needs a few milliseconds to reach the client so by then the snake is at x=101).
If you always set etm
to 0, the game will mostly run fine.
So the big question is: how can we achieve this from the server-side?
I think that the first 2 byte's are used the simulate play. So the server must keep a track of how long player's have been playing for.
So if each connection has a timestamp from when they started, could that be used to get the values of the first 2 bytes
Not quite. (c
is usually very low, so it can't be the overall-playtime)
The server needs a timestamp of the last message. Then when it sends the next message, it calculates how many milliseconds have passed since that last message. The result will be the first two bytes.
Since etm
is about e-c
and e
is the time since the last message client-side, c
the time since the last message server-side, therefore e
and c
should be about the same, so etm
is about 0
.
That would make sense
So the server should create a timestamp whenever a message is sent, then take away that timestamp from the timestamp of the last message or is that right.
It should be newTimestamp - lastTimestamp
so that the result is positive.
@zrneely , you wrote "Time since last message from client" in the documentation. Shouldn't it be "Time since last message TO client"?
@sitano has also implemented it that way (time since last message to client).
Should I try implement it into my server and see how it work's?
Yes, I'm confident it will work :)
Ok, I'll have to do it tomorrow. I'm a bit busy at the moment. I'll tell you back here if it work's after I try it
Should I create a new function which does the subtraction or should I just add an extra parameter to each function for the timestamp?
Don't add an extra parameter, that would be a lot of duplicate code. You should be able to set these bytes just before you send the data, where you are independent from the packet type. (Before this line https://github.com/RowanHarley/Slither-Server/blob/master/index.js#L183 )
@Mat2095 , if I add the timestamp there, how will I change the first 2 byte's of the array as they are set inside different files
I've updated the code a bit but still got nothing:
This is part of lag compensation algorithm implemented in the client via comparing server time flow (which is measured in time intervals between packets server sent to the client) and client time (which is measured in time intervals of client receiving packets from the server) and coalescing them relatively.
Then client calculates lag compensation based on it, which is exactly how much client should render / simulate world behind or in front of the server time. Client tunes lag comp coef. softly.
https://github.com/sitano/slitherss/blob/master/src/server/game.h#L75
function send (id, data) {
client = clients[id];
if (client) {
currentTime = Date.now();
deltaTime = currentTime - client.lastTime;
client.lastTime = currentTime;
message.writeInt16(0, data, deltaTime);
client.send(data, {binary: true});
}
}
Also the client needs to remember only one time, not two.
Should I also add this code to the broadcast ()
function?
Again, to prevent duplicate code I'd suggest
function broadcast (data) {
for (var i = 0; i < clients.length; i++) {
send(i, data);
}
}
@Mat2095 I've tested it but it's still not working
Can you push your changes? What exactly doesn't work?
Ok I'll update my github code.
I've updated it. The code is here
gtg I won't be able to reply until tomorrow
Thank's @Mat2095 for helping to fix most of the glitchy snake movement! I'll close this issue
How do the first 2 byte's of each message work? Can I just set them to 0 or is there a special number I need to give them?