roblox-code-review
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRoblox 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
严重程度指南
| Severity | Examples |
|---|---|
| Critical | Client-authoritative rewards/damage/currency; unvalidated remote args (NaN, instance spoofing); purchases granted outside |
| High | Data loss paths (no |
| Medium | Deprecated/superseded APIs; |
| Low | Style, naming, missing types, magic numbers, dead code, minor inefficiencies. |
| 严重程度 | 示例 |
|---|---|
| 严重 | 由客户端主导奖励、伤害或货币发放;未校验的 Remote 参数(NaN、Instance 伪造);在 |
| 高 | 数据丢失路径(缺少 |
| 中 | 已弃用或被取代的 API; |
| 低 | 样式、命名、缺少类型标注、魔法数字、死代码、轻微性能低效。 |
Checklist
检查清单
Security ()
roblox-security- Every /
OnServerEvent: types checked withOnServerInvoke, numberstypeof, strings length/UTF-8 checked, instancesmath.isfinite+IsA, rate limited, context checked.IsDescendantOf(trusted) - No server-only logic, admin lists, or secrets in /
ReplicatedStorage/StarterPlayer.Workspace - /
ProximityPrompt/ClickDetectorhandlers re-validate distance/state on the server.Touched - Gameplay-critical unanchored parts are server-owned.
Data ()
roblox-data-stores- Session locking (ProfileStore or equivalent); for read-modify-write; retries with backoff.
UpdateAsync - flushes saves in parallel; no saves of
BindToClose/Instance/mixed tables.Vector3 - Failed loads never overwritten with defaults; player-keyed tables cleared on leave.
- Keys stable (), Studio uses a separate store/universe.
User_{UserId}
Monetization ()
roblox-monetization- Single ; idempotent by
ProcessReceipt; returnsPurchaseIdonly after persisting.PurchaseGranted - 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 () and characters already spawned.
for _, p in Players:GetPlayers() - 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 (/nil checks for
WaitForChildcontent).Workspace
Performance ()
roblox-performance- No per-frame /
FindFirstChild/GetDescendants; params objects reused.Instance.new - 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 (), fail closed.
FilterStringAsync - Chat uses ; public editable text rate-limited (≥ 1 minute).
TextChatService
Modern API usage
- ,
task.*variants,*Async, mover constraints,Raycast,PivotTo,Animator:LoadAnimation,TextChatService,UIDragDetectorcollision-group APIs,workspace+CreatePath.ComputeAsync - Full map of deprecated and superseded members: references/deprecated-apis.md.
Code quality ()
roblox-luau- with typed public APIs; services via
--!strict; noGetService/_G.shared - Clear module boundaries; config separated from logic; tests for pure logic ().
roblox-testing
安全()
roblox-security- 每个 /
OnServerEvent的处理逻辑:用OnServerInvoke检查类型,用typeof检查数字,检查字符串长度和 UTF-8,对 Instance 使用math.isfinite+IsA,实施速率限制,并检查调用上下文。IsDescendantOf(trusted) - /
ReplicatedStorage/StarterPlayer中不得包含仅限服务端的逻辑、管理员列表或机密。Workspace - 服务器端必须重新验证 /
ProximityPrompt/ClickDetector处理器中的距离和状态。Touched - 关键玩法中的未锚定部件应由服务端掌控。
数据()
roblox-data-stores- 使用会话锁定(或同类方案);读改写操作使用
ProfileStore;采用退避机制进行重试。UpdateAsync - 应并行刷新待保存数据;不得保存
BindToClose/Instance/混合类型表。Vector3 - 加载失败的数据绝不能被默认值覆盖;玩家离开时清空以玩家为键的表。
- Key 保持稳定();Studio 使用独立的 store 和 universe。
User_{UserId}
商业化()
roblox-monetization- 仅有一个 ;按
ProcessReceipt保证幂等;只有在持久化完成后才返回PurchaseId。PurchaseGranted - 权益需在玩家加入游戏时及会话内购买后进行检查;价格不能硬编码;付费随机物品需公开概率并遵守
Pass。PolicyService
正确性与生命周期()
roblox-architecture- 处理已经进入游戏的玩家()以及已经生成的角色。
for _, p in Players:GetPlayers() - 角色重生时重建角色级状态;玩家离开时清理玩家级状态。
- 模块顶层不得 yield;不得存在循环 require;每份状态只能有一个所有者。
- 能够安全处理 Deferred Event(不依赖处理器同步运行)。
- 客户端代码应符合 Streaming 安全要求(对 内容使用
Workspace/nil 检查)。WaitForChild
性能()
roblox-performance- 禁止逐帧调用 /
FindFirstChild/GetDescendants;复用参数对象。Instance.new - 采用事件驱动而非轮询;Think 循环应进行节流并错峰调度。
- Tween 和装饰性效果在客户端执行;Remote 消息采用批处理或节流;消息负载保持最小。
- 及时断开连接或销毁 Instance;不得使用无界缓存。
文本与安全()
roblox-text-chat- 所有展示给其他玩家的玩家创作文本都必须在服务端进行过滤(),并采用 fail-closed 策略。
FilterStringAsync - Chat 使用 ;公开可编辑文本应限频(间隔 ≥ 1 分钟)。
TextChatService
现代 API 使用
- 使用 、
task.*变体、*Async、mover constraints、Raycast、PivotTo、Animator:LoadAnimation、TextChatService、UIDragDetector碰撞组 API、workspace+CreatePath。ComputeAsync - 完整的已弃用和被取代成员映射表:references/deprecated-apis.md。
代码质量()
roblox-luau- 使用 ,并为公共 API 添加类型标注;通过
--!strict获取服务;不得使用GetService/_G。shared - 模块边界清晰;配置与逻辑分离;为纯逻辑编写测试()。
roblox-testing
Output format
输出格式
text
undefinedtext
undefinedSummary
Summary
<2–3 sentences: overall risk, the most important fixes>
<2–3 sentences: overall risk, the most important fixes>
Findings
Findings
- [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.
- [High] ...
- [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.
- [High] ...
Modernization (optional)
Modernization (optional)
- Replace →
wait()(12 occurrences) ...task.wait()
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()(12 occurrences) ...task.wait()
主动提出应用修复;在修复时,除缺陷本身外保持行为不变,并重新运行相关检查(类型检查、测试、通过 `roblox-studio-mcp` 进行 Studio Playtest)。