Movement Validator
The Movement Validator module provides real-time detection of movement anomalies including speed hacks, teleports, fly hacks, and noclip.
Overview
local Rewind = require(ReplicatedStorage.Packages.Rewind)
-- Configure movement validation (server only)
Rewind.ConfigureMovementValidation({
speedTolerance = 1.3, -- Allow 30% over base speed
teleportThreshold = 50, -- Flag teleports over 50 studs
maxAirTime = 3, -- Flag flying after 3 seconds
checkNoclip = true,
})
-- Start monitoring a player
Rewind.StartMovementMonitoring(player)
-- Listen for anomalies
Rewind.OnMovementAnomaly:Connect(function(player, anomalyType, data)
print(player.Name .. " detected: " .. anomalyType)
-- Record to abuse tracker
Rewind.RecordAbuse(player, anomalyType, data)
end)
Types
AnomalyType
type AnomalyType =
| "speed_hack" -- Moving faster than allowed
| "teleport" -- Sudden large position change
| "fly_hack" -- Sustained air time without ground contact
| "noclip" -- Moving through solid objects
MovementValidationResult
type MovementValidationResult = {
valid: boolean, -- Whether movement is valid
anomalyType: AnomalyType?, -- Type of anomaly if invalid
details: {
currentSpeed: number?,
maxAllowedSpeed: number?,
distanceMoved: number?,
airTime: number?,
collidedPart: BasePart?,
}?,
}
MovementConfig
type MovementConfig = {
speedTolerance: number?, -- Multiplier above base speed (default 1.2)
teleportThreshold: number?, -- Distance in studs (default 50)
maxAirTime: number?, -- Seconds before fly detection (default 3)
checkNoclip: boolean?, -- Check for noclip (default true)
checkInterval: number?, -- How often to check (default 0.1)
violationThreshold: number?, -- Violations before flagging (default 3)
baseWalkSpeed: number?, -- Base walk speed (default 16)
baseJumpPower: number?, -- Base jump power (default 50)
groundRayDistance: number?, -- Ray distance for ground check (default 5)
noclipRayDistance: number?, -- Ray distance for noclip check (default 2)
}
PlayerMovementState
type PlayerMovementState = {
player: Player,
lastPosition: Vector3,
lastGroundedTime: number,
lastValidationTime: number,
airTime: number,
violations: {
speed: number,
teleport: number,
fly: number,
noclip: number,
},
speedMultiplier: number, -- Current speed multiplier (for abilities)
isMonitoring: boolean,
}
API Reference
ConfigureMovementValidation
Configures the movement validation system.
Rewind.ConfigureMovementValidation(config: MovementConfig): ()
Parameters:
config- The movement validation configuration
Example:
-- Strict configuration for competitive games
Rewind.ConfigureMovementValidation({
speedTolerance = 1.1, -- Only 10% tolerance
teleportThreshold = 30,
maxAirTime = 2,
checkNoclip = true,
checkInterval = 0.05, -- Check every 50ms
violationThreshold = 2, -- Flag after 2 violations
})
-- Lenient configuration for casual games
Rewind.ConfigureMovementValidation({
speedTolerance = 1.5, -- 50% tolerance for laggy players
teleportThreshold = 100,
maxAirTime = 5,
checkNoclip = true,
checkInterval = 0.2,
violationThreshold = 5,
})
StartMovementMonitoring
Starts monitoring a player for movement anomalies.
Rewind.StartMovementMonitoring(player: Player): ()
Parameters:
player- The player to start monitoring
Example:
game.Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
-- Wait for character to load
character:WaitForChild("HumanoidRootPart")
-- Start monitoring
Rewind.StartMovementMonitoring(player)
end)
end)
StopMovementMonitoring
Stops monitoring a player.
Rewind.StopMovementMonitoring(player: Player): ()
Parameters:
player- The player to stop monitoring
Example:
game.Players.PlayerRemoving:Connect(function(player)
Rewind.StopMovementMonitoring(player)
end)
-- Or when entering a safe zone
local function enterSafeZone(player)
Rewind.StopMovementMonitoring(player)
end
ValidateMovement
Manually validates a player's current movement.
Rewind.ValidateMovement(player: Player, position: Vector3?, velocity: Vector3?): MovementValidationResult
Parameters:
player- The player to validateposition- Optional override position (uses current if nil)velocity- Optional velocity vector
Returns: MovementValidationResult - The validation result
Example:
-- Manual validation check
local result = Rewind.ValidateMovement(player)
if not result.valid then
print("Invalid movement:", result.anomalyType)
print("Details:", result.details)
end
-- Validate client-reported position
remotes.MoveRequest.OnServerEvent:Connect(function(player, reportedPosition)
local result = Rewind.ValidateMovement(player, reportedPosition)
if result.valid then
-- Accept the movement
player.Character:MoveTo(reportedPosition)
else
-- Reject and correct
correctPlayerPosition(player)
end
end)
SetPlayerSpeedMultiplier
Sets a temporary speed multiplier for a player (for abilities like sprinting).
Rewind.SetPlayerSpeedMultiplier(player: Player, multiplier: number, duration: number?): ()
Parameters:
player- The player to set multiplier formultiplier- The speed multiplier (e.g., 2.0 for double speed)duration- Optional duration in seconds (nil = permanent until changed)
Example:
-- Sprint ability
local function activateSprint(player)
-- Allow 2x speed for 10 seconds
Rewind.SetPlayerSpeedMultiplier(player, 2.0, 10)
-- Also update the humanoid
player.Character.Humanoid.WalkSpeed = 32
task.delay(10, function()
player.Character.Humanoid.WalkSpeed = 16
end)
end
-- Speed boost pickup
local function collectSpeedBoost(player)
Rewind.SetPlayerSpeedMultiplier(player, 1.5, 30)
player.Character.Humanoid.WalkSpeed = 24
end
-- Reset speed
local function resetSpeed(player)
Rewind.SetPlayerSpeedMultiplier(player, 1.0)
player.Character.Humanoid.WalkSpeed = 16
end
GetMovementViolations
Gets the current violation counts for a player.
Rewind.GetMovementViolations(player: Player): {speed: number, teleport: number, fly: number, noclip: number}?
Parameters:
player- The player to get violations for
Returns: Violation counts by type, or nil if not monitoring
Example:
local violations = Rewind.GetMovementViolations(player)
if violations then
print("Speed violations:", violations.speed)
print("Teleport violations:", violations.teleport)
print("Fly violations:", violations.fly)
print("Noclip violations:", violations.noclip)
local total = violations.speed + violations.teleport + violations.fly + violations.noclip
if total > 10 then
-- Take action
Rewind.RecordAbuse(player, "speed_hack", violations)
end
end
ClearMovementViolations
Clears all violations for a player.
Rewind.ClearMovementViolations(player: Player): ()
Parameters:
player- The player to clear violations for
Example:
-- Clear after legitimate teleport
local function teleportPlayer(player, destination)
-- Stop monitoring during teleport
Rewind.StopMovementMonitoring(player)
-- Teleport
player.Character:MoveTo(destination)
-- Wait for physics to settle
task.wait(0.5)
-- Clear any violations and resume
Rewind.ClearMovementViolations(player)
Rewind.StartMovementMonitoring(player)
end
Events
OnMovementAnomaly
Fired when a movement anomaly is detected.
Rewind.OnMovementAnomaly:Connect(function(player: Player, anomalyType: AnomalyType, data: {[string]: any})
print(player.Name .. " anomaly: " .. anomalyType)
if anomalyType == "speed_hack" then
print("Speed:", data.currentSpeed, "Max:", data.maxAllowedSpeed)
elseif anomalyType == "teleport" then
print("Distance:", data.distanceMoved)
elseif anomalyType == "fly_hack" then
print("Air time:", data.airTime)
elseif anomalyType == "noclip" then
print("Collided with:", data.collidedPart.Name)
end
end)
Integration Examples
With Abuse Tracker
-- Start both systems
Rewind.StartAbuseTracking({
thresholds = { warn = 3, kick = 5, ban = 10 },
})
Rewind.ConfigureMovementValidation({
speedTolerance = 1.2,
teleportThreshold = 50,
})
-- Connect movement anomalies to abuse tracker
Rewind.OnMovementAnomaly:Connect(function(player, anomalyType, data)
-- Map to abuse reasons
local reasonMap = {
speed_hack = "speed_hack",
teleport = "teleport",
fly_hack = "fly_hack",
noclip = "clip",
}
Rewind.RecordAbuse(player, reasonMap[anomalyType], data)
end)
-- Monitor all players
game.Players.PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function()
task.wait(1) -- Wait for character to load
Rewind.StartMovementMonitoring(player)
end)
end)
With Game Abilities
-- Track active abilities to prevent false positives
local activeAbilities = {}
local function activateAbility(player, abilityName)
activeAbilities[player] = abilityName
if abilityName == "Sprint" then
Rewind.SetPlayerSpeedMultiplier(player, 2.0, 10)
elseif abilityName == "Dash" then
-- Dash might trigger teleport detection
Rewind.StopMovementMonitoring(player)
-- Perform dash
performDash(player)
task.wait(0.5)
Rewind.ClearMovementViolations(player)
Rewind.StartMovementMonitoring(player)
elseif abilityName == "Flight" then
-- Flight ability - disable fly detection
Rewind.SetPlayerSpeedMultiplier(player, 1.5, 30)
-- You might want to track this separately
end
activeAbilities[player] = nil
end
-- Filter anomalies based on active abilities
Rewind.OnMovementAnomaly:Connect(function(player, anomalyType, data)
local ability = activeAbilities[player]
-- Don't flag if ability explains the anomaly
if ability == "Flight" and anomalyType == "fly_hack" then
return
end
if ability == "Dash" and anomalyType == "teleport" then
return
end
-- Record legitimate violations
Rewind.RecordAbuse(player, anomalyType, data)
end)
Custom Zones
-- Define zones where certain checks are disabled
local safeZones = {
lobby = { position = Vector3.new(0, 0, 0), radius = 100 },
spawn = { position = Vector3.new(500, 0, 0), radius = 50 },
}
local noFlyZones = {} -- Zones where flying IS allowed
local function isInSafeZone(position)
for _, zone in pairs(safeZones) do
if (position - zone.position).Magnitude <= zone.radius then
return true
end
end
return false
end
Rewind.OnMovementAnomaly:Connect(function(player, anomalyType, data)
local character = player.Character
if not character then return end
local position = character.PrimaryPart.Position
-- Ignore anomalies in safe zones
if isInSafeZone(position) then
return
end
-- Process the anomaly
Rewind.RecordAbuse(player, anomalyType, data)
end)
Best Practices
1. Account for Lag
Rewind.ConfigureMovementValidation({
-- Higher tolerance for laggier games
speedTolerance = 1.3,
-- Higher threshold for teleport
teleportThreshold = 75,
-- More violations before flagging
violationThreshold = 5,
-- Less frequent checks
checkInterval = 0.2,
})
2. Handle Legitimate Teleports
local function safeTeleport(player, destination)
-- Pause monitoring
Rewind.StopMovementMonitoring(player)
-- Teleport
player.Character:SetPrimaryPartCFrame(CFrame.new(destination))
-- Wait for physics
task.wait(1)
-- Clear and resume
Rewind.ClearMovementViolations(player)
Rewind.StartMovementMonitoring(player)
end
3. Speed Ability Management
local playerSpeeds = {}
local function setPlayerSpeed(player, speed, duration)
local baseSpeed = 16
local multiplier = speed / baseSpeed
playerSpeeds[player] = multiplier
Rewind.SetPlayerSpeedMultiplier(player, multiplier, duration)
player.Character.Humanoid.WalkSpeed = speed
if duration then
task.delay(duration, function()
if playerSpeeds[player] == multiplier then
playerSpeeds[player] = 1
player.Character.Humanoid.WalkSpeed = baseSpeed
end
end)
end
end
4. Vehicle Integration
-- Vehicles have different speed limits
local function onVehicleEnter(player, vehicle)
local vehicleMaxSpeed = vehicle:GetAttribute("MaxSpeed") or 100
local baseSpeed = 16
Rewind.SetPlayerSpeedMultiplier(player, vehicleMaxSpeed / baseSpeed)
end
local function onVehicleExit(player)
Rewind.SetPlayerSpeedMultiplier(player, 1.0)
end
5. Debug Mode
local DEBUG_MODE = true
if DEBUG_MODE then
Rewind.OnMovementAnomaly:Connect(function(player, anomalyType, data)
-- Don't actually record, just log
warn(string.format(
"[DEBUG] %s - %s: %s",
player.Name,
anomalyType,
game:GetService("HttpService"):JSONEncode(data)
))
end)
else
Rewind.OnMovementAnomaly:Connect(function(player, anomalyType, data)
Rewind.RecordAbuse(player, anomalyType, data)
end)
end