Feedback on obtaining clients' pings for lag compensation

Currently I am trying to think of a method to help with lag compensation. Earlier I saw a video (Netcode 101) which showed BF1’s method of handling laggy players:

There is a ping threshold (140, 150, etc) which signals the server when to use client-sided hit detection and do some sort of verification on the server or do fully server-sided detection whenever the ping is over the threshold.

However, since this accounts for ping and it could be dangerous to leave that logic to the player to decide whenever it is over, I needed a secure method of obtaining pings on the server.

Here is my current method: local HttpService = game:GetService(“HttpService”)
local Players = game:GetService(“Players”)

local NetworkingModule = {}
local Thread

local function RegisterPlayer(player)
    NetworkingModule.RegisteredPlayers[player] = 0
end


local function UnregisterPlayer(player)
    if NetworkingModule.RegisteredPlayers[player] then
        NetworkingModule.RegisteredPlayers[player] = nil
    end
end


local function HandlePlayer(player)
    local unique_key = tostring(HttpService:GenerateGUID(false))
    local received_key = NetworkingModule.Receiver:InvokeClient(player)
    if received_key ~= unique_key then
        player:Kick("Client desynchronization")
    end
end


local function BeginRecording()
    while true do
        for player, status in pairs(NetworkingModule.RegisteredPlayers) do
            if status == 1 then continue end
            NetworkingModule.Promise.try(function()
                NetworkingModule.RegisteredPlayers[player] = 1
                HandlePlayer(player)
            end):andThen(function()
                NetworkingModule.RegisteredPlayers[player] = 0
            end)
        end
        Thread:Wait(3)
    end
end


function NetworkingModule:Init()
    coroutine.wrap(BeginRecording)()

    self._data.PlayerPings = {}
    local replicationLagEvent = self:_RegisterEvent("ReplicationLag", "RemoteFunction")
    NetworkingModule.Receiver = self:_RegisterEvent("Receiver", "RemoteFunction")
    NetworkingModule.RegisteredPlayers = {}
    NetworkingModule.Promise = self.util.promise
    Thread = self.util.wait

    Players.PlayerAdded:Connect(RegisterPlayer)
    Players.PlayerRemoving:Connect(UnregisterPlayer)

    function replicationLagEvent.OnServerInvoke()
        return
    end
end

return NetworkingModule

I used promises and added a status to the player to avoid yielding and having double calls, then sent the key to the player which is then returned like this:

self._events.Receiver.OnClientInvoke = function(t)
    return t
end

Am I doing this wrong? Is this sufficient? If there are other better methods of lag compensation without having to account for ping, please let me know. Thanks!

2 Likes

Surprisingly, found a better method suited for my case literally 3 minutes after posting this.

Considering the hit detection is based off of the player’s animations (swords), I attached a .AnimationPlayed to every new player humanoid to check if the player began attacking and does the logic from there. To handle the delay between the client and the server, we will deplete the enemy’s health bar visually and then correct it whenever the server is done (can just be showed as health regeneration, however those with high pings might experience more frequent corrections).

1 Like