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