Generate a shorter access code from reserver server?

MY QUESTION:
How do I make the roblox reserved server code shorter?

POST I’VE TRIED USING:

My current server creation script:

local DataStoreService = game:GetService("DataStoreService")
local RS = game:GetService("ReplicatedStorage")
local TS = game:GetService("TeleportService")

local ServerAccessCodes = DataStoreService:GetDataStore("ReservedServerAccessCodes")
local accessCode, serverId = TS:ReserveServer(9222349596)

game.ReplicatedStorage.ServerCreation.OnServerEvent:Connect(function(Player, playersMoving)
	if type(accessCode) == "string" then
		print("ACCESS-CODE: "..accessCode)
		--Player.PlayerGui.menu.Create.Visible = true
		Player.PlayerGui.menu.Create.RoomCodeBox.Text = accessCode
		ServerAccessCodes:SetAsync(serverId, accessCode)
		TS.TeleportInitFailed:Connect(function()
			Player.PlayerGui.menu.ServerLoading.TextLabel.Text = "Server load failed - Returning in a few seconds"
			wait(5)
			Player.PlayerGui.menu.ServerLoading.Visible = false
			Player.PlayerGui.menu.ServerLoading.TextLabel.Text = "Server Loading \n Please wait"
			return
		end)
		return
	end
	return
end)

Any help is very much apricated since this is my first ever time using ROBLOX teleport services
If more info is needed let me know

The default AccessCodes are just way to long

1 Like

You need to make your own.

This will turn 4 digit numbers into access codes.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TeleportService = game:GetService("TeleportService")

local codeMap = {}
local random = Random.new()

function reserveServer()
    local accessCode, serverId = TeleportService:ReserveServer(9222349596)
    local userAccessCode = random:NextInteger(1000, 9999)
    codeMap[userAccessCode] = accessCode
end

function teleportPlayer()
    local code = codeMap[userAccessCode]
    -- do stuff with the access code
end

Added lines

+ function reserveServer()
      local accessCode, serverId = TeleportService:ReserveServer(9222349596)
      local userAccessCode = random:NextInteger(1000, 9999)
+     codeMap[userAccessCode] = accessCode
+ end
2 Likes

EDIT: I didn’t see you edited the post a bit

Hey am I doing this right so far because as of right now it’s coming up as place is restricted
Here’s how I have it setup right now

local DSS = game:GetService("DataStoreService")
local RS = game:GetService("ReplicatedStorage")
local TS = game:GetService("TeleportService")

local DS = DSS:GetDataStore("ServerCodes")

local codeMap = {}
local random = Random.new()
local accessCode, serverId = TS:ReserveServer(9222349596)
local userAccessCode = random:NextInteger(100000, 999999)

game.ReplicatedStorage.ServerCreation.OnServerEvent:Connect(function(Player, playersMoving)
	local code = codeMap[userAccessCode]
	print(userAccessCode)
	Player.PlayerGui.menu.Create.RoomCodeBox.Text = userAccessCode
	DS:SetAsync(serverId, userAccessCode)
end)

game.ReplicatedStorage.ServerCreatedJoin.OnServerEvent:Connect(function(Player)
	TS:TeleportToPrivateServer(9222349596, userAccessCode, {Player})
end)

This is creating a code just not letting me access the server


You don’t use the userAccessCode to join the server, you use the userAccessCode to get the real access code via codeMap.

You can also use MemoryStoreService, because it’s faster than data stores:

-- Use the service's name as the variable name!
local MemoryStoreService = game:GetService("MemoryStoreService")
local TeleportService = game:GetService("TeleportService")

local codeMap = MemoryStoreService:GetSortedMap("codeMap")
local random = Random.new()

function createServer(player: Player)
    -- Remember to rate limit
    local accessCode, serverId = TeleportService:ReserveServer(9222349596)
    local userAccessCode = random:NextInteger(100000, 999999)
   
    -- 600 seconds is 10 minutes, increase as desired
    codeMap:SetAsync(userAccessCode, accessCode, 600)
end

function joinServer(player: Player, userAccessCode: number)
    -- Remember to rate limit and check types
    local accessCode = codeMap:GetAsync(userAccessCode)

    if accessCode then
        TeleportService:TeleportToPrivateServer(9222349596, accessCode, {player})
    end
end

However, if you don’t need cross-server compatibility you can omit the usage of MemoryStoreService and just use a table:

- local MemoryStoreService = game:GetService("MemoryStoreService")
- local codeMap = MemoryStoreService:GetSortedMap("codeMap")
+ local codeMap = {}
- -- 600 seconds is 10 minutes, increase as desired
- codeMap:SetAsync(userAccessCode, accessCode, 600)
+ -- Remember to delete the key when you're done (by setting it to nil)
+ codeMap[userAccessCode] = accessCode
- local accessCode = codeMap:GetAsync(userAccessCode)
+ local accessCode = codeMap[userAccessCode]
2 Likes

Thank you so much after a bit of working with it I finally got it to work

This will work to an extent. The generation of access codes has a rather large issue though. You are randomly generating 4 digit access codes. That leaves room for the same access code to get generated which will override another and make a server inaccessible because it will always teleport you to the newest one instead.

At first glance the chances of that happening seem slim. They are less slim than you might think though. Assuming 10000 possibilities for server codes (your code actually only has 9000) if you have generated 50 access codes there is already an 11.5% chance that you have overridden at least 1. And after generating 119 there is a 50% chance that you have broken at least one server access code. That probably seems unrealistic, but it’s true. The math is the same as the “Birthday Paradox” if you want to look into it. I have also added a snippet of code that will show the same thing (through testing it a million times).

Code for practical example

Here was my output:
image

Here was my code

local passed = 0
local tests = 1000000

local lastyield = os.clock()
for total = 0, tests do
	if os.clock() - lastyield > 1 then
		task.wait()
		print(tostring(passed) .. "/" .. tostring(total) .. "tests", tostring(passed/total*100) .. "%")
		lastyield = os.clock()
	end
	
	local tab = {}
	for i=0, 50 do
		local num = math.random(0, 10000)
		if tab[num] then
			passed+=1
			break
		end
		tab[num] = true
	end
end

print("~~~~~~~~~~~~~~~~~~FINISHED~~~~~~~~~~~~~~~~~~")
print(tostring(passed) .. "/" .. tostring(tests))
print(tostring(passed/tests*100) .. "% of trials resulted in an access code override")
Formula I used for calculating the probability

Look up “The Birthday Paradox” for an explanation of why this works. I’m not really going to delve into that in this post.

‘p’ is how many unique access codes there are, and ‘n’ is how many codes you’ve generated.
image

Now for a solution

The easiest solution would be to check if the code is in use and pick another random code. I would limit this to only getting a few attempts before it either makes all the new user codes longer or just resorts to showing the default access code (for scalability). You can also increase the amount of total access codes by allowing characters in there as well.

There are solutions that would actually garuntee unique codes, but that is more complicated and probably not worth it. Just resorting the the default access code when it overlaps with others too many times is far easier since that one is already going to be unique.

Two other potential solutions would include having an external server dedicated to this task. Or making it so that if it’s generated at a certain time or by a certain server it has a specified prefix and only has to worry about servers it created.

2 Likes