I'm going to put this here both as a note to myself and as a way of
getting commentary on this from anybody who is interested in player
physics, server-side.  Please do correct me if anything is wrong here.

So how does player physics work?

At the very base are the CUserCmds that are fed into the server.
CServerGameClients (I will be referring to these by implementation, not
interface) gets these through ProcessUsercmds() and passes them on to
CBasePlayer's ProcessUsercmds().  They're buffered there.

Now there comes a time when GameFrame() is called in CServerGameDLL.
The call chain of interest is:

CServerGameDLL::GameFrame()
Physics_RunThinkFunctions()
Physics_SimulateEntity()
CBasePlayer::PhysicsSimulate()

Now is where the CUserCmds are actually used.  For each CUserCmd, this
happens:

  Each CUserCmd is passed into CBasePlayer::PlayerRunCommand().
  CPlayerMove::RunCommand() is called, calling these three:

    CBasePlayer::SetupMove() [prepares the CMoveData]
    CGameMovement::ProcessMovement() [updates pos, vel, etc.]
    CBasePlayer::FinishMove() [copies the updated data back]

  The VPhysics shadow object is updated with new pos and vel.

Ok then, all CUserCmds are processed.  Then, CServerGameDLL::GameFrame()
calls IGameSystem::FrameUpdatePostEntityThinkAllSystems(), and this
happens:

CPhysicsHook::FrameUpdatePostEntityThink()
PhysFrame()

In this function, the entire physics environment is first simulated.
Then, CBasePlayer::VPhysicsShadowUpdate() is called.  This is where the
fun stuff is, where the player entity's position is reconciled with what
the physics system thinks it is.

Then, after all this, data is sent off to the client, yadda yadda.


****  SO  ****


What's the moral of the story?  Here's what I get out of the code:

For player movement, what happens is that player's aren't really
physically simulated at all!  Everything (movement, gravity, swimming,
etc.) is handled by the CGameMovement class.  With every CUserCmd:

1.  CGameMovement "simulates" the player and derives new pos/vel.
2.  A physics "shadow object" is updated with the new pos/vel.

This happens for every CUserCmd.  Then, after all the CUserCmds have
been processed that frame, the physics simulation actually occurs.  At
this time, _all the VPhysics shadow updates for that frame are processed
at once_.  Let's say, there were 3 CUserCmds from the player processed
this frame, then the 3 shadow state updates will happen sequentially in
the same frame.

After physics simulation occurs, the player entity is reconciled with
the VPhysics entity.  Any VPhysics damage or position/velocity
differences are copied back into the entity.  Then the ent data is
packaged and shot off to the clients.


****  QUESTIONS  ****

1.  Are we guaranteed only 1 CUserCmd processed per frame?


****  OTHER THOUGHTS ****


I haven't seen any GoldSrc code before, but I suspect that the only way
to _exactly_ reproduce GoldSrc player physics would be some crazy coding
in VPhysicsShadowUpdate(), or even stripping the player of VPhysics
simulation entirely.  You'll likely do a _lot_ of copy-pasting of
GoldSrc code either way.  I think, to be honest, that you'll have to go
the latter route (nuking VPhysics) because there's no way that VPhysics
will exactly reproduce GoldSrc physics.  You'll have to do it all in
CGameMovement.


John Sheu


_______________________________________________
To unsubscribe, edit your list preferences, or view the list archives, please 
visit:
http://list.valvesoftware.com/mailman/listinfo/hlcoders

Reply via email to