Send custom data via svc_director message instead of delta.

Minor refactoring.
This commit is contained in:
s1lent 2018-01-02 20:32:24 +07:00
parent a672305041
commit 33ce752b11
No known key found for this signature in database
GPG Key ID: 0FE401DC73916B5C
15 changed files with 321 additions and 109 deletions

View File

@ -46,6 +46,7 @@ typedef struct _UserMsg
} UserMsg;
bool HookUserMsg(char *pszMsgName, pfnUserMsgHook pfn);
bool UnHookUserMsg(char *pszMsgName);
extern UserMsg *g_pClientUserMsgs;
extern std::map<std::string, pfnUserMsgHook> g_ClientUserMsgsMap;

View File

@ -188,5 +188,8 @@ typedef struct playermove_s
void (*PM_PlaySound)(int channel, const char *sample, float volume, float attenuation, int fFlags, int pitch);
const char *(*PM_TraceTexture)(int ground, float *vstart, float *vend);
void (*PM_PlaybackEventFull)(int flags, int clientindex, unsigned short eventindex, float delay, float *origin, float *angles, float fparam1, float fparam2, int iparam1, int iparam2, int bparam1, int bparam2);
pmtrace_t (*PM_PlayerTraceEx)(float *start, float *end, int traceFlags, int (*pfnIgnore)(physent_t *pe));
int (*PM_TestPlayerPositionEx)(float *pos, pmtrace_t *ptrace, int (*pfnIgnore)(physent_t *pe));
struct pmtrace_s *(*PM_TraceLineEx)(float *start, float *end, int flags, int usehulll, int (*pfnIgnore)(physent_t *pe));
} playermove_t;

View File

@ -44,44 +44,104 @@ int Initialize(cl_enginefunc_t *pEnginefuncs, int iVersion)
void HUD_Init()
{
g_pClientfuncs->pHudFrame = HUD_Frame;
g_pClientfuncs->pPostRunCmd = HUD_PostRunCmd;
g_pClientfuncs->pProcessPlayerState = HUD_ProcessPlayerState;
g_pClientfuncs->pStudioInterface = HUD_GetStudioModelInterface;
g_pClientfuncs->pDirectorMessage = HUD_DirectorMessage;
gClientfuncs.pHudInitFunc();
gHUD.Init();
}
void HUD_WeaponsPostThink(local_state_t *from, local_state_t *to, usercmd_t *cmd, double time, unsigned int random_seed)
void HUD_Frame(double time)
{
int flags = from->client.iuser3;
net_status_t st;
gEngfuncs.pNetAPI->Status(&st);
g_bHoldingKnife = (from->client.m_iId == WEAPON_KNIFE);
g_bHoldingShield = (flags & PLAYER_HOLDING_SHIELD) != 0;
const auto delay = 0.5;
if (st.connected == 1 && st.connection_time > (delay - 0.1) && st.connection_time < delay)
{
// tell the server that i want to sync
gEngfuncs.pfnServerCmd("__request_sync");
}
gClientfuncs.pHudFrame(time);
}
void HUD_ProcessPlayerState(entity_state_t *dst, entity_state_t *src)
union split_double_t
{
// save current values of fields from server-side
auto &sync = g_PlayerSyncInfo[src->number];
split_double_t() : d (0.0) {}
split_double_t(double f) : d(f) {}
sync.yaw = src->vuser1[0];
sync.gaityaw = src->vuser1[1];
sync.gaitframe = src->vuser1[2];
double d;
struct {
int32_t lo;
int32_t hi;
};
};
sync.gaitmovement = src->vuser2[0];
sync.gaitsequence = src->vuser2[1];
sync.pitch = src->vuser2[2];
constexpr size_t DIRECTOR_UID = 0xabcdef00;
sync.prevgaitorigin[0] = src->maxs[0];
sync.prevgaitorigin[1] = src->maxs[1];
sync.prevgaitorigin[2] = src->maxs[2];
void HUD_DirectorMessage(int iSize, void *pbuf)
{
BEGIN_READ(pbuf, iSize);
sync.time = src->mins[0]; // m_clTime
sync.oldtime = src->mins[1]; // m_clOldTime
sync.frametime = src->mins[2]; // m_clTime - m_clOldTime?
auto cmd = READ_BYTE();
if (cmd != DRC_CMD_TIMESCALE)
{
gClientfuncs.pDirectorMessage(iSize, pbuf);
return;
}
gClientfuncs.pProcessPlayerState(dst, src);
// make sure that this is our custom message
auto uid = READ_LONG();
if (uid != DIRECTOR_UID)
{
gClientfuncs.pDirectorMessage(iSize, pbuf);
return;
}
auto index = READ_BYTE();
// header packet
if (index == 0)
{
// parse time
split_double_t time, oldtime;
time.lo = READ_LONG();
time.hi = READ_LONG();
oldtime.lo = READ_LONG();
oldtime.hi = READ_LONG();
sv.time = time.d;
sv.oldtime = oldtime.d;
sv.frametime = READ_FLOAT();
}
else
{
auto &sync = g_PlayerSyncInfo[index];
// save current values of fields from server-side
sync.prevgaitorigin[0] = READ_FLOAT();
sync.prevgaitorigin[1] = READ_FLOAT();
sync.prevgaitorigin[2] = READ_FLOAT();
sync.yaw = READ_FLOAT();
sync.pitch = READ_FLOAT();
sync.gaityaw = READ_FLOAT();
sync.gaitframe = READ_FLOAT();
sync.gaitmovement = READ_FLOAT();
sync.gaitsequence = READ_LONG ();
}
}
void HUD_WeaponsPostThink(local_state_t *from, local_state_t *to, usercmd_t *cmd, double time, unsigned int random_seed)
{
g_bHoldingKnife = (from->client.m_iId == WEAPON_KNIFE);
g_bHoldingShield = (from->client.iuser3 & PLAYER_HOLDING_SHIELD) == PLAYER_HOLDING_SHIELD;
}
void R_ForceCVars(qboolean multiplayer)

