How would I go about making a "server ID" system

I’m trying to make a server code system that is 100% unique, but is not a massive 12 character string of letters and numbers (like game.JobId or httpService:GenerateGuid()). I’m looking for a short 5-6 character code (example: 4HV29) that players can enter to join someone’s server. I’m planning for this to work very similarly to how The Final Stand 2’s private server system works. Basically, you create a server as an owner and when it teleports you, it gives you a code. You then send this code to whoever you want to join and then they input that code and it teleports them.

The issue: I don’t know how to go about generating a server code and linking it to the server so that players can teleport to the server.

First Idea: Compress the Job Id into a 5-6 character string. Issue: I don’t really know where to start with doing that. I’ve looked up string compression algorithms but none of them really work the way I need them to and my brain is not smart enough to do this yet. If anyone has a string compressor algorithm I’d be glad to take a look at it. If I were to put this idea in my game, this is roughly how it would work:

  1. To get the game’s code (to show to the lobby creator to send to his friends), compress the Job Id.
  2. When a player inputs the code, run the decompressor algorithm on the server and see if there is a valid server with that job id.
  3. If there is, teleport the player. If not, show a message that says “Code is invalid” or something like that.

Second Idea: Generate a code, see if there is a lobby with that code using MemoryStoreService, and then link that code to the game’s Job Id using MemoryStoreService. Issue: I’m not sure how reliable this method is and it might lead to false invalid codes and duplicate codes. This is how this idea would work:

  1. Generate Code (example: 4HV29)
  2. Check if there is a server with this code already using MemoryStoreService
  3. Teleport the player to a private server and add the server to MemoryStoreService
  4. When a player enters in a code, check MemoryStoreService for a key and if there is one, teleport them. If not, I’ll add a message that says “Unable to find game” or something like that.
  5. In the server that was created, use game:BindToClose() to automatically remove the key from MemoryStoreService and for extra safety, also remove the key from MemoryStoreService if the Job Id is invalid when teleporting players

Those are two of the ideas I’ve created just at the top of my head but I’m not really sure how reliable the second method is. I’ll be glad to hear if you guys have any other ideas, feedback on my current ideas, or any help in how I can execute the first idea. If I can’t figure out the first idea or if the second one is more reliable I’ll just go with the second one. Thanks for reading!

tl;dr: Trying to make a unique 5-6 character code with letters and numbers so that I can teleport players to a private server.

1 Like

You can try generating custom codes and making them as an alias to the Job Id.

1 Like

I would recommend the second idea. It will probably be easier to pull off + you won’t need to worry about unwanted duplicates.

1 Like

I got it working. If you want the code, here it is:

local teleportService = game:GetService("TeleportService")
local dataStoreService = game:GetService("DataStoreService")
local memoryStoreService = game:GetService("MemoryStoreService")

local replicatedStorage = game:GetService("ReplicatedStorage")

local modules = replicatedStorage:WaitForChild("Modules")
local remotes = replicatedStorage:WaitForChild("Remotes")
local bindables = replicatedStorage:WaitForChild("Bindables")

local generateCode = require(modules:WaitForChild("CodeGenerator"))

local privateServerCodes = memoryStoreService:GetSortedMap("PrivateServers")

local function getAccessCodeFromServerCode(serverCode:string)
	local success, accessCode = pcall(function()
		return privateServerCodes:GetAsync(serverCode)
	end)
	if success and accessCode then
		return accessCode
	else
		if not success then
			warn(accessCode)
		end
	end
	return nil
end

local function generateRandomCode(characters:number?, includeLetters:boolean?)
	local code:string = ""

	repeat
		code = generateCode(characters, includeLetters)
		if getAccessCodeFromServerCode(code) then
			code = ""
			task.wait(1)
		end
	until code ~= ""

	return code
end

local function teleportPlayer(player:Player, accessCode:string, serverCode:string)
	local teleportOptions = Instance.new("TeleportOptions")

	teleportOptions.ShouldReserveServer = false
	teleportOptions.ReservedServerAccessCode = accessCode

	teleportOptions:SetTeleportData({
		ServerCode = serverCode
	})

	teleportService:TeleportAsync(10638033070, {player}, teleportOptions)
end

local function createPrivateServer(player:Player)
	local gotAccessCode, accessCode = pcall(function()
		return teleportService:ReserveServer(10638033070)
	end)
	local serverCode = generateRandomCode()

	if gotAccessCode and accessCode then
		local setAccessCode, respose = pcall(function()
			return privateServerCodes:SetAsync(serverCode:upper(), accessCode, 86400)
		end)

		if setAccessCode then
			teleportPlayer(player, accessCode, serverCode)
		else
			remotes.CreatePrivateServer:FireClient(player, "Unable to create server! Please try again later. (Roblox servers might be down)")
			warn(respose)
		end
	else
		remotes.CreatePrivateServer:FireClient(player, "Unable to create server! Please try again later. (Roblox servers might be down)")
		warn(accessCode)
	end
end

local function joinPrivateServer(player:Player, serverCode:string)
	local accessCode:string? = getAccessCodeFromServerCode(serverCode)

	if accessCode then
		teleportPlayer(player, accessCode, serverCode)
	else
		remotes.JoinPrivateServer:FireClient(player, "Unable to find server (Check your spelling!)")
	end
end

remotes.CreatePrivateServer.OnServerEvent:Connect(createPrivateServer)
remotes.JoinPrivateServer.OnServerEvent:Connect(joinPrivateServer)

This is the code generation function:

local alphabet = string.split("ABCDEFGHIJKLMNOPQRSTUVWXYZ", "")

local function convert(i)
	if (alphabet[i]) then
		return alphabet[i]
	else
		local n = i
		local s = ""
		local r = (n - 1) % 26 + 1
		local d = math.floor(n / 26)
		if (r == 26) then d = d - 1 end -- hacky fix to the offset problem
		return convert(d)..convert(r)
	end
end

return function(characters:number?, includeLetters:boolean?)
	local code = ""

	local numberOfCharacters = math.clamp(characters or 5, 1, 6)

	for i = 1, numberOfCharacters do
		if includeLetters == false or math.random(1, 2) == 1 then
			local randomNumber = math.random(0, 9)
			if (i == 1) or (i == numberOfCharacters) then
				randomNumber = math.clamp(randomNumber, 1, 9)
			end
			code..= tostring(randomNumber)
		else
			local randomLetter = convert(math.random(1, 26))

			code..= randomLetter
		end
	end

	return code
end

Feel free to take, edit, and use the code however you want.

1 Like