ClitherProject / Slither.io-Protocol

The Documented Slither.io Protocol
151 stars 37 forks source link

How do first 2 byte's of each message work? #70

Closed RowanHarley closed 8 years ago

RowanHarley commented 8 years ago

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?

RowanHarley commented 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

RowanHarley commented 8 years ago

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?

Mat2095 commented 8 years ago

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?

RowanHarley commented 8 years ago

Well I noticed that the 'W' and 'F' packet were all set to 0 so I thought that they could be fixed numbers

RowanHarley commented 8 years ago

But why does it matter what number the first 2 bytes are given. Is that for lag simulation or something

Mat2095 commented 8 years ago

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.

RowanHarley commented 8 years ago

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

RowanHarley commented 8 years ago

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;

Mat2095 commented 8 years ago

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?

RowanHarley commented 8 years ago

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.

RowanHarley commented 8 years ago

So if each connection has a timestamp from when they started, could that be used to get the values of the first 2 bytes

Mat2095 commented 8 years ago

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.

RowanHarley commented 8 years ago

That would make sense

RowanHarley commented 8 years ago

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.

Mat2095 commented 8 years ago

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"?

Mat2095 commented 8 years ago

@sitano has also implemented it that way (time since last message to client).

RowanHarley commented 8 years ago

Should I try implement it into my server and see how it work's?

Mat2095 commented 8 years ago

Yes, I'm confident it will work :)

RowanHarley commented 8 years ago

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

RowanHarley commented 8 years ago

Should I create a new function which does the subtraction or should I just add an extra parameter to each function for the timestamp?

Mat2095 commented 8 years ago

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 )

RowanHarley commented 8 years ago

@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

RowanHarley commented 8 years ago

I've updated the code a bit but still got nothing: screenshot 3

sitano commented 8 years ago

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

Mat2095 commented 8 years ago
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.

RowanHarley commented 8 years ago

Should I also add this code to the broadcast () function?

Mat2095 commented 8 years ago

Again, to prevent duplicate code I'd suggest


function broadcast (data) {
    for (var i = 0; i < clients.length; i++) {
        send(i, data);
    }
}
RowanHarley commented 8 years ago

@Mat2095 I've tested it but it's still not working

Mat2095 commented 8 years ago

Can you push your changes? What exactly doesn't work?

RowanHarley commented 8 years ago

Ok I'll update my github code.

RowanHarley commented 8 years ago

I've updated it. The code is here

RowanHarley commented 8 years ago

gtg I won't be able to reply until tomorrow

RowanHarley commented 8 years ago

Thank's @Mat2095 for helping to fix most of the glitchy snake movement! I'll close this issue