I’m going to start off by saying this, to pre-existing developers with http services and other matchmaking services. You should not use this unless you are paying for the http server.
Now that I’ve given that warning I will go into the tutorial.
All of the scripts that you are seeing are first-hand made. I used no tutorials and although I posted to scripting support, no one replied which told me I should probably make a tutorial to the community on how this works. I am open to advice.
Let’s start out with the functions. Just like any service start off by receiving it.
game:GetService("MemoryStoreService")
The MemoryStoreService contains SortedMaps too if you want to view these click this link to the entire overview of the service
Memory Store
Functions:
GetQueue
ReadAsync
AddAsync
RemoveAsync
Keep in mind that those are only the queue functions, they are the only ones used with queues.
GetQueue
1st variable: The key, which works exactly like a dataStore. It is even global.
2nd variable: The invisibility timeout. If a value is read by ReadAsync it cannot be read again for x, time. This one I’m going to model for you because it is very important to understand, for this demonstration it will be zero but keep it mind it can be useful.
--Incorrect usage below
local MSS = game:GetService("MemoryStoreService")
local Queue = MSS:GetQueue("Matchmaking-"..game.PlaceId.."-"..game.PrivateServerId, 30) -- defaults to 30 so I didn't have to add it but wanted to show you where it goes
--quick addition DO NOT WRITE THIS SCRIPT
function Main(plr)
Queue:AddAsync(plr.Name, 30, 1) -- second value is very important, will explain
wait(1)
print("Testing")
local read1 = Queue:ReadAsync(100, false, 2) -- 3rd value is timeout just incase it doesn't get, in this case, 100 values.
print("Read 1: "..read1)
wait(2)
local read2 = Queue:ReadAsync(100, false, 2)
print("Read 2: "..read2)
end
game.Players.PlayerAdded:Connect(function(plr) -- calls the main function
Main(plr)
end
--Output
--[[ Multi-line comment for those that don't know
Read 1: {
[1] = "(what the name is)"
}
Read 2: nil
]]--
As you can see because we did not wait 30 seconds the queue could not read the name because it was invisible
If we waited 30 seconds the value wouldn’t have been there because of AddAsync automatic removal timeout unless we set it over 31.
Here is the correct script for this scenario
--Correct usage below
local MSS = game:GetService("MemoryStoreService")
local Queue = MSS:GetQueue("Matchmaking-"..game.PlaceId.."-"..game.PrivateServerId, 0)
--quick addition DO NOT WRITE THIS SCRIPT
function Main(plr)
Queue:AddAsync(plr.Name, 30, 1) -- second value is very important, will explain
wait(1)
print("Testing")
local read1 = Queue:ReadAsync(100, false, 2) -- 3rd value is timeout just incase it doesn't get, in this case, 100 values.
print("Read 1: "..read1)
wait(2)
local read2 = Queue:ReadAsync(100, false, 2)
print("Read 2: "..read2)
end
game.Players.PlayerAdded:Connect(function(plr) -- calls the main function
Main(plr)
end
--Output
--[[
Read 1: {
[1] = "(what the name is)"
}
Read 2: {
[1] = "(what the name is)"
}
Since the timeout for GetQueue is 0 we can read it instantly. Keep it 0 for the demonstration.
AddAsync
1st variable: Value wanted to be added
2nd variable: Automatic Removal time, keep this below a minute or 60.
3rd variable: Priority, you can change this to put parties in the front of the queue by saying 1, and solos in the back by a ridiculously high number like 1000.
The automatic removal is the most important thing. This service is pretty bad because you have to process a value for it to be able to be removed. Unfortunately, processing values are a little buggy and it removes values half the time. Making the values low ensures that you will not read the value twice because it will be automatically deleted in x time Or you can make another queue with an invisibility timeout separate from the first queue for your main matchmaking function.
RemoveAsync
1st variable: Value to remove
Put in the value DIRECTLY returned from ReadAsync.
ReadAsync
Pay attention here
1st variable: How many values for it to read, max = 100
2nd variable: If you don’t get the number of values you want, return nil if set to true. If set to nil will return all the values it has received in the 3rd variable time frame.
3rd variable: Time to read queue until it gets 1st variable values. Set to 0.01 usually.
ALL OF THESE FUNCTIONS YIELD: you do not need to do wait()
--All functions in coding format
local MSS = game.GetService:("MemoryStoreService")
local queue = MSS:GetQueue(whateveryouwanttocallit..SecurityPurposesAddSpecialCharacters..game.PlaceId, 0)
queue:AddAsync(value, timeout, priority)
local Read = queue:ReadAsync(valuesWanted, nilIfNotValuesWanted, waitTimeForValuesWanted)
print(Read)
--[[
Output:
{
[1] = (value)
}
]]--
queue:RemoveAsync(valueDirectlyReturnedFromReadAsync)
Implementing Matchmaking Via MemoryStoreQueue
Let’s start off by receiving the services we might want. This will not be a tutorial on how to get players from touching parts or GUI. This is purely how to make a matchmaking service.
local Players = game:GetService("Players")
local MSS = game:GetService("MemoryStoreService")
local TS: game:GetService("TeleportService")
local RS = game:GetService("ReplicatedStorage")
Next, let’s set up the framework for ourselves.
local Players = game:GetService("Players")
local MSS = game:GetService("MemoryStoreService")
local TS: game:GetService("TeleportService")
local RS = game:GetService("ReplicatedStorage")
local targetPlaceID = WHATEVERYOURSIS -- LOOK HERE: this is if you want to teleport all of this stuff
local teleportOptions = Instance.new("TeleportOptions")
teleportOptions.ShouldReserveServer = true
local TeleportModule = require(RS:WaitForChild("TeleportModule"))
--^ Variables in Game
local currentServer = game.PrivateServerId
local currentAmount = 0 --just to calculate players received
local plrTable = {} -- needed to hold read
--^ tables and counters
--change these
local playersNeeded = 2
local playersWanted = 4
--change these
function Main()
end
function Add()
end
function Remove()
--unfortunately, I will not be demonstrating this today.
--They will only be removed once they are teleported or the function is complete
end
function RemoveAll()
end
--calls
Players.PlayerAdded:Connect(function(plr)
Add(plr)
end
game.BindToClose(function()
RemoveAll()
end
Great! Our framework is complete. Let’s go ahead and add the Add function
local Players = game:GetService("Players")
local MSS = game:GetService("MemoryStoreService")
local TS: game:GetService("TeleportService")
local RS = game:GetService("ReplicatedStorage")
local targetPlaceID = WHATEVERYOURSIS -- LOOK HERE: this is if you want to teleport all of this stuff
local teleportOptions = Instance.new("TeleportOptions")
teleportOptions.ShouldReserveServer = true
local TeleportModule = require(RS:WaitForChild("TeleportModule"))
--^ Variables in Game
local currentServer = game.PrivateServerId
local currentAmount = 0 --just to calculate players received
local plrTable = {} -- needed to hold read
--^ tables and counters
--change these
local playersNeeded = 2
local playersWanted = 4
--change these
function Main()
end
function Add()
local success, err = pcall(function()
MMNS:AddAsync(plr.Name, 30, 1) -- change timeout to whatever you want as long as it is not above 3 minutes.
end)
if success then
print("Player Added to Queue: "..plr.Name)
Main()
else
print(err)
end
end
function Remove()
--unfortunately, I will not be demonstrating this today.
--They will only be removed once they are teleported or the function is complete
end
function RemoveAll()
end
--calls--
Players.PlayerAdded:Connect(function(plr)
Add(plr)
end
game.BindToClose(function()
RemoveAll()
end
Next the main function.
local Players = game:GetService("Players")
local MSS = game:GetService("MemoryStoreService")
local TS: game:GetService("TeleportService")
local RS = game:GetService("ReplicatedStorage")
local targetPlaceID = WHATEVERYOURSIS -- LOOK HERE: this is if you want to teleport all of this stuff
local teleportOptions = Instance.new("TeleportOptions")
teleportOptions.ShouldReserveServer = true
local TeleportModule = require(RS:WaitForChild("TeleportModule"))
--^ Variables in Game
local currentServer = game.PrivateServerId
local currentAmount = 0 --just to calculate players received
local plrTable = {} -- needed to hold read
--^ tables and counters
--change these
local playersNeeded = 2
local playersWanted = 4
--change these
function Main()
local success, err = pcall(function()
plrTable = MMNS:ReadAsync(100, false, 0.01)
end)
print(success, err)
if plrTable ~= nil then
print("check")
for i, player in ipairs(plrTable) do
currentAmount += 1
print("processed")
end
if currentAmount >= playersNeeded then
currentAmount = 0
local playersSelected = {}
local forRemoval = {} -- very important
print("Game Found")
if game.CreatorId ~= "0" then
print("check")
local playersToTP = {} -- still need
for i, plyr in ipairs(MMNS:ReadAsync(playersWanted, false, 2)) do
print(plyr.." Teleporting")
local playeR = Players:FindFirstChild(plyr)
table.insert(playersToTP, 1, playeR)
forRemoval[i] = plyr
end
print(forRemoval)
print(MMNS:ReadAsync(100, false, 0.01))
MMNS:RemoveAsync(forRemoval)
local teleportResult = TeleportModule.teleportWithRetry(targetPlaceID, playersToTP, teleportOptions)
--can be ingame via CFrames and MoveTo
else
print("In studio")
end
else
currentAmount = 0
print("not enough")
end
else
print("error table = nil")
end
end
function Add()
local success, err = pcall(function()
MMNS:AddAsync(plr.Name, 30, 1) -- change timeout to whatever you want as long as it is not above 3 minutes.
end)
if success then
print("Player Added to Queue: "..plr.Name)
Main()
else
print(err)
end
end
function Remove()
--unfortunately, I will not be demonstrating this today.
--They will only be removed once they are teleported or the function is complete
end
function RemoveAll()
end
--calls--
Players.PlayerAdded:Connect(function(plr)
Add(plr)
end
game.BindToClose(function()
RemoveAll()
end
Finally, add remove all so the server can cleanup on shutdown
local Players = game:GetService("Players")
local MSS = game:GetService("MemoryStoreService")
local TS: game:GetService("TeleportService")
local targetPlaceID = WHATEVERYOURSIS -- LOOK HERE: this is if you want to teleport all of this stuff
local teleportOptions = Instance.new("TeleportOptions")
teleportOptions.ShouldReserveServer = true
local TeleportModule = require(RS:WaitForChild("TeleportModule"))
--^ Variables in Game
local currentServer = game.PrivateServerId
local currentAmount = 0 --just to calculate players received
local plrTable = {} -- needed to hold read
--^ tables and counters
--change these
local playersNeeded = 2
local playersWanted = 4
--change these
function Main()
local success, err = pcall(function()
plrTable = MMNS:ReadAsync(100, false, 0.01)
end)
print(success, err)
if plrTable ~= nil then
print("check")
for i, player in ipairs(plrTable) do
currentAmount += 1
print("processed")
end
if currentAmount >= playersNeeded then
currentAmount = 0
local playersSelected = {}
local forRemoval = {} -- very important
print("Game Found")
if game.CreatorId ~= "0" then
print("check")
local playersToTP = {} -- still need
for i, plyr in ipairs(MMNS:ReadAsync(playersWanted, false, 2)) do
print(plyr.." Teleporting")
local playeR = Players:FindFirstChild(plyr)
table.insert(playersToTP, 1, playeR)
forRemoval[i] = plyr
end
print(forRemoval)
print(MMNS:ReadAsync(100, false, 0.01))
MMNS:RemoveAsync(forRemoval)
local teleportResult = TeleportModule.teleportWithRetry(targetPlaceID, playersToTP, teleportOptions)
--can be ingame via CFrames and MoveTo
else
print("In studio")
end
else
currentAmount = 0
print("not enough")
end
else
print("error table = nil")
end
end
function Add()
local success, err = pcall(function()
MMNS:AddAsync(plr.Name, 30, 1) -- change timeout to whatever you want as long as it is not above 3 minutes.
end)
if success then
print("Player Added to Queue: "..plr.Name)
Main()
else
print(err)
end
end
function Remove()
--unfortunately, I will not be demonstrating this today.
--They will only be removed once they are teleported or the function is complete
end
function RemoveAll()
local success, err = pcall(function()
local read = MMNS:ReadAsync(100, false, 5)
MMNS:RemoveAsync(read)
end)
print(success, err)
print("done")
end
--calls--
Players.PlayerAdded:Connect(function(plr)
Add(plr)
end
game.BindToClose(function()
RemoveAll()
end
Closing Notes
This used Roblox’s pre-existing Teleport Module, you can make your own I will link Roblox’s right here
[Teleporting Between Places | Roblox Creator Documentation](Teleporting Between Places)
Good luck!
Any advice? Feel free to comment.
Any edits? Feel free to let me know what to edit.