Am i doing hitbox replication right?

As the title saids, i want hitbox replicatoin.

The problem, I HAVE NO IDEA WHAT TO DO??

I currently have client sends request → server validates

The currenct code tries to put the hitbox where the player WAS when they sent the request,

        local ServerPosition = hrp.CFrame
		local ClientPosition = data.position
		local serverPos = ServerPosition.Position
		local clientPos = ClientPosition.Position
		local MaxDist =  ClientAccuracy*100
		local offset = clientPos-serverPos
		local distance = offset.Magnitude
		
		if distance > MaxDist then
			clientPos= serverPos + offset.Unit * MaxDist
		end
		
		local clamped =  CFrame.new(clientPos) * ClientPosition.Rotation

I have NO IDEA if this is good or bad, to me it feels good (with 150 ms simulated ping) but at the same time there i have NO idea if this is a good way to do hitboxes.

PLEASE if someone knows how it should be done, give me the basic idea. Ive been fighting this loop of thought and i need someone else to break it.

1 Like

Your current approach is okay as a basic sanity check, but it is not true lag compensation.

Clamping the client position only limits how far the client can move the hitbox from the server’s current position. It does not prove that the player was actually there when the attack happened, and the client can still send a fake position or rotation.

A more reliable setup is:

  1. The client sends the attack timestamp and attack data.
  2. The server stores a short history of each character’s positions.
  3. The server rewinds to the attacker’s position at that timestamp.
  4. The server creates or checks the hitbox from the rewound position.
  5. The server validates cooldowns, attack range, state, and timestamp limits.

The server should remain authoritative. The client can tell the server when an attack was started, but it should not be allowed to decide the final hitbox position.

Your clamp can still be used as an additional validation layer, but I would also:

  • reject timestamps that are too old
  • validate the attack rotation
  • validate the player’s current state and cooldown
  • limit how much rewind is allowed
  • avoid trusting a full client-provided CFrame

For a simpler system, you can let the server use the player’s current position and slightly enlarge the hitbox based on ping. For a more accurate system, use server-side position history and rewind.

1 Like

Alright, I think i got it now???

Every frame im now calculating what position the player was:

		local runConn = RunService.Heartbeat:Connect(function(dt)
			local char = plr.Character
			if not char then return end

			local hrp = char:FindFirstChild("HumanoidRootPart")
			if not hrp then return end

			local currentTime = workspace:GetServerTimeNow()
			local history = PlayerPositionRollback[plr.UserId]

			if history then
				table.insert(history, {Time = currentTime, CFrame = hrp.CFrame})

				while #history > 0 and (currentTime - history[1].Time) > MaxHistoryAge do
					table.remove(history, 1)
				end
			end
		end)

Then when the client makes a request, we check the rollback.

function RewindUser(userId, ping)
	local history = PlayerPositionRollback[userId]
	if not history or #history == 0 then return nil end
	
	-- I did abit of research earlier and this made it feel better somehow
	local Buffer = 0.05
	local targetTime = workspace:GetServerTimeNow() - (ping/2) + Buffer
	
	-- refuse the client from going to far back
	if targetTime <= history[1].Time then
		return history[1].CFrame
	end

	if targetTime >= history[#history].Time then
		return history[#history].CFrame
	end
	
	-- merge two frames together to make it feel better i guess
	for i = 1, #history - 1 do
		-- ..merge
	end
	
	-- fallback to latest frame
	return history[#history].CFrame
end

Im not sure if this is the correct idea, but i think it is good

Your clamp is fine as an additional sanity check, but it is not real lag compensation. You are comparing the client position against the server’s current position, not the position the player had when the request was sent. You are also fully trusting the client-provided rotation.

Ideally, the server should store a short position history, validate the client timestamp, rewind to the appropriate server-recorded position, and create the hitbox itself. Keep the server authoritative and use the client position only as a hint, not as the final source of truth.

1 Like