I’m currently trying to figure out how to implement a custom username system. However, I’m struggling to figure out how it would work. How do I prevent users from claiming already existing usernames (in-game) or in other words duplicate usernames.
Basically, I’m wondering how I would create a real-time database using Roblox’s internal datastore services.
I’m not requesting for code, just a concept or overview
you can always save the datastore as a table and insert names and save it to the datastore. EX:
local dss = game:GetService("DataStoreService")
local ds = dss:GetDataStore("Names")
ds:SetAsync("Names", table.insert(ds:GetAsync("Names") or {}, "Joe"))--random name
Yes, as datastores are on the server and will work for every server. The only problem would be people trying to change names too much, so I would recommend a debounce to make sure they don’t spam (if it’s not a one time thing).
You could make a data table in a data store that acts like a leaderboard updating to all servers and when a name is claimed it will be added but if not it would be rejected due to already being in the table.
local players = game:GetService("Players")
local dataStores = game:GetService("DataStoreService")
local dataStore = dataStores:GetDataStore("DataStore")
local nameDataStore = dataStores:GetDataStore("Usernames")
local xProtectedCall = xpcall
local commands = {";name", ":name", "/name"}
local function changeName(player, newName)
local oldName = player.leaderstats.Username.Value
if oldName == newName then
return
end
local success1, result1 = xProtectedCall(function()
return nameDataStore:GetAsync(game.GameId)
end, function(errors)
return errors
end)
if success1 then
if result1 then
print(result1)
if not result1[newName] then
result1[newName] = true
result1[oldName] = nil
local success2, result2 = xProtectedCall(function()
nameDataStore:SetAsync(game.GameId, result1)
end, function(errors)
return errors
end)
if success2 then
if result2 then
print(result2)
end
else
warn(result2)
end
local success3, result3 = xProtectedCall(function()
return dataStore:SetAsync("Usernames_"..player.UserId, newName) --Store the username change.
end, function(errors)
return errors
end)
if success3 then
if result3 then
print(result3)
end
else
warn(result3)
end
player.leaderstats.Username.Value = newName --Change the player's displayed username.
end
end
else
warn(result1)
end
end
local function loadData(player)
local success, result = xProtectedCall(function()
return dataStore:GetAsync("Usernames_"..player.UserId)
end, function(errors)
return errors
end)
if success then
if result then
print(result)
player.leaderstats.Username.Value = result
end
else
warn(result)
end
end
local function saveData(player)
local success, result = xProtectedCall(function()
dataStore:SetAsync("Usernames_"..player.UserId, player.leaderstats.Username.Value)
end, function(errors)
return errors
end)
end
local function onPlayerAdded(player)
local function onPlayerChatted(message)
for _, command in ipairs(commands) do
if message:lower():match("^"..command) then
local splitName = message:split(" ")[2]
if splitName then
if splitName:match("^%w+$") then --Alphanumeric characters only.
local nameLength = splitName:len()
if nameLength >= 1 and nameLength <= 20 then --One to twenty characters allowed.
changeName(player, splitName)
end
end
end
end
end
end
player.Chatted:Connect(onPlayerChatted)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local username = Instance.new("StringValue")
username.Name = "Username"
username.Value = ""
username.Parent = leaderstats
loadData(player)
end
local function onPlayerRemoving(player)
saveData(player) --Check if the player has selected a username/their data previously loaded before saving.
end
local function onServerShutdown(player)
for _, player in ipairs(players:GetPlayers()) do
if player.leaderstats.Username.Value ~= "" then --Check if the player has selected a username/their data previously loaded before saving.
saveData(player)
end
end
end
players.PlayerAdded:Connect(onPlayerAdded)
players.PlayerRemoving:Connect(onPlayerRemoving)
game:BindToClose(onServerShutdown)
Here’s a full system I just created which works. It currently uses the built-in leaderstats system to display custom names but that can be changed if necessary. The way it operates is when a player types one of the following commands; “;name”, “:name”, “/name” followed by a string the string is checked for availability, if it is available then the player’s custom name becomes that string and any previous custom name they may have had is made available again. If you need any further assistance do not hesitate to reach out.
You can start by making a simple Server Script that will change the players usernames when they request to.
After that, you can just save it into a Datastore and make it so when someone changes their username, the game checks the Datastore and if there is already someone with that username, just don’t allow it.
Make sure to use the Roblox filtering service because if you don’t people will be able to name themselves inaproppiate stuff!
Thanks to @vitu0089 for pointing this out.
Just a quick warning, if you allow players to create the usernames, you have to send them through the Roblox filtering service at some point in the process. If you don’t, you could be given a warning or worse, in case someone decided to name themselves the N-word or something.
Hey I appreciate the response! yes I do need further assistance. You said that it works? Testing it myself, It doesn’t seem to be working. I have Studio API and HTTPS enabled; even tested it in a game. Do you have a game that displays it in action?