View File

@ -40,6 +40,7 @@ cvar_t *cl_minmodels;
cvar_t *default_fov;
cvar_t *sensitivity;
server_sync_t sv;
player_sync_t g_PlayerSyncInfo [MAX_PLAYERS + 1];
extra_player_info_t g_PlayerExtraInfo[MAX_PLAYERS + 1]; // additional player info sent directly to the client dll

View File

@ -37,6 +37,13 @@ enum
MAX_TEAM_NAME = 16,
};
struct server_sync_t
{
double time;
double oldtime;
float frametime;
};
struct player_sync_t
{
float yaw;
@ -45,9 +52,6 @@ struct player_sync_t
float gaitframe;
float gaitmovement;
int gaitsequence;
float time;
float oldtime;
float frametime;
Vector prevgaitorigin;
};
@ -72,7 +76,8 @@ struct extra_player_info_t
};
// Macros to hook function calls into the HUD object
#define HOOK_MESSAGE(x) HookUserMsg(#x, __MsgFunc_##x)
#define HOOK_MESSAGE(x) HookUserMsg(#x, __MsgFunc_##x)
#define UNHOOK_MESSAGE(x) UnHookUserMsg(#x)
#define DECLARE_MESSAGE(y, x)\
int __MsgFunc_##x(const char *pszName, int iSize, void *pbuf)\
@ -113,6 +118,7 @@ private:
extern CHud gHUD;
extern server_sync_t sv;
extern player_sync_t g_PlayerSyncInfo [MAX_PLAYERS + 1];
extern extra_player_info_t g_PlayerExtraInfo[MAX_PLAYERS + 1];

View File

