Custom Username System?

Hello,

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

3 Likes

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
3 Likes

And this would replicate for every user correct?

2 Likes

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).

4 Likes

Right, thanks! I’ll test it out!

2 Likes

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.

2 Likes
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.

2 Likes

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.

:warning: 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.

1 Like

How does this prevent duplicate usernames?
Also, he said that he is not requesting any code.

1 Like

That’s fine, he doesn’t have to take it, I wanted to write it anyway.

1 Like

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.

2 Likes

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?

1 Like