Most efficient way to list servers?

Hey!, Recently, I’ve been trying to make a functional server list but i havent found a good and stable way to do it as HTTP requests to roblox are disabled.

Example of what i want to acomplish:

Your best bet will probably be MemoryStoreService

Each server advertises itself every few seconds; clients pull the list through one RemoteFunction and TeleportService moves them over

Lmk if you need an example

I didnt know that service existed! An example would be perfect tho. :smiley:

1 Like

Setup

  1. In ReplicatedStorage add
    • RemoteFunction GetServers
    • RemoteEvent JoinServer
  2. Place a server script (script below) in ServerScriptService.
  3. Place a local script (script below) in StarterPlayerScripts.
  4. Build a simple GUI:
    • ScreenGui > Frame
      • Refresh (TextButton)
      • List (Frame with a UIListLayout)
      • Template (Frame with ServerName (TextLabel), PlayerCount (TextLabel), Join (TextButton); set Visible = false)
  5. The list should populate and clicking Join teleports you in

ServerScript

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

local MAP_NAME = "ServerList"
local TTL_SECONDS = 90
local REFRESH_SECONDS = 10
local MAX_RETURN = 200

local map = MemoryStoreService:GetSortedMap(MAP_NAME)
local jobId = game.JobId
local placeId = game.PlaceId

local function publish()
    map:SetAsync(jobId, #game.Players:GetPlayers(), TTL_SECONDS)
    task.delay(REFRESH_SECONDS, publish)
end

publish()

ReplicatedStorage.GetServers.OnServerInvoke = function(player, limit)
    limit = math.clamp(typeof(limit) == "number" and limit or 50, 1, MAX_RETURN)

    local ok, data = pcall(function()
        return map:GetRangeAsync(Enum.SortDirection.Descending, limit)
    end)

    return ok and data or {}
end

ReplicatedStorage.JoinServer.OnServerEvent:Connect(function(player, targetJobId)
    if typeof(targetJobId) ~= "string" then return end

    pcall(function()
        TeleportService:TeleportToPlaceInstance(placeId, targetJobId, player)
    end)
end)

LocalScript

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local frame = script.Parent
local listGui = frame.List
local template = frame.Template

local debounce = false
local REFRESH_COOLDOWN = 5

local function makeCell(jobId, players)
    local cell = template:Clone()
    cell.ServerName.Text = jobId:sub(1, 8) .. "…"
    cell.PlayerCount.Text = players .. "/" .. game.MaxPlayers

    local conn
    conn = cell.Join.MouseButton1Click:Connect(function()
        ReplicatedStorage.JoinServer:FireServer(jobId)
    end)

    cell.Destroying:Connect(function()
        if conn then conn:Disconnect() end
    end)

    cell.Parent = listGui
end

local function refresh()
    if debounce then return end
    debounce = true

    local ok, entries = pcall(function()
        return ReplicatedStorage.GetServers:InvokeServer(100)
    end)

    if ok and entries then
        for _, child in ipairs(listGui:GetChildren()) do
            if child:IsA("Frame") then child:Destroy() end
        end

        for _, entry in ipairs(entries) do
            makeCell(entry.key, entry.value)
        end
    end

    task.delay(REFRESH_COOLDOWN, function() debounce = false end)
end

frame.Refresh.MouseButton1Click:Connect(refresh)
refresh()

I haven’t fully tested this out but it should be a decent base setup for you to get familiar with the service, I hope this helped out

Thank you so much! I’ve been searching for days and here is the solution.

1 Like