roblox-text-chat
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseChat and text safety
聊天与文本安全
Non-negotiable rules (Roblox Community Standards)
不可违反的规则(Roblox 社区标准)
- Player-to-player conversation must go through TextChatService s (handles filtering, privacy/parental settings, and abuse reporting). The legacy
TextChannelservice/ChatLua modules are gone —ChatServiceis the only chat system.TextChatService - Any text authored by one player and shown to another (pet names, signs, guild names, trade notes,
custom UI) must be filtered with on the server before display — and re-filtered when loaded from a DataStore later.
TextService:FilterStringAsync - Editable text others can see (signs, bulletin boards) needs a rate limit of at least 1 minute.
- Respect privacy settings with /
CanUserChatAsync/CanUsersChatAsyncand mark direct-message channels withCanUsersDirectChatAsync.TextChannel:SetDirectChatRequester()
Not chat (no filtering needed): your own UI text, game status messages, admin announcements you write.
- 玩家之间的对话必须通过 TextChatService 的 (负责过滤、隐私/家长设置和滥用举报)。旧版
TextChannel服务/ChatLua 模块已被移除——ChatService是唯一的聊天系统。TextChatService - 任何由一名玩家创作并向另一名玩家展示的文本(宠物名称、告示牌、公会名称、交易备注、自定义 UI),都必须在服务器上使用 进行过滤——以后从 DataStore 加载时也必须重新过滤。
TextService:FilterStringAsync - 可编辑且他人可见的文本(告示牌、公告板)需要至少 1 分钟的速率限制。
- 遵守隐私设置,使用 /
CanUserChatAsync/CanUsersChatAsync,并通过CanUsersDirectChatAsync标记私信频道。TextChannel:SetDirectChatRequester()
不属于聊天的内容(无需过滤):你自己的 UI 文本、游戏状态消息、你编写的管理员公告。
Filtering player-authored text
过滤玩家创作的文本
luau
--!strict
local TextService = game:GetService("TextService")
-- Broadcast (e.g. a sign everyone sees). Returns nil if filtering failed: then show nothing.
local function filterForEveryone(text: string, fromUserId: number): string?
local ok, result = pcall(function()
local filterResult = TextService:FilterStringAsync(text, fromUserId, Enum.TextFilterContext.PublicChat)
return filterResult:GetNonChatStringForBroadcastAsync()
end)
return if ok then result else nil
end
-- Per-recipient (respects each viewer's age/settings; e.g. a private note).
local function filterForUser(text: string, fromUserId: number, toUserId: number): string?
local ok, result = pcall(function()
local filterResult = TextService:FilterStringAsync(text, fromUserId, Enum.TextFilterContext.PrivateChat)
return filterResult:GetNonChatStringForUserAsync(toUserId)
end)
return if ok then result else nil
end
return { forEveryone = filterForEveryone, forUser = filterForUser }- Filter on the server, after the player submits (not per keystroke); rate-limit and length-cap first.
- On failure, fail closed (show nothing / a placeholder), never the raw text.
- Store the raw text if you must, but always filter at display time (filters and viewer settings change).
- Numbers-only or short strings can still be filtered (hashtags ); design UI for that.
###
luau
--!strict
local TextService = game:GetService("TextService")
-- Broadcast (e.g. a sign everyone sees). Returns nil if filtering failed: then show nothing.
local function filterForEveryone(text: string, fromUserId: number): string?
local ok, result = pcall(function()
local filterResult = TextService:FilterStringAsync(text, fromUserId, Enum.TextFilterContext.PublicChat)
return filterResult:GetNonChatStringForBroadcastAsync()
end)
return if ok then result else nil
end
-- Per-recipient (respects each viewer's age/settings; e.g. a private note).
local function filterForUser(text: string, fromUserId: number, toUserId: number): string?
local ok, result = pcall(function()
local filterResult = TextService:FilterStringAsync(text, fromUserId, Enum.TextFilterContext.PrivateChat)
return filterResult:GetNonChatStringForUserAsync(toUserId)
end)
return if ok then result else nil
end
return { forEveryone = filterForEveryone, forUser = filterForUser }- 在服务器上、玩家提交后进行过滤(而不是每次按键时过滤);先实施速率限制并限制长度。
- 过滤失败时,必须采用失败关闭策略(不显示任何内容/显示占位符),绝不显示原始文本。
- 如果确有需要,可以存储原始文本,但始终必须在显示时进行过滤(过滤规则和观看者设置可能发生变化)。
- 纯数字或短字符串仍可能被过滤(井号 );应据此设计 UI。
###
TextChatService essentials
TextChatService 基础知识
- Defaults: creates
CreateDefaultTextChannelsandRBXGeneral;RBXSystemadds built-ins (CreateDefaultCommands,/whisper,/team, ...). Configure look via/mute,ChatWindowConfiguration,ChatInputBarConfiguration(or disable and build your own UI withBubbleChatConfigurationandTextChannel:SendAsync).TextChatService.MessageReceived - Flow: client → server
TextChannel:SendAsync(text)per recipient → filtering → clients'TextChannel.ShouldDeliverCallback(message, textSource)callbacks → display.OnIncomingMessage - Callbacks must not yield. is server-only;
ShouldDeliverCallbackandTextChatService.OnIncomingMessageare client-only (formatting).TextChannel.OnIncomingMessage - System messages: on the client (local only).
channel:DisplaySystemMessage(text) - Custom channels (team, party, proximity): create s under
TextChannelon the server,TextChatServiceto add members; check the returnedchannel:AddUserAsync(userId)'sTextSource.CanSend
luau
--!strict
-- Client: chat tags and colors via OnIncomingMessage (formatting only; never yields).
local Players = game:GetService("Players")
local TextChatService = game:GetService("TextChatService")
TextChatService.OnIncomingMessage = function(message: TextChatMessage)
local properties = Instance.new("TextChatMessageProperties")
local source = message.TextSource
if source then
local player = Players:GetPlayerByUserId(source.UserId)
if player and player:GetAttribute("VIP") then
properties.PrefixText = `<font color="#F5CD30">[VIP]</font> {message.PrefixText}`
end
end
return properties
endluau
--!strict
-- Server: a /spawn command, restricted to admins.
local Players = game:GetService("Players")
local TextChatService = game:GetService("TextChatService")
local ADMINS: { [number]: boolean } = { [123456] = true }
local command = Instance.new("TextChatCommand")
command.Name = "SpawnCommand"
command.PrimaryAlias = "/spawn"
command.Parent = TextChatService
command.Triggered:Connect(function(source: TextSource, unfilteredText: string)
if not ADMINS[source.UserId] then
return
end
local player = Players:GetPlayerByUserId(source.UserId)
print(`{player and player.Name} ran: {unfilteredText}`)
end)More: proximity chat, team channels, custom UI, and migrating from legacy chat:
references/chat-recipes.md.
- 默认设置:会创建
CreateDefaultTextChannels和RBXGeneral;RBXSystem会添加内置命令(CreateDefaultCommands、/whisper、/team等)。可通过/mute、ChatWindowConfiguration、ChatInputBarConfiguration配置外观(也可以禁用这些功能,并使用BubbleChatConfiguration和TextChannel:SendAsync构建自己的 UI)。TextChatService.MessageReceived - 流程:客户端 → 服务器针对每位接收者执行
TextChannel:SendAsync(text)→ 过滤 → 客户端的TextChannel.ShouldDeliverCallback(message, textSource)回调 → 显示。OnIncomingMessage - 回调不得 yield。仅限服务器使用;
ShouldDeliverCallback和TextChatService.OnIncomingMessage仅限客户端使用(用于格式化)。TextChannel.OnIncomingMessage - 系统消息:在客户端调用 (仅在本地显示)。
channel:DisplaySystemMessage(text) - 自定义频道(团队、队伍、附近聊天):在服务器上于 下创建
TextChatService,通过TextChannel添加成员;检查返回的channel:AddUserAsync(userId)的TextSource。CanSend
luau
--!strict
-- Client: chat tags and colors via OnIncomingMessage (formatting only; never yields).
local Players = game:GetService("Players")
local TextChatService = game:GetService("TextChatService")
TextChatService.OnIncomingMessage = function(message: TextChatMessage)
local properties = Instance.new("TextChatMessageProperties")
local source = message.TextSource
if source then
local player = Players:GetPlayerByUserId(source.UserId)
if player and player:GetAttribute("VIP") then
properties.PrefixText = `<font color="#F5CD30">[VIP]</font> {message.PrefixText}`
end
end
return properties
endluau
--!strict
-- Server: a /spawn command, restricted to admins.
local Players = game:GetService("Players")
local TextChatService = game:GetService("TextChatService")
local ADMINS: { [number]: boolean } = { [123456] = true }
local command = Instance.new("TextChatCommand")
command.Name = "SpawnCommand"
command.PrimaryAlias = "/spawn"
command.Parent = TextChatService
command.Triggered:Connect(function(source: TextSource, unfilteredText: string)
if not ADMINS[source.UserId] then
return
end
local player = Players:GetPlayerByUserId(source.UserId)
print(`{player and player.Name} ran: {unfilteredText}`)
end)更多内容:附近聊天、团队频道、自定义 UI,以及从旧版聊天迁移:
references/chat-recipes.md。
PolicyService (per-user restrictions)
PolicyService(按用户限制)
PolicyService:GetPolicyInfoForPlayerAsync(player)pcallArePaidRandomItemsRestrictedIsPaidItemTradingAllowedAreAdsAllowedAllowedExternalLinkReferencesIsSubjectToChinaPoliciesIsContentSharingAllowedAllowedExternalLinkReferencesPolicyService:GetPolicyInfoForPlayerAsync(player)pcallArePaidRandomItemsRestrictedIsPaidItemTradingAllowedAreAdsAllowedAllowedExternalLinkReferencesIsSubjectToChinaPoliciesIsContentSharingAllowedAllowedExternalLinkReferencesRelated skills
相关 skill
roblox-securityroblox-uiroblox-monetizationroblox-data-storesroblox-securityroblox-uiroblox-monetizationroblox-data-stores