Fix health and armor puresync validation#5039
Conversation
|
Was this PR carefully tested for edge cases ? I can already see that the auth token can stay valid for 3 seconds and may be reused after taking damage, allowing the player to heal back mtasa-blue/Server/mods/deathmatch/logic/CPed.cpp Lines 422 to 425 in 46160c3 |
…lass to enhance synchronization and prevent unauthorized changes
|
Good catch you're right, I missed this edge case in the initial testing. The token was only consumed on a matching increase, so taking damage in between left it valid and allowed syncing back to the authorized value within the 3s window. Fixed in the latest commit: pending health/armor authorizations are now invalidated on a meaningful sync decrease (HEALTH_AUTH_EPSILON / ARMOR_AUTH_EPSILON), so heal-back after damage is rejected. The threshold matches the auth epsilon to avoid false invalidation from wire quantization (~0.78 health step). Thanks for flagging this. |
Summary
Align player health/armor puresync with gameplay limits and make server state authoritative.
SPlayerHealthSyncmax from255to200andSPlayerArmorSyncmax from127.5to100CNetAPI,CPedSync) instead of reading raw GTA memoryCPed::SetHealth()toGetMaxHealth()AuthorizeHealthChange/AuthorizeArmorChange)SET_ELEMENT_HEALTH/SET_PED_ARMOR) back to the syncing client when values are clamped or rejectedSyncDataTypes_Tests.cppComplements #3983, which already added client-side
setPedArmorvalidation and server armor clamping.Motivation
Fixes #3791.
#3791 reported that client and server health/armor could diverge. For example, a client could use
setPedArmor(me, 9999)while the server reflected wire-encoded caps (127.5armor, up to255health) that did not match script limits or anti-cheat expectations.This was discussed in #3791 with different views:
getPedArmor/getElementHealth127.5/255come from 8-bit sync encoding, not gameplay limitsRelated issues/commits reviewed while implementing this:
583e675da9): urgent client/server armor clamp fix; this PR completes the remaining setPedArmor and setElementHealth synchronization problems from Client to Server #3791 scope7d7302bf61(2009): original sync ranges were health0–200, armor0–1009b50a0d657(2013): introduced255/127.5as 8-bit quantization capsdac27a9de4(2015): removed old/new protocol split, leaving255/127.5permanentc4f55858c9/ Add MockBitStream and sync structure round-trip tests #4791: sync structure round-trip testsThis PR intentionally does not include:
setPedArmor/setElementHealthsetPedStatchangesClient and server must be updated together because sync struct ranges changed.
Test plan
Manual:
crun setPedArmor(localPlayer, 9999)→ client ≤ 100;srun getPedArmor(player)must never return127.5crun setElementHealth(localPlayer, 999)→ servergetElementHealth(player)≤GetMaxHealth(), never255setPedArmor(player, 75)→ both sides report ~75createPickuparmor/health pickup still works via serverUse()onPlayerDamage/onPedDamagewith correct deltasAutomated:
SyncDataTypes_Tests(updated ranges + new clamp round-trip tests)Checklist