I intend on placing a few of them next to each other for a build I’m working on. However, I’m scared that It could generate a bad word. Should I be worried?
You don’t need to worry about this because in the article u/The_DuckDeveloper provided, it is shown that Roblox already has a built-in method to do text filtering (in code).
With the help of the assistant, I changed the code to the following, and it works!
local TextService = game:GetService("TextService")
local letters = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
local function getRandomLetter()
local randomIndex = math.random(1, #letters)
return letters[randomIndex]
end
local function filterAndSetText(textLabel)
local randomLetter = getRandomLetter()
local placeholderUserId = 0
local success, filteredTextResult = pcall(function()
return TextService:FilterStringAsync(randomLetter, placeholderUserId)
end)
if success then
local filteredText = filteredTextResult:GetNonChatStringForBroadcastAsync()
textLabel.Text = filteredText
else
textLabel.Text = randomLetter
end
end
local blocksModel = script.Parent
for _, block in blocksModel:GetChildren() do
if block:IsA("Part") then
local surfaceGui = block:FindFirstChildOfClass("SurfaceGui")
if surfaceGui then
local textLabel = surfaceGui:FindFirstChildOfClass("TextLabel")
if textLabel then
filterAndSetText(textLabel)
end
end
end
end
This isn’t even a solution though. You’re only filtering one letter separately for each block, which (should) never fail. You need to filter the combination of random letters if you want to avoid bad words.
Also
You just set the text anyway even if the filtering fails. Incredible.
I believe that’s what I did. Rather than a different letter being generated in each block. I made a script that I believe generates a 3 letter word, assigning each block a letter in chronological order.
This is the script you posted in your reply claiming to have fixed the issue. Let’s look at what it does VS what it’s supposed to do.
for _, block in blocksModel:GetChildren() do
if block:IsA("Part") then
local surfaceGui = block:FindFirstChildOfClass("SurfaceGui")
if surfaceGui then
local textLabel = surfaceGui:FindFirstChildOfClass("TextLabel")
if textLabel then
filterAndSetText(textLabel)
end
end
end
end
This loops through all the blocks in the model, and runs the filterAndSetText() function for each one separately.
local function filterAndSetText(textLabel)
local randomLetter = getRandomLetter()
local placeholderUserId = 0
local success, filteredTextResult = pcall(function()
return TextService:FilterStringAsync(randomLetter, placeholderUserId)
end)
if success then
local filteredText = filteredTextResult:GetNonChatStringForBroadcastAsync()
textLabel.Text = filteredText
else
textLabel.Text = randomLetter
end
end
There are 3 blocks, so this function here is ran 3 times total, once for each block.
Heres what the first block would do.
It gets a random letter with the getRandomLetter() function. Example output: A
It then filters that letter, and sets the text of the block’s textlabel to the filtered text.
Now while the code does work fine, the issue is an error in logic. The issue is not that a single random letter generated may produce something not appropriate, which is what the script is preventing. The issue is that a combination of 3 random characters might produce something inappropriate.
If each block performs the 2 steps listed above, that would not actually solve the actual issue here. What needs to happen is something like this:
Each block gets a random letter. Example output: A, B and C
The script combines the 3 random letters into (in this example case) ABC. It then filters THAT.
If the combination was not filtered, apply the random letters onto the blocks
This is what is actually supposed to happen.
Heres my adjusted version of the code
local TextService = game:GetService("TextService")
local letters = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"}
local function getRandomLetter()
local randomIndex = math.random(1, #letters)
return letters[randomIndex]
end
--This function has been changed to filter the text we pass into it, and return the result.
local function filterText(text)
local placeholderUserId = 0
local success, filteredTextResult = pcall(function()
return TextService:FilterStringAsync(text, placeholderUserId)
end)
if success then
--Here the filtering was succesful. If we wanted to, we could check for the # symbol and then generate a new set of random letters. For this example we'll just return the result, even if it was completely replaced by ###
local filteredText = filteredTextResult:GetNonChatStringForBroadcastAsync()
return filteredText
else
--Because the filtering wasn't succesful, we can't just show the text because we can't know if it would have been accepted by the filter.
--There are some options here, but in this case we will just try again.
return filterText(text)
end
end
local blocksModel = script.Parent
local randomString = ""
--For every block, we add one random letter to our string of random letters.
for _, block in blocksModel:GetChildren() do
if block:IsA("Part") then
local surfaceGui = block:FindFirstChildOfClass("SurfaceGui")
if surfaceGui then
local textLabel = surfaceGui:FindFirstChildOfClass("TextLabel")
if textLabel then
local randomLetter = getRandomLetter()
randomString = randomString .. randomLetter
end
end
end
end
--Now lets filter our string to make sure its good to show in-game.
local filteredString = filterText(randomString)
--Now we can apply it to our blocks! Notice how we use the index (i) this time.
for i, block in blocksModel:GetChildren() do
if block:IsA("Part") then
local surfaceGui = block:FindFirstChildOfClass("SurfaceGui")
if surfaceGui then
local textLabel = surfaceGui:FindFirstChildOfClass("TextLabel")
if textLabel then
--Since were working with strings, here's how we get a specific character of the random string we made and filtered earlier.
textLabel.Text = string.sub(filteredString, i, i)
end
end
end
end
I didn’t mention it before this point really, but you shouldn’t set the text if the filtering fails, since that means the text did not get filtered at all, and could still be bad. My example code here retries the filtering if it doesn’t succeed.
Note that this is not tested, and will (probably) not work if you simply copy and paste it. This is an example, and I hope it will point you in the right direction.
Sorry for the late response and any potential mistakes in this post, It’s a long one