ClitherProject / Slither.io-Protocol

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

Snake Segments Movement #94

Closed gustavopsantos closed 5 months ago

gustavopsantos commented 5 months ago

I already took a look at the protocol, and the client/server repositories listed in, however im not being able to understand how slitherio handles the snake segments movement.

  1. I tried a approach of storing a history of head position over time, but this worked too perfect, in my approach if you make a circle with snake head, all the other segments will just follow it perfectly, this does not happen on slitherio, in slitherio after you make a circle with snake head, the tail shrinks it to the center.
  2. I tried another approach of making the segments to move to the direction of its parent segment when X Units far, in my opinion the behaviour is not more similar to slitherio, however when making circles the far segment stops following its parent as some parts of the snake is stopped

Another behaviour I noted when player slitherio is when you have a big snake and you start making circles at the same spot, at one point the tail stops moving, and the last segment starts collapsing inside your snake. After that, if you begin to walk in a straight line, at some point the tail de-collapse from inside your snake and it appears again.

So my question is, anyone know exactly how the segment movement is being handled? Thanks in advance!

Mat2095 commented 5 months ago

Yeah, this is something I didn't manage to reverse back when I worked on my custom client. Also on my client the snakes were shown longer on than they actually were over time, this might be related. As far as I understand, this is something that is done on the client and on the server separately. The client obiously has to do that to show the "slithering", and the server has to do it as well since the server has to do the collisions. But it is not sent over the connection.

I'd say the best way to solve this would be to reverse-engineer the official client, but that's not easy. I did a lot of reverse-engineering of the client, but I gave up on this particular problem.

Did you try running https://github.com/Gegy/Slyther or https://github.com/dickbalaska/slyther to check if they have this behaviour implemented? It might be hidden here, this loop that goes over the points/segments of the snake: https://github.com/dickbalaska/slyther/blob/slyther2/client/src/main/java/net/gegy1000/slyther/client/game/entity/ClientSnake.java#L178 . Although the code still uses many abbreviations and is more of a "literal" translation from the official client to Java, which I still find somewhat hard to read/understand. For example I don't know what "eiu" is suppose to mean, and they might not know either, it might be the obfuscated variable-name from the official client.

gustavopsantos commented 5 months ago

https://github.com/Gegy/Slyther seems to be outdated regarding to network protocol, however https://github.com/dickbalaska/slyther that is a fork from https://github.com/Gegy/Slyther works fine and it seems to have the correct movement behaviour implemented, but sadly does not have issues enabled on its repository

Mat2095 commented 5 months ago

I see. But maybe you can use it to reverse-engineer the behaviour. Like removing some of the code in that for-loop, see how the behaviour changes, to figure out what steps are required to implement it.

gustavopsantos commented 5 months ago

@Mat2095 I have some other questions as well.

  1. Does all the packets sent are sent in order? I havent found much online about websockets, are they built on top of TCP?
  2. I see the only packet who sends full snake body parts positions are packet s: add/remove Snake and that typically server sends max body parts as 411, so knowing that each body part takes 2 bytes (except for first one), its safe to say that s packet can weight something close to ~822 bytes, without accounting for skins, name and any other info? For me it looks weird to have a packet that size, but maybe it is what it is? Can websockets handle that traffic if many large snakes enters in local player field of view?
  3. After a snake enters fov and local player receives s packet, the snake is only further updated only using the following packets? e Snake rotation counterclockwise (?dir ang ?wang ?sp) E Snake rotation counterclockwise (dir wang ?sp) 3 Snake rotation counterclockwise (dir ang wang | sp) 4 Snake rotation clockwise (dir ang? wang ?sp) 5 Snake rotation clockwise (dir ang wang)
  4. In packet a: initial setup what is cst (snake tail speed ratio) and how its really used for? Maybe its a clue on how the movement works.

Thanks again!

Mat2095 commented 5 months ago
  1. According to the first sentence on Wikipedia about WebSocket, it is built on top of TCP, yes. So the order is preserved.
  2. According to https://stackoverflow.com/a/20658569 the maximum size of a websocket message is multiple exa-bytes, so that won't be a problem. Even with name and skin, the s message is just around 1 kB, I wouldn't see that as weird. And in practice, I guess most snakes are significantly shorter. I think a snake starts at ~10 segments.
  3. No, packets h, r, g, G, n, N also update snakes
  4. It might be related, yes. In my own client I didn't end up using this variable, but like I said, I didn't implement the "slithering" movement. You might be able to look into the official client source. Gegy used it here: https://github.com/dickbalaska/slyther/blob/a8ea072467716431358216f069aecea3e9da503c/client/src/main/java/net/gegy1000/slyther/network/message/fromserver/MessageSnakeMovement.java#L75
gustavopsantos commented 5 months ago

Thanks for all the fast replies ;)