Game Movement
Getting your head around how the game movement system works isn't easy. This page will try to clarify what goes on.
Client vs Server vs Singleplayer
Clients connected to a server usually use Prediction to guess what the server will do before it actually does it. You should understand how prediction works before continuing, if you are planning to work with multiplayer.
Prediction is disabled in singleplayer, since it isn't necessary to guess what the server will do. Most predicted hooks (i.e., hooks that are called while prediction is running) do not run in singleplayer for this reason.
Interpolation is used in both singleplayer and multiplayer to smoothly blend game ticks together, since the client can have a framerate faster than the tickrate of the game; it operates separately to prediction, and is how singleplayer gameplay can still be smooth without prediction.
If prediction is disabled in multiplayer, all client side simulation is disabled, and you can ignore any parts below that reference it. The user's input and other data is sent to the server, and the client is not updated until it receives the player's new state from the server.
User Command
The game keeps track of player input and other state via user command (CUserCmd) structures. These structures are built using the player's keys, mouse activity, position, view angles, velocity, and more. This user command is then stored in a queue in the engine, to later be sent to and played back on the server.
CreateMove
Every frame, the client runs the CreateMove function internally. This prepares an empty user command, reads the keyboard and mouse input, transfers that information into the command, and lets the player and other objects run their own internal CreateMove functions to modify that information. Then, control is passed to the GM:CreateMove hook.
This hook runs after all the internal checks and updates have completed, so the command structure should have all the information you need to handle local player input. However, since it only runs on the client, it can be easily overridden. If you rely on the player being in a specific state serverside, you shoud enforce your changes on the server using one of the below hooks instead of this one.
Note the name of this function is not related to CMoveData or similar classes and functions, it is a reference to "player movement" in general and is completely separate to the "move system".
StartCommand
In a multiplayer game with prediction enabled, some physics, such as player physics, are simulated on the client. This simulation will also predict the results of the queued user commands. The GM:StartCommand hook is what is called internally as the first step of client prediction.
In both singleplayer and multiplayer, non-predicted user commands are sent from the client to the server (your game can be both the client and the server, such as in singleplayer) where StartCommand is again run. This process runs in parallel to client prediction.
In both cases, all available queued user commands are processed sequentially. This hook is a good place to change controls (prevent movement, etc) that should apply to both server and client, since everything else down the line depends on what happens here. It's necessary to update both realms since updating only the client (in CreateMove) would allow it to theoretically bypass whatever changes were made before the user command packet is sent to the server.
Note however that doing two different things on the client and server in this hook will result in prediction errors, if the client is predicting.
SetupMove
The GM:SetupMove hook is used to transfer data from the user command to the global CMoveData structure, and set the origin/velocity of the entity you're moving (probably the player).
Changes to the user command in this hook are ignored. Internally, it has already been read and its values used to update the move data. It's still provided as an argument however, to allow you to easily make your own move data modifications based on the user command.
Like StartCommand, this and later move hooks are called on both the server and client. However, unlike StartCommand, they won't be called on the client in singleplayer, since prediction is disabled and the server can be trusted to make timely updates.
Also like StartCommand, it's important the client and server be doing the same thing, else prediction errors may occur. Given an identical user command, the resulting move data should be identical too, regardless of realm.
Move
The GM:Move hook does the brunt of the work. Physics calculations, collision checks, and other intensive work should be done here. The results of these checks should be written to the move data structure.
So in this hook you would, for example, look at the MoveData structure, move its origin based on its other factors (buttons down, velocity, etc), while taking into account collision with the floor and walls.
Note that you should only change the move data structure, and not the entity that will be moved. This is because these hooks can be called multiple times to work out prediction errors. While the engine is handling prediction, entities are moved around by the engine, and many properties will be overwritten when prediction is completed.
FinishMove
The GM:FinishMove hook is where you should apply the changes from the move data onto your entity. Unlike the other hooks which may run multiple times on the client to calculate prediction, this hook is called only once after prediction is completed.
The Drive System
The drive system was invented to make this all more modular, and make it so you can control not only the player, but other objects too.
Garry's Mod
Rust
Steamworks
Wiki Help