mirror of
https://github.com/s1lentq/ReGameDLL_CS.git
synced 2025-01-24 20:47:57 +03:00
Implemented simple player movement version control to avoid desync
Bump minor API version
This commit is contained in:
parent
4e1cb1091f
commit
8b6d659077
@ -74,6 +74,7 @@ const int DEFAULT_FOV = 90; // the default field of view
|
||||
#define PLAYER_PREVENT_DUCK BIT(4)
|
||||
#define PLAYER_PREVENT_CLIMB BIT(5) // The player can't climb ladder
|
||||
#define PLAYER_PREVENT_JUMP BIT(6)
|
||||
#define PLAYER_PREVENT_DDUCK BIT(7)
|
||||
|
||||
#define MENU_KEY_1 BIT(0)
|
||||
#define MENU_KEY_2 BIT(1)
|
||||
|
@ -3299,6 +3299,26 @@ void EXT_FUNC InternalCommand(edict_t *pEntity, const char *pcmd, const char *pa
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef REGAMEDLL_ADD
|
||||
// Request from client for the given version of player movement control, if any
|
||||
else if (FStrEq(pcmd, "cl_pmove_version"))
|
||||
{
|
||||
// cl_pmove_version <num>
|
||||
if (CMD_ARGC_() < 2)
|
||||
return; // invalid
|
||||
|
||||
PlayerMovementVersion &playerMovementVersion = pPlayer->CSPlayer()->m_MovementVersion;
|
||||
playerMovementVersion.Set(parg1);
|
||||
|
||||
// If the client's requested movement version is newer, enforce it to the available one
|
||||
if (playerMovementVersion.IsGreaterThan(PM_VERSION))
|
||||
{
|
||||
playerMovementVersion.Set(PM_VERSION); // reset to available version
|
||||
CLIENT_COMMAND(pEntity, "cl_pmove_version %s\n", playerMovementVersion.ToString());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
if (g_pGameRules->ClientCommand_DeadOrAlive(GetClassPtr<CCSPlayer>((CBasePlayer *)pev), pcmd))
|
||||
@ -3727,6 +3747,20 @@ void EXT_FUNC ServerDeactivate()
|
||||
|
||||
void EXT_FUNC ServerActivate(edict_t *pEdictList, int edictCount, int clientMax)
|
||||
{
|
||||
#ifdef REGAMEDLL_ADD
|
||||
//
|
||||
// Tells clients which version of player movement (pmove) the server is using
|
||||
//
|
||||
// In GoldSrc, both the server and clients handle player movement using shared code.
|
||||
// If the server changes how movement works, due to improvements or bugfixes, it can mess up
|
||||
// the client's movement prediction, causing desync. To avoid this, the server can tell clients what
|
||||
// version of the movement code it's using. Clients that don't recognize or respond to this version
|
||||
// will be treated as using the previous behavior, and the server will handle them accordingly.
|
||||
// Clients that do recognize it will let the server know, so everything stays in sync.
|
||||
//
|
||||
SET_KEY_VALUE(GET_INFO_BUFFER(pEdictList), "pmove", PM_ServerVersion());
|
||||
#endif
|
||||
|
||||
int i;
|
||||
CBaseEntity *pClass;
|
||||
|
||||
|
@ -91,6 +91,74 @@ typedef struct physent_s
|
||||
|
||||
} physent_t;
|
||||
|
||||
#define PM_VERSION_MAJOR 1
|
||||
#define PM_VERSION_MINOR 0
|
||||
#define PM_VERSION_PATCH 0
|
||||
#define PM_VERSION PM_VERSION_MAJOR, PM_VERSION_MINOR, PM_VERSION_PATCH
|
||||
|
||||
#define PM_VERSION_STRINGIZE(x) #x
|
||||
#define PM_VERSION_STRING(major,minor,patch) \
|
||||
(patch == 0 ?\
|
||||
PM_VERSION_STRINGIZE(major) "." PM_VERSION_STRINGIZE(minor) :\
|
||||
PM_VERSION_STRINGIZE(major) "." PM_VERSION_STRINGIZE(minor) "." PM_VERSION_STRINGIZE(patch))
|
||||
|
||||
// Control version of the player movement system
|
||||
struct PlayerMovementVersion {
|
||||
uint8_t major, minor, patch;
|
||||
uint32_t u32;
|
||||
|
||||
PlayerMovementVersion() {
|
||||
Set(0, 0, 0);
|
||||
}
|
||||
|
||||
PlayerMovementVersion(uint32_t majorVersion, uint32_t minorVersion, uint32_t patchVersion = 0) {
|
||||
Set(majorVersion, minorVersion, patchVersion);
|
||||
}
|
||||
|
||||
inline void Set(uint32_t majorVersion, uint32_t minorVersion, uint32_t patchVersion = 0)
|
||||
{
|
||||
major = majorVersion;
|
||||
minor = minorVersion;
|
||||
patch = patchVersion;
|
||||
u32 = (major << 16) | (minor << 8) | patch;
|
||||
}
|
||||
|
||||
inline void Set(const char *version)
|
||||
{
|
||||
if (!version)
|
||||
return;
|
||||
|
||||
major = minor = patch = u32 = 0;
|
||||
int result = sscanf(version, "%hhu.%hhu.%hhu", &major, &minor, &patch);
|
||||
if (result < 1)
|
||||
return; // major invalid
|
||||
|
||||
u32 = (major << 16) | (minor << 8) | patch;
|
||||
}
|
||||
|
||||
// Compares if the current version is less than the given version
|
||||
inline bool IsLessThan(uint32_t major, uint32_t minor, uint32_t patch = 0) const {
|
||||
return u32 < ((major << 16) | (minor << 8) | patch);
|
||||
}
|
||||
|
||||
// Compares if the current version is greater than the given version
|
||||
inline bool IsGreaterThan(uint32_t major, uint32_t minor, uint32_t patch = 0) const {
|
||||
return u32 > ((major << 16) | (minor << 8) | patch);
|
||||
}
|
||||
|
||||
// Compares if the current version is greater than or equal to the given version
|
||||
inline bool IsAtLeast(uint32_t major, uint32_t minor, uint32_t patch = 0) const {
|
||||
return !IsLessThan(major, minor, patch);
|
||||
}
|
||||
|
||||
const char *ToString() const {
|
||||
static char string[14];
|
||||
int len = Q_snprintf(string, sizeof(string), "%u.%u.%u", major, minor, patch);
|
||||
if (patch == 0 && len > 2) string[len - 2] = '\0';
|
||||
return string;
|
||||
}
|
||||
};
|
||||
|
||||
typedef struct playermove_s
|
||||
{
|
||||
int player_index; // So we don't try to run the PM_CheckStuck nudging too quickly.
|
||||
@ -111,7 +179,7 @@ typedef struct playermove_s
|
||||
qboolean bInDuck; // In process of ducking or ducked already?
|
||||
int flTimeStepSound; // For walking/falling
|
||||
// Next time we can play a step sound
|
||||
int iStepLeft;
|
||||
qboolean iStepLeft;
|
||||
float flFallVelocity;
|
||||
vec3_t punchangle;
|
||||
float flSwimTime;
|
||||
|
@ -898,7 +898,7 @@ void PM_WalkMove()
|
||||
|
||||
#ifdef REGAMEDLL_ADD
|
||||
// Player can speed up the run if '+speed' button is pressed
|
||||
if ((pmove->cmd.buttons & IN_RUN) && pmove->fuser3 > 0)
|
||||
if (pmoveplayer->m_MovementVersion.IsAtLeast(1, 0) && (pmove->cmd.buttons & IN_RUN) && pmove->fuser3 > 0)
|
||||
{
|
||||
fmove *= pmove->fuser3;
|
||||
smove *= pmove->fuser3;
|
||||
@ -1450,7 +1450,7 @@ void PM_CategorizePosition()
|
||||
|
||||
// Do not stick to the ground of an OBSERVER or NOCLIP mode
|
||||
#ifdef REGAMEDLL_FIXES
|
||||
if (pmove->movetype == MOVETYPE_NOCLIP || pmove->movetype == MOVETYPE_NONE)
|
||||
if (pmoveplayer->m_MovementVersion.IsAtLeast(1, 0) && (pmove->movetype == MOVETYPE_NOCLIP || pmove->movetype == MOVETYPE_NONE))
|
||||
{
|
||||
pmove->onground = -1;
|
||||
return;
|
||||
@ -1704,7 +1704,7 @@ void PM_SpectatorMove()
|
||||
|
||||
#ifdef REGAMEDLL_ADD
|
||||
// Observer can accelerate in air if '+speed' button is pressed
|
||||
if (pmove->cmd.buttons & IN_RUN)
|
||||
if (pmoveplayer->m_MovementVersion.IsAtLeast(1, 0) && pmove->cmd.buttons & IN_RUN)
|
||||
{
|
||||
float flAirAccelerate = (pmove->fuser3 > 0.0f) ? pmove->fuser3 : max(pmove->movevars->airaccelerate / 100.0f, 7.0f);
|
||||
fmove *= flAirAccelerate;
|
||||
@ -1737,12 +1737,15 @@ void PM_SpectatorMove()
|
||||
|
||||
addspeed = wishspeed - currentspeed;
|
||||
|
||||
#ifndef REGAMEDLL_FIXES
|
||||
if (addspeed <= 0)
|
||||
return;
|
||||
#else
|
||||
if (addspeed > 0)
|
||||
{
|
||||
#ifdef REGAMEDLL_FIXES
|
||||
if (pmoveplayer->m_MovementVersion.IsLessThan(1, 0))
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (addspeed > 0)
|
||||
{
|
||||
accelspeed = pmove->movevars->accelerate * pmove->frametime * wishspeed;
|
||||
if (accelspeed > addspeed)
|
||||
@ -1844,7 +1847,7 @@ LINK_HOOK_VOID_CHAIN2(PM_UnDuck)
|
||||
void EXT_FUNC __API_HOOK(PM_UnDuck)()
|
||||
{
|
||||
#ifdef REGAMEDLL_ADD
|
||||
if (unduck_method.value)
|
||||
if (unduck_method.value || (pmove->iuser3 & PLAYER_PREVENT_DDUCK))
|
||||
#endif
|
||||
{
|
||||
#ifdef REGAMEDLL_FIXES
|
||||
@ -2365,7 +2368,7 @@ void PM_NoClip()
|
||||
|
||||
#ifdef REGAMEDLL_ADD
|
||||
// Player with noclip can accelerate in air if '+speed' button is pressed
|
||||
if ((pmove->cmd.buttons & IN_RUN) && pmove->fuser3 > 0)
|
||||
if (pmoveplayer->m_MovementVersion.IsAtLeast(1, 0) && (pmove->cmd.buttons & IN_RUN) && pmove->fuser3 > 0)
|
||||
{
|
||||
float flAirAccelerate = pmove->fuser3;
|
||||
fmove *= flAirAccelerate;
|
||||
@ -3379,3 +3382,8 @@ void EXT_FUNC __API_HOOK(PM_Init)(struct playermove_s *ppmove)
|
||||
|
||||
pm_shared_initialized = TRUE;
|
||||
}
|
||||
|
||||
const char *PM_ServerVersion()
|
||||
{
|
||||
return PM_VERSION_STRING(PM_VERSION_MAJOR, PM_VERSION_MINOR, PM_VERSION_PATCH);
|
||||
}
|
||||
|
@ -96,4 +96,6 @@ void PM_AirAccelerate_OrigFunc(vec_t *wishdir, float wishspeed, float accel);
|
||||
void PM_AirMove(int playerIndex = 0);
|
||||
#endif
|
||||
|
||||
const char *PM_ServerVersion();
|
||||
|
||||
extern struct playermove_s *pmove;
|
||||
|
@ -186,6 +186,9 @@ public:
|
||||
|
||||
int m_iGibDamageThreshold; // negative health to reach to gib player
|
||||
usercmd_t m_LastCmd;
|
||||
|
||||
// Player movement version control
|
||||
PlayerMovementVersion m_MovementVersion;
|
||||
};
|
||||
|
||||
// Inlines
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include <API/CSInterfaces.h>
|
||||
|
||||
#define REGAMEDLL_API_VERSION_MAJOR 5
|
||||
#define REGAMEDLL_API_VERSION_MINOR 27
|
||||
#define REGAMEDLL_API_VERSION_MINOR 28
|
||||
|
||||
// CBasePlayer::Spawn hook
|
||||
typedef IHookChainClass<void, class CBasePlayer> IReGameHook_CBasePlayer_Spawn;
|
||||
|
@ -6,5 +6,5 @@
|
||||
#pragma once
|
||||
|
||||
#define VERSION_MAJOR 5
|
||||
#define VERSION_MINOR 27
|
||||
#define VERSION_MINOR 28
|
||||
#define VERSION_MAINTENANCE 0
|
||||
|
Loading…
x
Reference in New Issue
Block a user