Creating Custom Detectors
ExtensionsStep-by-step tutorial for building, typing, and registering new server-side detection modules in RAC.
# Overview
RAC's modular architecture makes it easy to add custom detection logic for game-specific mechanics (e.g. fishing minigames, vehicle speed, or trading bots).
Every detector is a Luau ModuleScript placed in ServerScriptService/RAC/Detectors/Custom/.
# The Detector Interface
A valid detector implements the following methods:
--!strict
local Types = require(game.ReplicatedStorage.RAC.Shared.Types)
local CustomDetector = {
Name = "FishingBotDetector",
Category = "Economy" :: Types.DetectorCategory,
Enabled = true,
}
local engineRef: any = nil
function CustomDetector:Init(engine: any)
engineRef = engine
print(string.format("[RAC] %s initialized successfully.", self.Name))
end
function CustomDetector:ScanPlayer(player: Player, playerState: Types.PlayerMonitoringState, deltaTime: number)
if not self.Enabled then return end
-- Custom detection logic here
local reactionTime = player:GetAttribute("LastMinigameReactionMs")
if reactionTime and reactionTime < 30 then
-- Inhuman 30ms reaction speed: likely automated macro
self:ReportIncident(player, reactionTime)
end
end
function CustomDetector:ReportIncident(player: Player, reactionMs: number)
local detectionEngine = engineRef:GetDetectionEngine()
detectionEngine.RegisterIncident(player, {
detectorName = self.Name,
category = self.Category,
severity = "High",
confidence = 0.88,
evidence = string.format("Minigame reaction time %d ms below human threshold (150ms).", reactionMs),
metadata = { reactionMs = reactionMs },
})
end
return CustomDetector
# Dynamic Auto-Registration
During server boot, ModuleRegistry scans all child folders in ServerScriptService/RAC/Detectors/. Any ModuleScript exposing Name and ScanPlayer is automatically indexed into the main loop—no manual wiring required!
# Next Steps
- Learn how to attach game telemetry in Custom Evidence & Telemetry.
- Review Trust Boundaries.