This commit is contained in:
JSaurusRex 2024-09-11 23:30:44 +02:00 committed by GitHub
commit 13faf02ae6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 68 additions and 19 deletions

View file

@ -1016,11 +1016,11 @@ void CClient::Render()
GameClient()->OnRender(); GameClient()->OnRender();
DebugRender(); DebugRender();
if(State() == IClient::STATE_ONLINE && g_Config.m_ClAntiPingLimit) // if(State() == IClient::STATE_ONLINE && g_Config.m_ClAntiPingLimit)
{ // {
int64_t Now = time_get(); // int64_t Now = time_get();
g_Config.m_ClAntiPing = (m_PredictedTime.Get(Now) - m_aGameTime[g_Config.m_ClDummy].Get(Now)) * 1000 / (float)time_freq() > g_Config.m_ClAntiPingLimit; // g_Config.m_ClAntiPing = (m_PredictedTime.Get(Now) - m_aGameTime[g_Config.m_ClDummy].Get(Now)) * 1000 / (float)time_freq() > g_Config.m_ClAntiPingLimit;
} // }
} }
const char *CClient::LoadMap(const char *pName, const char *pFilename, SHA256_DIGEST *pWantedSha256, unsigned WantedCrc) const char *CClient::LoadMap(const char *pName, const char *pFilename, SHA256_DIGEST *pWantedSha256, unsigned WantedCrc)

View file

