Loading...
Loading...
Design and harden Roblox client/server networking with RemoteEvent, RemoteFunction, and UnreliableRemoteEvent; server authority, argument and Instance validation, rate limits, proximity/ownership checks, targeted replication, streaming, lifecycle, prediction, and reconciliation. Use for Roblox remotes, exploits, request spam, multiplayer replication, network ownership, high-frequency cosmetic updates, or server/client desynchronization.
npx skill4agent add gamedev-skills/awesome-gamedev-agent-skills roblox-networkingroblox-luauroblox-luauroblox-datastoresroblox-physicsFireClient| Primitive | Use | Do not use |
|---|---|---|
| ordered, reliable one-way requests/facts | continuous samples where newer replaces older |
| ephemeral cosmetic/continuous state tolerant of loss and reordering | purchases, damage decisions, inventory, one-shot state transitions |
| bounded client-to-server query that truly needs an immediate reply | server-to-client invocation; long/uncertain work; ordinary commands |
RemoteEvent:FireClient()-- ServerScriptService/CombatRequests.server.luau
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local attack = ReplicatedStorage.Remotes.Attack
local lastRequest: {[Player]: number} = {}
local RANGE = 12
local COOLDOWN = 0.25
attack.OnServerEvent:Connect(function(player: Player, target: unknown)
local now = Workspace:GetServerTimeNow()
if now - (lastRequest[player] or -math.huge) < COOLDOWN then return end
lastRequest[player] = now
if typeof(target) ~= "Instance" or not target:IsA("Model") then return end
if not target:IsDescendantOf(Workspace.Characters) then return end
local targetHumanoid = target:FindFirstChildOfClass("Humanoid")
local targetRoot = target:FindFirstChild("HumanoidRootPart")
local character = player.Character
local root = character and character:FindFirstChild("HumanoidRootPart")
local humanoid = character and character:FindFirstChildOfClass("Humanoid")
if not targetHumanoid or not targetRoot or not root or not humanoid then return end
if humanoid.Health <= 0 or targetHumanoid.Health <= 0 then return end
if (root.Position - targetRoot.Position).Magnitude > RANGE then return end
if not serverCombatStateAllowsAttack(player, now) then return end
targetHumanoid:TakeDamage(serverDamageFor(player))
end)
Players.PlayerRemoving:Connect(function(player)
lastRequest[player] = nil
end)type Bucket = {tokens: number, updatedAt: number}
local buckets: {[Player]: Bucket} = {}
local CAPACITY, REFILL_PER_SECOND = 6, 3
local function consume(player: Player, cost: number): boolean
local now = os.clock()
local bucket = buckets[player] or {tokens = CAPACITY, updatedAt = now}
bucket.tokens = math.min(CAPACITY,
bucket.tokens + (now - bucket.updatedAt) * REFILL_PER_SECOND)
bucket.updatedAt = now
if bucket.tokens < cost then buckets[player] = bucket; return false end
bucket.tokens -= cost
buckets[player] = bucket
return true
endUnreliableRemoteEventRemoteEventUnreliableRemoteEvent| Symptom | Likely cause | Remedy |
|---|---|---|
| exploiter chooses damage/price | outcome accepted from client | send intent/ID; derive and apply on server |
| arbitrary object can be deleted | only | validate class, ancestry, ownership, state, and allowlisted operation |
| server stalls on a player | server invokes client | replace with asynchronous events |
| valid player triggers throttling | per-frame reliable messages | lower frequency, state replication, batching, or unreliable cosmetics |
| old packet reverses new effect | unordered unreliable samples treated as commands | make samples replaceable/versioned; use reliable event for transitions |
| remote breaks after respawn | cached character/root | resolve current character during handling and reject stale state |
| private data leaks | | use |
| distance check is bypassed | client-owned object moved near target | anchor/server-own critical object and validate full server context |
references/validation-and-testing.mdroblox-luauroblox-charactersroblox-physicsroblox-studio-workflowhttps://create.roblox.com/docs/scripting/events/remotehttps://create.roblox.com/docs/scripting/security/client-server-boundaryhttps://create.roblox.com/docs/physics/network-ownershiphttps://create.roblox.com/docs/studio/testing-modes