roblox-code-review

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Roblox code review

Roblox 代码审查

Review in severity order. Report each finding with file:line, severity, what breaks, and the fix. Verify claims against the code (and the engine reference when unsure) — don't pattern-match blindly.
按严重程度顺序进行审查。每个发现都应报告 文件:行号、严重程度、会出现什么问题以及修复方法。 对照代码验证结论(不确定时查阅引擎参考文档)——不要盲目进行模式匹配。

Severity guide

严重程度指南

SeverityExamples
CriticalClient-authoritative rewards/damage/currency; unvalidated remote args (NaN, instance spoofing); purchases granted outside
ProcessReceipt
or non-idempotent; data saved with
SetAsync
from multiple servers without session locking; secrets/API keys in replicated code; unfiltered player text shown to others.
HighData loss paths (no
BindToClose
, saving default data after a failed load, no retry); memory leaks (connections, player-keyed tables);
InvokeClient
; per-frame remotes; infinite yields (
WaitForChild
without timeout on optional instances,
RemoteFunction
handlers that can yield forever); streaming-unsafe client indexing.
MediumDeprecated/superseded APIs;
wait
/
spawn
/
delay
; polling loops; server-side tweens; missing
pcall
on network/yielding APIs; missing late-joiner handling; race conditions on
CharacterAdded
.
LowStyle, naming, missing types, magic numbers, dead code, minor inefficiencies.
严重程度示例
严重由客户端主导奖励、伤害或货币发放;未校验的 Remote 参数(NaN、Instance 伪造);在
ProcessReceipt
之外发放购买内容,或购买处理流程非幂等;多台服务器在没有会话锁的情况下通过
SetAsync
保存数据;复制到客户端的代码中存在机密或 API 密钥;向其他玩家展示未经过滤的玩家文本。
高数据丢失路径(缺少
BindToClose
、加载失败后仍保存默认数据、没有重试);内存泄漏(事件连接、以玩家为键的表);
InvokeClient
;逐帧触发 Remote;无限期 yield(对可选 Instance 使用没有超时的
WaitForChild
、
RemoteFunction
处理器可能永久 yield);客户端索引不符合 Streaming 安全要求。
中已弃用或被取代的 API;
wait
/
spawn
/
delay
;轮询循环;在服务端执行 Tween;网络 API 或可能 yield 的 API 调用缺少
pcall
;缺少 Late Joiner(后加入玩家)处理;
CharacterAdded
上存在竞态条件。
低样式、命名、缺少类型标注、魔法数字、死代码、轻微性能低效。

Checklist

检查清单

Security (
roblox-security
)
  • Every
    OnServerEvent
    /
    OnServerInvoke
    : types checked with
    typeof
    , numbers
    math.isfinite
    , strings length/UTF-8 checked, instances
    IsA
    +
    IsDescendantOf(trusted)
    , rate limited, context checked.
  • No server-only logic, admin lists, or secrets in
    ReplicatedStorage
    /
    StarterPlayer
    /
    Workspace
    .
  • ProximityPrompt
    /
    ClickDetector
    /
    Touched
    handlers re-validate distance/state on the server.
  • Gameplay-critical unanchored parts are server-owned.
Data (
roblox-data-stores
)
  • Session locking (ProfileStore or equivalent);
    UpdateAsync
    for read-modify-write; retries with backoff.
  • BindToClose
    flushes saves in parallel; no saves of
    Instance
    /
    Vector3
    /mixed tables.
  • Failed loads never overwritten with defaults; player-keyed tables cleared on leave.
  • Keys stable (
    User_{UserId}
    ), Studio uses a separate store/universe.
Monetization (
roblox-monetization
)
  • Single
    ProcessReceipt
    ; idempotent by
    PurchaseId
    ; returns
    PurchaseGranted
    only after persisting.
  • Pass perks checked on join and after in-session purchase; prices not hardcoded; paid random items disclose odds and respect
    PolicyService
    .