@ -13,7 +13,8 @@
// client // client
MACRO_CONFIG_INT(ClPredict, cl_predict, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict client movements") MACRO_CONFIG_INT(ClPredict, cl_predict, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict client movements")
MACRO_CONFIG_INT(ClPredictDummy, cl_predict_dummy, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict dummy movements") MACRO_CONFIG_INT(ClPredictDummy, cl_predict_dummy, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict dummy movements")
MACRO_CONFIG_INT(ClAntiPingLimit, cl_antiping_limit, 0, 0, 200, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Antiping limit (0 to disable)") MACRO_CONFIG_INT(ClAntiPingLimit, cl_antiping_limit, 0, 0, 200, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Adds delay to antiping (0 to disable)")
MACRO_CONFIG_INT(ClAntiPingpercent, cl_antiping_percent, 100, 0, 100, CFGFLAG_CLIENT | CFGFLAG_SAVE, "how far ahead Antiping predicts, ignored when antiping limit is used")
MACRO_CONFIG_INT(ClAntiPing, cl_antiping, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Enable antiping, i. e. more aggressive prediction.") MACRO_CONFIG_INT(ClAntiPing, cl_antiping, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Enable antiping, i. e. more aggressive prediction.")
MACRO_CONFIG_INT(ClAntiPingPlayers, cl_antiping_players, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict other player's movement more aggressively (only enabled if cl_antiping is set to 1)") MACRO_CONFIG_INT(ClAntiPingPlayers, cl_antiping_players, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict other player's movement more aggressively (only enabled if cl_antiping is set to 1)")
MACRO_CONFIG_INT(ClAntiPingGrenade, cl_antiping_grenade, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict grenades (only enabled if cl_antiping is set to 1)") MACRO_CONFIG_INT(ClAntiPingGrenade, cl_antiping_grenade, 1, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SAVE, "Predict grenades (only enabled if cl_antiping is set to 1)")

View file

@ -58,9 +58,11 @@ void CItems::RenderProjectile(const CProjectileData *pCurrent, int ItemId)
bool IsOtherTeam = (pCurrent->m_ExtraInfo && pCurrent->m_Owner >= 0 && m_pClient->IsOtherTeam(pCurrent->m_Owner)); bool IsOtherTeam = (pCurrent->m_ExtraInfo && pCurrent->m_Owner >= 0 && m_pClient->IsOtherTeam(pCurrent->m_Owner));
int predictTick = GameClient()->GetPredictionTick();
float Ct; float Ct;
if(m_pClient->Predict() && m_pClient->AntiPingGrenade() && LocalPlayerInGame && !IsOtherTeam) if(m_pClient->Predict() && m_pClient->AntiPingGrenade() && LocalPlayerInGame && !IsOtherTeam)
Ct = ((float)(Client()->PredGameTick(g_Config.m_ClDummy) - 1 - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy)) / (float)Client()->GameTickSpeed(); Ct = ((float)(predictTick - 1 - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy)) / (float)Client()->GameTickSpeed();
else else
Ct = (Client()->PrevGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) / (float)Client()->GameTickSpeed() + s_LastGameTickTime; Ct = (Client()->PrevGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) / (float)Client()->GameTickSpeed() + s_LastGameTickTime;
if(Ct < 0) if(Ct < 0)
@ -304,9 +306,11 @@ void CItems::RenderLaser(const CLaserData *pCurrent, bool IsPredicted)
{ {
Dir = normalize_pre_length(Pos - From, Len); Dir = normalize_pre_length(Pos - From, Len);
int predictTick = GameClient()->GetPredictionTick();
float Ticks; float Ticks;
if(IsPredicted) if(IsPredicted)
Ticks = (float)(Client()->PredGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy); Ticks = (float)(predictTick - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy);
else else
Ticks = (float)(Client()->GameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->IntraGameTick(g_Config.m_ClDummy); Ticks = (float)(Client()->GameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->IntraGameTick(g_Config.m_ClDummy);
float Ms = (Ticks / Client()->GameTickSpeed()) * 1000.0f; float Ms = (Ticks / Client()->GameTickSpeed()) * 1000.0f;
@ -377,7 +381,7 @@ void CItems::OnRender()
auto &aSwitchers = GameClient()->Switchers(); auto &aSwitchers = GameClient()->Switchers();
if(UsePredicted) if(UsePredicted)
{ {
for(auto *pProj = (CProjectile *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PROJECTILE); pProj; pProj = (CProjectile *)pProj->NextEntity()) for(auto *pProj = (CProjectile *)GameClient()->m_PrevPredictedWorld.FindFirst(CGameWorld::ENTTYPE_PROJECTILE); pProj; pProj = (CProjectile *)pProj->NextEntity())
{ {
if(!IsSuper && pProj->m_Number > 0 && pProj->m_Number < (int)aSwitchers.size() && !aSwitchers[pProj->m_Number].m_aStatus[SwitcherTeam] && (pProj->m_Explosive ? BlinkingProjEx : BlinkingProj)) if(!IsSuper && pProj->m_Number > 0 && pProj->m_Number < (int)aSwitchers.size() && !aSwitchers[pProj->m_Number].m_aStatus[SwitcherTeam] && (pProj->m_Explosive ? BlinkingProjEx : BlinkingProj))
continue; continue;
@ -385,7 +389,7 @@ void CItems::OnRender()
CProjectileData Data = pProj->GetData(); CProjectileData Data = pProj->GetData();
RenderProjectile(&Data, pProj->GetId()); RenderProjectile(&Data, pProj->GetId());
} }
for(CEntity *pEnt = GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_LASER); pEnt; pEnt = pEnt->NextEntity()) for(CEntity *pEnt = GameClient()->m_PrevPredictedWorld.FindFirst(CGameWorld::ENTTYPE_LASER); pEnt; pEnt = pEnt->NextEntity())
{ {
auto *const pLaser = dynamic_cast<CLaser *>(pEnt); auto *const pLaser = dynamic_cast<CLaser *>(pEnt);
if(!pLaser || pLaser->GetOwner() < 0 || !GameClient()->m_aClients[pLaser->GetOwner()].m_IsPredictedLocal) if(!pLaser || pLaser->GetOwner() < 0 || !GameClient()->m_aClients[pLaser->GetOwner()].m_IsPredictedLocal)
@ -393,7 +397,7 @@ void CItems::OnRender()
CLaserData Data = pLaser->GetData(); CLaserData Data = pLaser->GetData();
RenderLaser(&Data, true); RenderLaser(&Data, true);
} }
for(auto *pPickup = (CPickup *)GameClient()->m_PredictedWorld.FindFirst(CGameWorld::ENTTYPE_PICKUP); pPickup; pPickup = (CPickup *)pPickup->NextEntity()) for(auto *pPickup = (CPickup *)GameClient()->m_PrevPredictedWorld.FindFirst(CGameWorld::ENTTYPE_PICKUP); pPickup; pPickup = (CPickup *)pPickup->NextEntity())
{ {
if(!IsSuper && pPickup->m_Layer == LAYER_SWITCH && pPickup->m_Number > 0 && pPickup->m_Number < (int)aSwitchers.size() && !aSwitchers[pPickup->m_Number].m_aStatus[SwitcherTeam] && BlinkingPickup) if(!IsSuper && pPickup->m_Layer == LAYER_SWITCH && pPickup->m_Number > 0 && pPickup->m_Number < (int)aSwitchers.size() && !aSwitchers[pPickup->m_Number].m_aStatus[SwitcherTeam] && BlinkingPickup)
continue; continue;
@ -601,7 +605,10 @@ void CItems::ReconstructSmokeTrail(const CProjectileData *pCurrent, int DestroyT
LocalPlayerInGame = m_pClient->m_aClients[m_pClient->m_Snap.m_pLocalInfo->m_ClientId].m_Team != TEAM_SPECTATORS; LocalPlayerInGame = m_pClient->m_aClients[m_pClient->m_Snap.m_pLocalInfo->m_ClientId].m_Team != TEAM_SPECTATORS;
if(!m_pClient->AntiPingGunfire() || !LocalPlayerInGame) if(!m_pClient->AntiPingGunfire() || !LocalPlayerInGame)
return; return;
if(Client()->PredGameTick(g_Config.m_ClDummy) == pCurrent->m_StartTick)
int predictTick = GameClient()->GetPredictionTick();
if(predictTick == pCurrent->m_StartTick)
return; return;
// get positions // get positions
@ -625,7 +632,7 @@ void CItems::ReconstructSmokeTrail(const CProjectileData *pCurrent, int DestroyT
Speed = pTuning->m_GunSpeed; Speed = pTuning->m_GunSpeed;
} }
float Pt = ((float)(Client()->PredGameTick(g_Config.m_ClDummy) - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy)) / (float)Client()->GameTickSpeed(); float Pt = ((float)(predictTick - pCurrent->m_StartTick) + Client()->PredIntraGameTick(g_Config.m_ClDummy)) / (float)Client()->GameTickSpeed();
if(Pt < 0) if(Pt < 0)
return; // projectile haven't been shot yet return; // projectile haven't been shot yet

View file

@ -2100,6 +2100,25 @@ void CGameClient::UpdateEditorIngameMoved()
} }
} }
int CGameClient::GetPredictionTick()
{
int predictTick = Client()->GetPredictionTime() * Client()->GameTickSpeed() / 1000.0f;
float predictPercentage = 1 - g_Config.m_ClAntiPingpercent / 100.0f;
int predictMin = std::floor(predictTick * predictPercentage);
int predictMin2 = g_Config.m_ClAntiPingLimit * Client()->GameTickSpeed() / 1000.0f;
if (g_Config.m_ClAntiPingLimit != 0)
predictMin = predictMin2;
predictTick = Client()->PredGameTick(g_Config.m_ClDummy) - predictMin;
if(predictTick < Client()->GameTick(g_Config.m_ClDummy) + 1)
{
predictTick = Client()->GameTick(g_Config.m_ClDummy) + 1;
}
return predictTick;
}
void CGameClient::OnPredict() void CGameClient::OnPredict()
{ {
// store the previous values so we can detect prediction errors // store the previous values so we can detect prediction errors
@ -2157,19 +2176,32 @@ void CGameClient::OnPredict()
if(PredictDummy()) if(PredictDummy())
pDummyChar = m_PredictedWorld.GetCharacterById(m_PredictedDummyId); pDummyChar = m_PredictedWorld.GetCharacterById(m_PredictedDummyId);
int predictTick = GetPredictionTick();
// predict // predict
for(int Tick = Client()->GameTick(g_Config.m_ClDummy) + 1; Tick <= Client()->PredGameTick(g_Config.m_ClDummy); Tick++) for(int Tick = Client()->GameTick(g_Config.m_ClDummy) + 1; Tick <= Client()->PredGameTick(g_Config.m_ClDummy); Tick++)
{ {
// fetch the previous characters // fetch the previous characters
if(Tick == Client()->PredGameTick(g_Config.m_ClDummy)) if(Tick == predictTick)
{ {
m_PrevPredictedWorld.CopyWorld(&m_PredictedWorld);
m_PredictedPrevChar = pLocalChar->GetCore();
for(int i = 0; i < MAX_CLIENTS; i++) for(int i = 0; i < MAX_CLIENTS; i++)
if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i)) if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i))
m_aClients[i].m_PrevPredicted = pChar->GetCore(); m_aClients[i].m_PrevPredicted = pChar->GetCore();
} }
if(Tick == Client()->PredGameTick(g_Config.m_ClDummy))
{
m_PredictedPrevChar = pLocalChar->GetCore();
m_aClients[m_Snap.m_LocalClientId].m_PrevPredicted = pLocalChar->GetCore();
if(pDummyChar)
m_aClients[m_PredictedDummyId].m_PrevPredicted = pDummyChar->GetCore();
}
if(Tick == predictTick)
{
m_PrevPredictedWorld.CopyWorld(&m_PredictedWorld);
}
// optionally allow some movement in freeze by not predicting freeze the last one to two ticks // optionally allow some movement in freeze by not predicting freeze the last one to two ticks
if(g_Config.m_ClPredictFreeze == 2 && Client()->PredGameTick(g_Config.m_ClDummy) - 1 - Client()->PredGameTick(g_Config.m_ClDummy) % 2 <= Tick) if(g_Config.m_ClPredictFreeze == 2 && Client()->PredGameTick(g_Config.m_ClDummy) - 1 - Client()->PredGameTick(g_Config.m_ClDummy) % 2 <= Tick)
pLocalChar->m_CanMoveInFreeze = true; pLocalChar->m_CanMoveInFreeze = true;
@ -2193,14 +2225,22 @@ void CGameClient::OnPredict()
m_PredictedWorld.Tick(); m_PredictedWorld.Tick();
// fetch the current characters // fetch the current characters
if(Tick == Client()->PredGameTick(g_Config.m_ClDummy)) if(Tick == predictTick)
{ {
m_PredictedChar = pLocalChar->GetCore();
for(int i = 0; i < MAX_CLIENTS; i++) for(int i = 0; i < MAX_CLIENTS; i++)
if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i)) if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i))
m_aClients[i].m_Predicted = pChar->GetCore(); m_aClients[i].m_Predicted = pChar->GetCore();
} }
if(Tick == Client()->PredGameTick(g_Config.m_ClDummy))
{
m_PredictedChar = pLocalChar->GetCore();
m_aClients[m_Snap.m_LocalClientId].m_Predicted = pLocalChar->GetCore();
if(pDummyChar)
m_aClients[m_PredictedDummyId].m_Predicted = pDummyChar->GetCore();
}
for(int i = 0; i < MAX_CLIENTS; i++) for(int i = 0; i < MAX_CLIENTS; i++)
if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i)) if(CCharacter *pChar = m_PredictedWorld.GetCharacterById(i))
{ {

View file

@ -499,6 +499,7 @@ public:
CRenderTools m_RenderTools; CRenderTools m_RenderTools;
void OnReset(); void OnReset();
int GetPredictionTick();
size_t ComponentCount() { return m_vpAll.size(); } size_t ComponentCount() { return m_vpAll.size(); }