I've been developing games as a hobby for a few years now and one thing that I like to do is to replicate games or a specific mechanic about them to understand how they work. I am sorry in advance this question might be a little bit lengthy but I am struggling to explain exactly what I am trying to achieve and the context around it in a more succinct way. A few months ago I decided to replicate something similar to how movement and combat work in League of Legends, and not to get too much into detail I ended up writing a server in C and a game in Unity that was server authoritative that replicated League of legends very well and I was quite happy with it. At that time I didn't predict client movement because Lol also didn't do that, and I thought that predicting pathfinding could be quite challenging to do, but I still had interpolation on the client and stuff like that so movement and combat in general was pretty smooth.
Sorry for the long intro but I thought it had important context for the question itself. Last week I decided to get that project and change it so that I would move with directional movement, like WASD or using a controller, instead of clicking and calculating a path. Implementing that without prediction was easy enough, I started by every time that the direction input changed I would just change that direction to the server which would then apply on every tick a movement based on that direction, and that worked great. I felt like with directional movement implementing prediction would be a lot easy so I decided to do that and I got stuck on a bunch of different problems implementing that without opening opportunities for users to cheat (I don't have any plans of actually making a game with this now but the whole purpose is to implement something as close as possible to a real world scenario so I can get a good understanding on how it works, so I want to avoid room for cheating as much as possible).
I've read a few good articles about the topic, mainly about how Quake does it and one from Gabriel Gambetta about how they do it (I did the same back when I made my first server authoritative implementation). So my first instinct was that for a given input the player would move an X amount of space for a given speed that the client already has, so I could just replicate that formula in the client. The main issue that I got right out the gate is that I couldn't match the exact amount of movement that the client and the server would apply for the player. For example assuming that the user has a latency of 10ms, if at time 0 I tell the server hey, I am moving to direction (1, 0) the server would get that information a time 10 and could start moving at that direction as soon as it gets the message, and would stop when the user sent direction (0, 0). The issue is that if the user sends at time 10 for example that the direction became (0, 0) if we assume a perfect scenario where the latency is exactly 10 like it was before then everything works great, it would receive the direction (0, 0) at time 20 and both would move exactly 10ms in that direction, in reality, that is almost impossible to happen, there is always some instability that makes it so that the interval between those 2 messages don't match the amount of time that the client moved. I could of course include the client time which the client started to move and stopped and move based of that, but I feel like that would allow cheaters to move more than they can. Also in the current game there are things like changing the speed, or getting stunned and rooted, that increases the complexity of this a lot since on cases like this there would always be a de-sync between the server and the client, but I am trying to solve a more basic scenario that don't include this cases first.
I feel like I am lacking some basic idea on how to implement something like this, the articles that I've mentioned seems to assume that for a give input the server would move the player in that direction for a defined amount of space, which is different than my approach where I move while the client is holding towards a specific direction. I've tried implementing something like that, but again I fall into the pitfall of, if a user can say that I should move "1 step" into that direction, how can I make sure that they wouldn't just send a bunch of messages to tell the server to move into that direction and bypass the defined speed for the player?
Can anyone point me to what I could read/watch to get a better understanding on how to implement something like this? Like I mentioned before I feel like I am not grasping exactly how this is implemented and I keep running in circles trying a bunch of different things that end up having the same 2 problems, either I cannot match the amount of movement between the client and the server, or I am sending too information that would allow clients to cheat.
Sorry again for such a big, and potentially not well written, question and thanks!