Correctness & lifecycle (
roblox-architecture
)
  • Handles players already in game (
    for _, p in Players:GetPlayers()
    ) and characters already spawned.
  • Per-character state rebuilt on respawn; per-player state cleaned on
    PlayerRemoving
    .
  • No yields at module top level; no circular requires; one owner per piece of state.
  • Deferred-event safe (doesn't rely on handlers running synchronously).
  • Client code streaming-safe (
    WaitForChild
    /nil checks for
    Workspace
    content).
Performance (
roblox-performance
)
  • No per-frame
    FindFirstChild
    /
    GetDescendants
    /
    Instance.new
    ; params objects reused.
  • Event-driven instead of polling; think loops throttled and staggered.
  • Tweens and cosmetic effects on clients; remotes batched/throttled; payloads minimal.
  • Connections disconnected / instances destroyed; no unbounded caches.
Text & safety (
roblox-text-chat
)
  • All player-authored text shown to others filtered server-side (
    FilterStringAsync
    ), fail closed.
  • Chat uses
    TextChatService
    ; public editable text rate-limited (≥ 1 minute).
Modern API usage
  • task.*
    ,
    *Async
    variants,
    Raycast
    , mover constraints,
    PivotTo
    ,
    Animator:LoadAnimation
    ,
    TextChatService
    ,
    UIDragDetector
    ,
    workspace
    collision-group APIs,
    CreatePath
    +
    ComputeAsync
    .
  • Full map of deprecated and superseded members: references/deprecated-apis.md.
Code quality (
roblox-luau
)
  • --!strict
    with typed public APIs; services via
    GetService
    ; no
    _G
    /
    shared
    .
  • Clear module boundaries; config separated from logic; tests for pure logic (
    roblox-testing
    ).
安全(
roblox-security
)
  • 每个
    OnServerEvent
    /
    OnServerInvoke
    的处理逻辑:用
    typeof
    检查类型,用
    math.isfinite
    检查数字,检查字符串长度和 UTF-8,对 Instance 使用
    IsA
    +
    IsDescendantOf(trusted)
    ,实施速率限制,并检查调用上下文。
  • ReplicatedStorage
    /
    StarterPlayer
    /
    Workspace
    中不得包含仅限服务端的逻辑、管理员列表或机密。
  • 服务器端必须重新验证
    ProximityPrompt
    /
    ClickDetector
    /
    Touched
    处理器中的距离和状态。
  • 关键玩法中的未锚定部件应由服务端掌控。
数据(
roblox-data-stores
)
  • 使用会话锁定(
    ProfileStore
    或同类方案);读改写操作使用
    UpdateAsync
    ;采用退避机制进行重试。
  • BindToClose
    应并行刷新待保存数据;不得保存
    Instance
    /
    Vector3
    /混合类型表。
  • 加载失败的数据绝不能被默认值覆盖;玩家离开时清空以玩家为键的表。
  • Key 保持稳定(
    User_{UserId}
    );Studio 使用独立的 store 和 universe。
商业化(
roblox-monetization
)
  • 仅有一个
    ProcessReceipt
    ;按
    PurchaseId
    保证幂等;只有在持久化完成后才返回
    PurchaseGranted
    。
  • Pass
    权益需在玩家加入游戏时及会话内购买后进行检查;价格不能硬编码;付费随机物品需公开概率并遵守
    PolicyService
    。
正确性与生命周期(
roblox-architecture
)
  • 处理已经进入游戏的玩家(
    for _, p in Players:GetPlayers()
    )以及已经生成的角色。
  • 角色重生时重建角色级状态;玩家离开时清理玩家级状态。
  • 模块顶层不得 yield;不得存在循环 require;每份状态只能有一个所有者。
  • 能够安全处理 Deferred Event(不依赖处理器同步运行)。
  • 客户端代码应符合 Streaming 安全要求(对
    Workspace
    内容使用
    WaitForChild
    /nil 检查)。
性能(
roblox-performance
)
  • 禁止逐帧调用
    FindFirstChild
    /
    GetDescendants
    /
    Instance.new
    ;复用参数对象。
  • 采用事件驱动而非轮询;Think 循环应进行节流并错峰调度。
  • Tween 和装饰性效果在客户端执行;Remote 消息采用批处理或节流;消息负载保持最小。
  • 及时断开连接或销毁 Instance;不得使用无界缓存。
文本与安全(
roblox-text-chat
)
  • 所有展示给其他玩家的玩家创作文本都必须在服务端进行过滤(
    FilterStringAsync
    ),并采用 fail-closed 策略。
  • Chat 使用
    TextChatService
    ;公开可编辑文本应限频(间隔 ≥ 1 分钟)。
现代 API 使用
  • 使用
    task.*
    、
    *Async
    变体、
    Raycast
    、mover constraints、
    PivotTo
    、
    Animator:LoadAnimation
    、
    TextChatService
    、
    UIDragDetector
    、
    workspace
    碰撞组 API、
    CreatePath
    +
    ComputeAsync
    。
  • 完整的已弃用和被取代成员映射表:references/deprecated-apis.md。
代码质量(
roblox-luau
)
  • 使用
    --!strict
    ,并为公共 API 添加类型标注;通过
    GetService
    获取服务;不得使用
    _G
    /
    shared
    。
  • 模块边界清晰;配置与逻辑分离;为纯逻辑编写测试(
    roblox-testing
    )。

Output format

输出格式

text
undefined
text
undefined

Summary

Summary

<2–3 sentences: overall risk, the most important fixes>
<2–3 sentences: overall risk, the most important fixes>

Findings

Findings

  1. [Critical] src/server/Shop.server.luau:42 — Price read from client argument. Impact: exploiters buy anything for 0 coins. Fix: look up ITEMS[itemId].price on the server.
  2. [High] ...
  1. [Critical] src/server/Shop.server.luau:42 — Price read from client argument. Impact: exploiters buy anything for 0 coins. Fix: look up ITEMS[itemId].price on the server.
  2. [High] ...

Modernization (optional)

Modernization (optional)

  • Replace
    wait()
    →
    task.wait()
    (12 occurrences) ...

Offer to apply fixes; when fixing, keep behavior identical except for the bug, and re-run the relevant
checks (type check, tests, Studio playtest via `roblox-studio-mcp`).
  • Replace
    wait()
    →
    task.wait()
    (12 occurrences) ...

主动提出应用修复;在修复时,除缺陷本身外保持行为不变,并重新运行相关检查(类型检查、测试、通过 `roblox-studio-mcp` 进行 Studio Playtest)。