@ -97,9 +97,15 @@ bool CEngine::Init(const char *szModuleName, const char *pszFile)
m_Software = !Q_stricmp(szModuleName, ENGINE_CLIENT_SOFT_LIB) ? true : false;
if (!LoadSecureClient_Init() || !LoadInSecureClient_Init())
if (!LoadSecureClient_Init())
{
TraceLog("> %s: Not found ClientFuncs\n", __FUNCTION__);
TraceLog("> %s: Not found LoadSecureClient\n", __FUNCTION__);
return false;
}
if (!LoadInSecureClient_Init())
{
TraceLog("> %s: Not found LoadInSecureClient\n", __FUNCTION__);
return false;
}
@ -229,12 +235,11 @@ bool CEngine::StudioLightingInit()
void R_StudioLighting(float *lv, int bone, int flags, const vec_t *normal)
{
if (!pfnR_StudioLighting) {
*lv = 0.75f;
return;
}
*lv = 0.75f;
pfnR_StudioLighting(lv, bone, flags, normal);
if (pfnR_StudioLighting) {
pfnR_StudioLighting(lv, bone, flags, normal);
}
if (g_EngineLib->IsSoftware()) {
*lv = *lv / (USHRT_MAX + 1);

View File

@ -356,8 +356,6 @@ void CGameStudioModelRenderer::StudioSetupBones()
&& m_pCurrentEntity->curstate.sequence != ANIM_SWIM_1
&& m_pCurrentEntity->curstate.sequence != ANIM_SWIM_2)
{
bool bCopy = true;
if (m_pPlayerInfo->gaitsequence >= m_pStudioHeader->numseq || m_pPlayerInfo->gaitsequence < 0)
m_pPlayerInfo->gaitsequence = 0;
@ -366,6 +364,7 @@ void CGameStudioModelRenderer::StudioSetupBones()
panim = StudioGetAnim(m_pRenderModel, pseqdesc);
StudioCalcRotations(pos2, q2, pseqdesc, panim, m_pPlayerInfo->gaitframe);
bool bCopy = true;
for (int i = 0; i < m_pStudioHeader->numbones; i++)
{
if (!Q_strcmp(pbones[i].name, "Bip01 Spine"))
@ -418,7 +417,7 @@ void CGameStudioModelRenderer::StudioEstimateGait(entity_state_t *pplayer)
float dt;
if (m_pPlayerSync)
{
dt = clamp(m_pPlayerSync->time - m_pPlayerSync->oldtime, 0.0f, 1.0f);
dt = clamp(sv.time - sv.oldtime, 0.0, 1.0);
}
else
{
@ -513,7 +512,7 @@ void CGameStudioModelRenderer::StudioProcessGait(entity_state_t *pplayer)
float dt;
if (m_pPlayerSync)
{
dt = clamp(m_pPlayerSync->time - m_pPlayerSync->oldtime, 0.0f, 1.0f);
dt = clamp(sv.time - sv.oldtime, 0.0, 1.0);
}
else
{
@ -732,7 +731,7 @@ void CGameStudioModelRenderer::SetupClientAnimation(entity_state_t *pplayer)
st->m_fSequenceLoops = ((GetSequenceFlags(pmodel, st) & STUDIO_LOOPING) != 0) ? TRUE : FALSE;
StudioFrameAdvance(st, fr, dt);
// gEngfuncs.Con_Printf("gs %i frame %f\n", st->gaitsequence, st->frame);
//gEngfuncs.Con_Printf("gs %i frame %f\n", st->gaitsequence, st->frame);
ent->angles = st->realangles;
ent->curstate.angles = st->angles;
@ -809,7 +808,7 @@ int CGameStudioModelRenderer::StudioDrawPlayer(int flags, entity_state_t *pplaye
// Call real draw function
int iret = _StudioDrawPlayer(flags, pplayer);
if (iret && m_pCvarDrawEntities->value == 6)
if (iret && (m_pCvarDrawEntities->value == 6 || m_pCvarDrawEntities->value == 7))
{
m_pPlayerSync = &g_PlayerSyncInfo[pplayer->number];
m_pPlayerInfo = IEngineStudio.PlayerInfo(m_nPlayerIndex);
@ -982,7 +981,6 @@ int CGameStudioModelRenderer::_StudioDrawPlayer(int flags, entity_state_t *pplay
if (m_pCurrentEntity->index > 0)
{
cl_entity_t *ent = gEngfuncs.GetEntityByIndex(m_pCurrentEntity->index);
Q_memcpy(ent->attachment, m_pCurrentEntity->attachment, sizeof(ent->attachment));
}
}
@ -1157,9 +1155,9 @@ void CGameStudioModelRenderer::CalculatePitchBlend(entity_state_t *pplayer)
StudioPlayerBlend(pseqdesc, &iBlend, &m_pCurrentEntity->angles[PITCH]);
m_pCurrentEntity->latched.prevangles[PITCH] = m_pCurrentEntity->angles[PITCH];
m_pCurrentEntity->curstate.blending[1] = iBlend;
m_pCurrentEntity->latched.prevblending[1] = m_pCurrentEntity->curstate.blending[1];
m_pCurrentEntity->latched.prevangles[PITCH] = m_pCurrentEntity->angles[PITCH];
m_pCurrentEntity->curstate.blending[1] = iBlend;
m_pCurrentEntity->latched.prevblending[1] = m_pCurrentEntity->curstate.blending[1];
m_pCurrentEntity->latched.prevseqblending[1] = m_pCurrentEntity->curstate.blending[1];
}

View File

@ -46,14 +46,14 @@ int CStudioModelRenderer::m_boxpnt[6][4] =
vec3_t CStudioModelRenderer::m_hullcolor[8] =
{
{ 1.0, 1.0, 1.0 },
{ 1.0, 0.5, 0.5 },
{ 0.5, 1.0, 0.5 },
{ 1.0, 1.0, 0.5 },
{ 0.5, 0.5, 1.0 },
{ 1.0, 0.5, 1.0 },
{ 0.5, 1.0, 1.0 },
{ 1.0, 1.0, 1.0 },
{ 1.0, 1.0, 1.0 }, // Shield : White
{ 1.0, 0.5, 0.5 }, // Head : Light red
{ 0.5, 1.0, 0.5 }, // Chest : Light green
{ 1.0, 1.0, 0.5 }, // Stomach : Light yellow
{ 0.5, 0.5, 1.0 }, // Leftarm : Light blue
{ 1.0, 0.5, 1.0 }, // Rightarm: Pink
{ 0.5, 1.0, 1.0 }, // Leftleg : Aqua
{ 1.0, 1.0, 1.0 }, // Rightleg: White
};
void CStudioModelRenderer::Init()
@ -63,7 +63,7 @@ void CStudioModelRenderer::Init()
m_pCvarDeveloper = IEngineStudio.GetCvar("developer");
m_pCvarDrawEntities = IEngineStudio.GetCvar("r_drawentities");
m_pChromeSprite = IEngineStudio.GetChromeSprite();
m_pWhiteSprite = IEngineStudio.Mod_ForName("sprites/white.spr", 1);
m_pWhiteSprite = IEngineStudio.Mod_ForName("sprites/white.spr", TRUE);
IEngineStudio.GetModelCounters(&m_pStudioModelCount, &m_pModelsDrawn);
@ -690,7 +690,7 @@ void CStudioModelRenderer::StudioSetupBones()
}
panim = StudioGetAnim(m_pRenderModel, pseqdesc);
StudioCalcRotations(pos, q, pseqdesc, panim, (int)f); // TODO: CHECK ME cast from float to int and to float
StudioCalcRotations(pos, q, pseqdesc, panim, f);
if (pseqdesc->numblends > 1)
{
@ -834,9 +834,6 @@ void CStudioModelRenderer::StudioSetupBones()
if (IEngineStudio.IsHardware())
{
ConcatTransforms((*m_protationmatrix), bonematrix, (*m_pbonetransform)[i]);
// MatrixCopy should be faster...
//ConcatTransforms((*m_protationmatrix), bonematrix, (*m_plighttransform)[i]);
MatrixCopy((*m_pbonetransform)[i], (*m_plighttransform)[i]);
}
else
@ -1693,7 +1690,6 @@ void CStudioModelRenderer::StudioDrawAbsBBox()
gEngfuncs.pTriAPI->Begin(TRI_QUADS);
gEngfuncs.pTriAPI->Color4f(0.5f, 0.5f, 1.0f, 1.0f);
//gEngfuncs.pTriAPI->TexCoord2f(0.0f, 0.0f);
for (j = 0; j < ARRAYSIZE(m_boxpnt); j++)
{
@ -1720,22 +1716,28 @@ void CStudioModelRenderer::StudioRenderFinal_Software()
if (m_pCvarDrawEntities->value == 2)
{
//IEngineStudio.StudioDrawBones();
StudioDrawBones(); // IEngineStudio.StudioDrawBones();
/*IEngineStudio.*/StudioDrawBones();
}
else if (m_pCvarDrawEntities->value == 3)
{
StudioDrawHulls(); // IEngineStudio.StudioDrawHulls();
/*IEngineStudio.*/StudioDrawHulls();
}
else
{
if (m_pPlayerSync)
{
if (m_pCurrentEntity->player && m_pCvarDrawEntities->value == 6)
if (m_pCurrentEntity->player)
{
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd);
StudioDrawHulls();
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
if (m_pCvarDrawEntities->value == 6)
{
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd);
StudioDrawHulls();
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
}
else if (m_pCvarDrawEntities->value == 7)
{
StudioDrawHulls();
}
}
}
else
@ -1752,13 +1754,13 @@ void CStudioModelRenderer::StudioRenderFinal_Software()
if (m_pCvarDrawEntities->value == 4)
{
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd);
StudioDrawHulls(); // IEngineStudio.StudioDrawHulls();
/*IEngineStudio.*/StudioDrawHulls();
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
}
if (m_pCvarDrawEntities->value == 5)
{
StudioDrawAbsBBox(); // IEngineStudio.StudioDrawAbsBBox();
/*IEngineStudio.*/StudioDrawAbsBBox();
}
IEngineStudio.RestoreRenderer();
@ -1771,21 +1773,28 @@ void CStudioModelRenderer::StudioRenderFinal_Hardware()
if (m_pCvarDrawEntities->value == 2)
{
StudioDrawBones(); // IEngineStudio.StudioDrawBones();
/*IEngineStudio.*/StudioDrawBones();
}
else if (m_pCvarDrawEntities->value == 3)
{
StudioDrawHulls(); // IEngineStudio.StudioDrawHulls();
/*IEngineStudio.*/StudioDrawHulls();
}
else
{
if (m_pPlayerSync)
{
if (m_pCurrentEntity->player && m_pCvarDrawEntities->value == 6)
if (m_pCurrentEntity->player)
{
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd);
StudioDrawHulls();
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
if (m_pCvarDrawEntities->value == 6)
{
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd);
StudioDrawHulls();
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
}
else if (m_pCvarDrawEntities->value == 7)
{
StudioDrawHulls();
}
}
}
else
@ -1811,13 +1820,13 @@ void CStudioModelRenderer::StudioRenderFinal_Hardware()
if (m_pCvarDrawEntities->value == 4)
{
gEngfuncs.pTriAPI->RenderMode(kRenderTransAdd);
StudioDrawHulls(); // IEngineStudio.StudioDrawHulls();
/*IEngineStudio.*/StudioDrawHulls();
gEngfuncs.pTriAPI->RenderMode(kRenderNormal);
}
if (m_pCvarDrawEntities->value == 5)
{
StudioDrawAbsBBox(); // IEngineStudio.StudioDrawAbsBBox();
/*IEngineStudio.*/StudioDrawAbsBBox();
}
IEngineStudio.RestoreRenderer();

View File

@ -157,7 +157,7 @@ void AngleQuaternion(float *angles, vec4_t quaternion)
void QuaternionSlerp(vec4_t p, vec4_t q, float t, vec4_t qt)
{
int i;
float omega, cosom, sinom, sclp, sclq;
float omega, cosom, sinom, sclp, sclq;
// decide if one of the quaternions is backwards
float a = 0;
@ -168,6 +168,7 @@ void QuaternionSlerp(vec4_t p, vec4_t q, float t, vec4_t qt)
a += (p[i] - q[i]) * (p[i] - q[i]);
b += (p[i] + q[i]) * (p[i] + q[i]);
}
if (a > b)
{
for (i = 0; i < 4; i++)
@ -176,7 +177,7 @@ void QuaternionSlerp(vec4_t p, vec4_t q, float t, vec4_t qt)
}
}
cosom = p[0]*q[0] + p[1]*q[1] + p[2]*q[2] + p[3]*q[3];
cosom = p[0] * q[0] + p[1] * q[1] + p[2] * q[2] + p[3] * q[3];
if ((1.0 + cosom) > 0.000001)
{
@ -184,6 +185,7 @@ void QuaternionSlerp(vec4_t p, vec4_t q, float t, vec4_t qt)
{
omega = acos(cosom);
sinom = sin(omega);
sclp = sin((1.0 - t) * omega) / sinom;
sclq = sin(t * omega) / sinom;
}
@ -201,11 +203,13 @@ void QuaternionSlerp(vec4_t p, vec4_t q, float t, vec4_t qt)
else
{
qt[0] = -q[1];
qt[1] = q[0];
qt[1] = q[0];
qt[2] = -q[3];
qt[3] = q[2];
qt[3] = q[2];
sclp = sin((1.0 - t) * (0.5 * M_PI));
sclq = sin(t * (0.5 * M_PI));
for (i = 0; i < 3; i++)
{
qt[i] = sclp * p[i] + sclq * qt[i];

View File

@ -29,7 +29,7 @@
#pragma once
#ifndef M_PI
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
#endif
#define PITCH 0 // up / down

View File

@ -48,3 +48,21 @@ bool HookUserMsg(char *pszMsgName, pfnUserMsgHook pfn)
return false;
}
bool UnHookUserMsg(char *pszMsgName)
{
auto pClientUserMsgs = g_pClientUserMsgs;
while (pClientUserMsgs)
{
if (!Q_strcmp(pClientUserMsgs->szName, pszMsgName))
{
pClientUserMsgs->pfn = g_ClientUserMsgsMap[pszMsgName];
g_ClientUserMsgsMap[pszMsgName] = nullptr;
return true;
}
pClientUserMsgs = pClientUserMsgs->next;
}
return false;
}

View File

@ -1,2 +0,0 @@
#pragma once

View File

@ -18,16 +18,16 @@ DLL_FUNCTIONS g_DllFunctionTable_Post =
NULL, // pfnRestoreGlobalState
NULL, // pfnResetGlobalState
NULL, // pfnClientConnect
NULL, // pfnClientDisconnect
&ClientDisconnect_Post, // pfnClientDisconnect
NULL, // pfnClientKill
NULL, // pfnClientPutInServer
NULL, // pfnClientCommand
&ClientCommand_Post, // pfnClientCommand
NULL, // pfnClientUserInfoChanged
&ServerActivate_Post, // pfnServerActivate
NULL, // pfnServerDeactivate
NULL, // pfnPlayerPreThink
NULL, // pfnPlayerPostThink
NULL, // pfnStartFrame
&PlayerPostThink_Post, // pfnPlayerPostThink
&StartFrame_Post, // pfnStartFrame
NULL, // pfnParmsNewLevel
NULL, // pfnParmsChangeLevel
NULL, // pfnGetGameDescription
@ -41,7 +41,7 @@ DLL_FUNCTIONS g_DllFunctionTable_Post =
NULL, // pfnPM_FindTextureType
NULL, // pfnSetupVisibility
NULL, // pfnUpdateClientData
&AddToFullPack_Post, // pfnAddToFullPack
NULL, // pfnAddToFullPack
NULL, // pfnCreateBaseline
NULL, // pfnRegisterEncoders
NULL, // pfnGetWeaponData

View File

@ -30,39 +30,145 @@
server_t *sv;
int AddToFullPack_Post(entity_state_t *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet)
struct player_t
{
if (ent->v.modelindex <= 0 || ent->v.modelindex >= MAX_MODELS)
struct player_info_t
{
RETURN_META_VALUE(MRES_IGNORED, 0);
bool read_packet : 1;
bool request_sync : 1;
};
player_info_t &operator[](size_t i) { return m_data[i - 1]; }
player_info_t &operator[](edict_t *pEdict) { return m_data[ENTINDEX(pEdict) - 1]; }
player_info_t &operator[](CBasePlayer *pPlayer) { return m_data[pPlayer->entindex() - 1]; }
player_info_t m_data[MAX_CLIENTS];
};
player_t g_Players;
constexpr size_t DIRECTOR_UID = 0xabcdef00;
void ClientCommand_Post(edict_t *pEdict)
{
const auto cmd = CMD_ARGV(0);
if (!Q_strcmp(cmd, "__request_sync"))
{
// want sync
g_Players[pEdict].request_sync = true;
}
// we need to call every time SV_StudioSetupBones
// to keep gaityaw and other synced on client-side
TraceResult tr;
TRACE_LINE(ent->v.origin - Vector(1, 1, 1), host->v.origin + Vector(1, 1, 1), 0, nullptr, &tr);
RETURN_META(MRES_IGNORED);
}
CBasePlayer *plr = UTIL_PlayerByIndexSafe(e);
if (plr)
void SendPlayerSyncInfo(CBasePlayer *pPlayer)
{
for (int i = 1; i <= gpGlobals->maxClients; i++)
{
state->vuser1[0] = plr->m_flYaw;
state->vuser1[1] = plr->m_flGaityaw;
state->vuser1[2] = plr->m_flGaitframe;
auto plr = UTIL_PlayerByIndex(i);
if (!plr)
continue;
state->vuser2[0] = plr->m_flGaitMovement;
state->vuser2[1] = plr->m_iGaitsequence;
state->vuser2[2] = plr->m_flPitch;
if (plr->IsDormant() || plr->has_disconnected)
continue;
state->maxs[0] = plr->m_prevgaitorigin[0];
state->maxs[1] = plr->m_prevgaitorigin[0];
state->maxs[2] = plr->m_prevgaitorigin[0];
if (!plr->IsNetClient())
continue;
state->mins[0] = sv->time;
state->mins[1] = sv->oldtime;
state->mins[2] = gpGlobals->frametime;
if (g_Players[plr].request_sync)
{
MESSAGE_BEGIN(MSG_ONE, SVC_DIRECTOR, nullptr, plr->pev);
WRITE_BYTE(42); // number of bytes this message
WRITE_BYTE(DRC_CMD_TIMESCALE);
WRITE_LONG(DIRECTOR_UID); // unique message id
WRITE_BYTE(pPlayer->entindex());
WRITE_LONG(*(int *)&pPlayer->m_prevgaitorigin[0]);
WRITE_LONG(*(int *)&pPlayer->m_prevgaitorigin[1]);
WRITE_LONG(*(int *)&pPlayer->m_prevgaitorigin[2]);
WRITE_LONG(*(int *)&pPlayer->m_flYaw);
WRITE_LONG(*(int *)&pPlayer->m_flPitch);
WRITE_LONG(*(int *)&pPlayer->m_flGaityaw);
WRITE_LONG(*(int *)&pPlayer->m_flGaitframe);
WRITE_LONG(*(int *)&pPlayer->m_flGaitMovement);
WRITE_LONG(pPlayer->m_iGaitsequence);
MESSAGE_END();
}
}
}
void PlayerPostThink_Post(edict_t *pEdict)
{
g_Players[pEdict].read_packet = true;
RETURN_META(MRES_IGNORED);
}
void ClientDisconnect_Post(edict_t *pEdict)
{
g_Players[pEdict].read_packet = false;
g_Players[pEdict].request_sync = false;
RETURN_META(MRES_IGNORED);
}
union split_double_t
{
split_double_t() : d (0.0) {}
split_double_t(double f) : d(f) {}
double d;
struct {
int32_t lo;
int32_t hi;
};
};
void StartFrame_Post()
{
int count = 0;
CBasePlayer *plrList[MAX_CLIENTS];
for (int i = 1; i <= gpGlobals->maxClients; i++)
{
auto pPlayer = UTIL_PlayerByIndex(i);
if (!pPlayer)
continue;
if (pPlayer->IsDormant() || pPlayer->has_disconnected)
continue;
if (!pPlayer->IsAlive())
continue;
if (!g_Players[i].read_packet)
{
RETURN_META(MRES_IGNORED);
}
g_Players[i].read_packet = false;
plrList[count++] = pPlayer;
}
RETURN_META_VALUE(MRES_IGNORED, 0);
if (count > 0)
{
split_double_t time(sv->time), oldtime(sv->oldtime);
MESSAGE_BEGIN(MSG_ALL, SVC_DIRECTOR);
WRITE_BYTE(26); // number of bytes this message
WRITE_BYTE(DRC_CMD_TIMESCALE);
WRITE_LONG(DIRECTOR_UID); // unique message id
WRITE_BYTE(0);
WRITE_LONG(time.lo);
WRITE_LONG(time.hi);
WRITE_LONG(oldtime.lo);
WRITE_LONG(oldtime.hi);
WRITE_LONG(*(int *)&gpGlobals->frametime);
MESSAGE_END();
// 26 + (42 * count) the total number of payload bytes
for (int i = 0; i < count; i++) {
SendPlayerSyncInfo(plrList[i]);
}
}
RETURN_META(MRES_IGNORED);
}
void ServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax)

View File

@ -28,7 +28,10 @@
#pragma once
#include "entity_state.h"
#include "hltv.h"
int AddToFullPack_Post(entity_state_t *state, int e, edict_t *ent, edict_t *host, int hostflags, int player, unsigned char *pSet);
void StartFrame_Post();
void PlayerPostThink_Post(edict_t *pEdict);
void ServerActivate_Post(edict_t *pEdictList, int edictCount, int clientMax);
void ClientDisconnect_Post(edict_t *pEdict);
void ClientCommand_Post(edict_t *pEdict);