I like the way Ultima Online handled it:
To the user, it appears that:
- Their character is always in the center of the screen
- Pressing and holding the right mouse button results in the character running towards the mouse cursor (or walking). (Left click normally interacts with stuff in UO)
- Clicking the left mouse button (IIRC) while holding the right mouse button, and then releasing both buttons, results in your character walking towards your mouse cursor without you having to hold any buttons. Right-clicking again will make your character stop moving.
What was really going on in the protocol:
UO was tile based, and every time the user tried to move into a tile, the client sent a move request packet with two variables (IIRC): one byte for a direction to move bitflag or'd with a speed bitflag, and another byte for a movement step number (0, 1, 2, 3, etc, it increased each time the client sent the packet and wrapped back to 0 upon passing 255, IIRC) to the server. The client proceeded as if it was successful while awaiting confirmation from the server and would do multiple steps up to 8 or so (random guess from fuzzy memory) before stopping even if it didn't get a response from the server right away. The server checked each move packet and would send back move success or move failure packets. Move success packets just told the client everything was great, it can keep going, and maybe it told it that it can forget previous position data too. The move failure packet indicated which movement step number the client should roll back to (the client kept a list of previous positions prior to each movement attempt in case they failed), and invalidated that move attempt and all move attempts after it.
Normally the client would be checking its own local data files and so forth to see if a move was valid, and not even sending a move request if not, but If there was ever a glitch where the client thought it could move somewhere and the server went 'umm nope', what it would look like was rubber-banding - like, try to walk into a type of terrain that the client said was OK and the server said NO WALKING FOR YOU, and your character looks like he's walking into it and being yanked back repeatedly. Of course someone running in front of you or a monster spawning or whatever could also block your path unexpectedly too.
Side note: UO used TCP with the nagle algorithm disabled, and some of the emulators run pretty well - the bandwidth requirements aren't bad. Of course all the packets are compressed too, come to think of it.