[v2.1.0] MatchmakingService - ON HOLD

Yes.

1 Like

Can you send data in and back? What I’m trying to say can we send saved data to another game and bring it back to the original game?

Another question that I have, is this going to be fast? Does this use or can we use the same system TDS uses for matchmaking? Which is where it would get the closest players to you.

This is awesome I could use this in future games thank you :blush:

1 Like

Is there a way to turn off multiplayer teleports if you leave or get disconnected? My game doesn’t support that feature. Also, if you do not even teleport, you get teleported solo anyway, which is a bad user experience. Would appreciate a way to turn that oof.

If you’re here for the hold explanation, it’s at the bottom of this post.

This is a matchmaking service, the most it provides is matchmaking and sending relevant data to games, if you want to send data back, you’d need to handle that yourself using any method you want. I don’t want to bloat the service with things potentially unrelated to matchmaking which would slow down the service for people that don’t want/need the functionality.

You can use it to append custom data relevant to the games/players which are being sent that you can then access on the game servers after a match is found, but it does not relay any info back after the game is over, other than potentially updating a player’s rating, which isn’t really going back to the other server at all it’s just updating it in a datastore.

I don’t know what TDS is, however there is no geolocation check in MMS, if that’s what you mean. It uses a FIFO priority-based queue (it’s essentially FIFO, but parties are handled a little differently).

I’m unsure what you mean. MMS does not handle reconnecting disconnected users to games anywhere in its code (it doesn’t even connect to PlayerAdded at all)

As for teleporting solo, MMS looks at your maps min/max values and will teleport users as soon as it reaches min, so if you don’t want users to teleport solo set min higher.

If you believe you have found a bug, please gather evidence (recordings are the easiest to follow) then submit that.

For everyone else regarding the future of this project

As of right now this project is on hold. MMS is a passion project of mine, I made it for the community. I don’t ask for or expect anything in return, I don’t even ask for, or care for any credit. I’m currently very busy with life at the moment. I’m a full time college student with finals coming up. I’m also an intern at roblox working on a game through the accelerator program as my full time job at the moment. Needless to say, I’m extremely busy and have very little free time, and the free time I do have I don’t want to turn into work time. I do other things in my life than program that I’d like to do when I have time.

I don’t plan on fully discontinuing this project anytime soon, however, just know that there will be no updates unless it’s to fix breaking bugs until I’m done with college, the internship, and probably find a new job afterwards. I’d like to settle in and get into a good rhythm again since right now, it really isn’t.

And of course, this project will always be free and open source. If you want to contribute, head over to the github, fork the project, add some changes, then PR it into the main repo and leave a reply here if I don’t see it. The beauty of open source software is that anyone can work on it.

I hope you understand where I’m coming from with this,
Steven

Not wanting to bump the topic, I did release 2.0.3 which is a small fix that doesn’t even add any lines of code:
Version 2.0.3

Changes (breaking):

  • None

Changes (non-breaking):

  • None

Fixes:

  • [Fix] Attempted a fix for an issue that would cause an error when teleporting players to existing games with no custom teleport data.
12 Likes

This is fully understandable Steven. It’s really amazing what you have done for all of us, and we really can’t thank you enough for sharing this with the community.

Furthermore, I am very grateful for you still fixing game-breaking bugs even though you‘re (understandably) very busy!

Thanks for everything, and good luck on your other projects too. I‘m sure we‘ll all keep in touch, and the project isn‘t disbanded - rather mothballed until you have more time :slight_smile:

Great module! The only problem I’m having is that

:SetPlayerRange(…)

isn’t working for me. I set the minimum amount to 2 players but when I queue up with 1 player I get teleported anyway. I think I followed the steps correctly,

hub server:

local MatchmakingService = require(script:WaitForChild("MatchMaking")).GetSingleton()

local MPremote = game:GetService("ReplicatedStorage"):WaitForChild("startMultiplayer")


-- Game modes ..................................................

gameModes = {
	["Distance"]  = {},
	["Elimination"]  = {}, -- disabled
	["Dodge"]  = {} -- disabled
}

MatchmakingService:SetPlayerRange("Distance", NumberRange.new(2, 4))
MatchmakingService:AddGamePlace("Distance", 7523477758)

--..............................................................


MPremote.OnServerEvent:connect(function(player, gameMode)
	if gameModes[gameMode] then
		print("exists")
		MatchmakingService:QueuePlayer(player, "unranked", gameMode)
	else
		player:Kick("Multiplayer game mode does not exist")
	end
end)

instance server:

local MatchmakingService = require(script:WaitForChild("MatchMaking")).GetSingleton()

-- Game modes ..................................................

gameModes = {
	["Distance"]  = {},
	["Elimination"]  = {}, -- disabled
	["Dodge"]  = {} -- disabled
}


MatchmakingService:SetPlayerRange("Distance", NumberRange.new(2, 4))

--..............................................................


MatchmakingService:SetIsGameServer(true)
local gameData
game.Players.PlayerAdded:Connect(function(player)
	if not gameData then
		gameData = MatchmakingService:GetGameData()
	end
	if #game.Players:GetPlayers() >= 2 then
		--Start()
		MatchmakingService:StartGame(gameData.gameCode, false) -- joinable = false

	end
end)

This shouldn’t be possible considering, even if the value was incorrect, the default is minimum 6 players. I’m not actually sure what causes this issue for you, however the first thing that comes to mind that may fix this for you is:

  1. Join the game
  2. Press F9, and open the developer console
  3. Enter the command: MatchmakingService:Clear() (replace MatchmakingService with a reference to the actual matchmaking service singleton, i.e. it should have the same location as require(script:WaitForChild("MatchMaking")).GetSingleton() from your script) to purge all ephemeral memory from your game (this may interrupt any currently running games and cause them to break when they close, so it’s recommended to restart your game before doing this)

If there’s an issue with games not being cleaned up for some reason it could be sending players to a game it thinks is still running and has players.

Also, I see that you’re using a version that’s imported manually so could you tell me what version you’re using?

1 Like

Thanks for the fast reply! I got the module from the Roblox library today. I found out why this problem happens. Because of my unfinished UI, I can keep firing the remote which contains QueuePlayer(…). I’m queuing up with myself every time and verified this in debug mode (the minimum was set to 4 players in the image):

I’ll fix this by keeping a list of all players currently looking for a server to only allow QueuePlayer once per player (in case exploiters abuse the remote)

Ah alright. Glad to hear you figured it out. I would do checks myself to prevent double queuing, however that would mean a lot of extra resources being used to search through memory, a local solution would be best. Just remember to remove the player from the list after they are removed from the game or you could very quickly create a memory leak.

2 Likes

Hello, sorry to bother you. I have an issue with my rating going below 0? I am up to date on the version. There are no errors in output or anything like that.

Hub Server Script:

-- Obtain the service
local smodule = require(game.ServerStorage.SideModule)
local MatchmakingService = require(7567983240).GetSingleton()
-- Set the game place
gameData = MatchmakingService:GetGameData()
MatchmakingService:AddGamePlace("Map 1", 9432073031)
MatchmakingService:SetPlayerRange("Map 1", NumberRange.new(2, 2))
local delayy = 10
MatchmakingService:SetFoundGameDelay(delayy)


-- Queue players (you can call QueuePlayer from anywhere)
game.ReplicatedStorage.rtt.OnServerEvent:Connect(function(player)
	local queueonce = player:FindFirstChild("queueonce")
	local rawr = player.PlayerGui.PlayScreen.MidBar.TextButton.Frame.Status
	local frames = player.PlayerGui.PlayScreen.MidBar.TextButton.Frame
	local status = player:FindFirstChild("status")
	local tab = {"f", "c"}
	local currentlysearching = player:FindFirstChild("cs")
	if queueonce.Value == false then
		MatchmakingService:QueuePlayer(player, "RankedTest2", "Map 1")
		queueonce.Value = true
		status.Value = "s"
		if currentlysearching.Value == false then
			while true do
				currentlysearching.Value = true
				if status.Value == {"f", "c"} then
					currentlysearching.Value = false
					break
				end
				rawr.Text = "Searching"
				if status.Value == {"f", "c"} then
					currentlysearching.Value = false
					break
				end
				wait(0.4)
				rawr.Text = "Searching."
				if status.Value == {"f", "c"} then
					currentlysearching.Value = false
					break
				end
				wait(0.4)
				rawr.Text = "Searching.."
				if status.Value == {"f", "c"} then
					currentlysearching.Value = false
					break
				end
				wait(0.4)
				rawr.Text = "Searching..."
				if status.Value == {"f", "c"} then
					currentlysearching.Value = false
					break
				end
				wait(0.4)
				if status.Value == {"f", "c"} then
					currentlysearching.Value = false
					break
				end
			end
		end
		print("queued")
	else
		print("Already queued up")
	end
end)

game.ReplicatedStorage.cancel.OnServerEvent:Connect(function(plr)
	local queueonce = plr:FindFirstChild("queueonce")
	local status = plr:FindFirstChild("status")
	if queueonce.Value == true then
		queueonce.Value = false
	end
	
	MatchmakingService:RemovePlayerFromQueueId(plr.UserId)
end)

game.Players.PlayerAdded:Connect(function(plr)
	
	MatchmakingService.FoundGame:Connect(function()
		local Players = game:GetService("Players")
		print("Found match!")
		local frame = plr.PlayerGui.PlayScreen.MidBar.TextButton.Frame
		local Status = frame:FindFirstChild("FoundG")
		local canc = frame:FindFirstChild("Cancel")
		local arr = frame:FindFirstChild("Status")
		arr.Visible = false
		canc.Visible = false
		local status = plr:FindFirstChild("status").Value
		status = "f"
		Status.Visible = true
		frame.Status.Text = "Found Match!"
		wait(2)
		while true do
			Status.Text = "Joining"
			wait(0.4)
			Status.Text = "Joining."
			wait(0.4)
			Status.Text = "Joining.."
			wait(0.4)
			Status.Text = "Joining..."
			wait(0.4)
		end
	end)
	
	local queueonce = Instance.new("BoolValue")
	queueonce.Parent = plr
	queueonce.Name = "queueonce"
	queueonce.Value = false

	local status = Instance.new("StringValue")
	status.Parent = plr
	status.Name = "status"
	status.Value = "n"

	local cs = Instance.new("BoolValue")
	cs.Parent = plr
	cs.Name = "cs"
	cs.Value = false
end)

game.ReplicatedStorage.rank.OnServerEvent:Connect(function(player, frame)
	local rating = MatchmakingService:GetPlayerRating(player, "RankedTest2")
	local ratingnu = MatchmakingService:ToRatingNumber(rating)
	local ratingnus = ratingnu * 15
	local ratingnum = math.ceil(ratingnus)
	local frame = player.PlayerGui.PlayScreen.MidBar.Ranks.Frame	

	frame.Ones.Text = "1v1, MMR: "..ratingnum
	if ratingnum < 250 then
		frame.Ones.TextLabel.Text = "Silver"
		frame.Ones.TextLabel.TextColor3 = Color3.new(0.6, 0.6, 0.6)
		frame.Ones.ImageLabel.Image = "http://www.roblox.com/asset/?id=9406476107"
	end
	if ratingnum > 250 then
		if ratingnum < 425 then
			frame.Ones.TextLabel.Text = "Gold"
			frame.Ones.TextLabel.TextColor3 = Color3.new(0.690196, 0.678431, 0.333333)
			frame.Ones.ImageLabel.Image = "http://www.roblox.com/asset/?id=9406479274"
		end
		end
	if ratingnum > 425 then
		if ratingnum < 675 then
			frame.Ones.TextLabel.Text = "Platinum"
			frame.Ones.TextLabel.TextColor3 = Color3.new(0.0745098, 0.415686, 0.509804)
			frame.Ones.ImageLabel.Image = "http://www.roblox.com/asset/?id=9406481687"
			end
	end
	if ratingnum > 675 then
		if ratingnum < 900 then
			frame.Ones.TextLabel.Text = "Diamond"
			frame.Ones.TextLabel.TextColor3 = Color3.new(0.192157, 0.270588, 0.54902)
			frame.Ones.ImageLabel.Image = "http://www.roblox.com/asset/?id=9406484073"
		end
	end
	if ratingnum > 900 then
		if ratingnum < 1240 then
			frame.Ones.TextLabel.Text = "Bedrock"
			frame.Ones.TextLabel.TextColor3 = Color3.new(0.129412, 0.137255, 0.117647)
			frame.Ones.ImageLabel.Image = "http://www.roblox.com/asset/?id=9406489538"
		end
	end
	if ratingnum > 1240 then
		frame.Ones.TextLabel.Text = "Emerald"
		frame.Ones.TextLabel.TextColor3 = Color3.new(0.352941, 0.552941, 0.266667)
		frame.Ones.ImageLabel.Image = "http://www.roblox.com/asset/?id=9406486698"
	end
end)



Game server script:

local MatchmakingService = require(7567983240).GetSingleton()
local Module = require(game.ServerStorage.MainModule)
local DataStore = require(1936396537)
-- It's important game servers know how large they can get. You don't really need every map here,
-- but you do need whichever map this is.
-- Tell the service this is a game server

MatchmakingService:SetIsGameServer(true)
MatchmakingService:SetPlayerRange("Map 1", NumberRange.new(2, 2))
local TweenService = game:GetService("TweenService")
started = false
endgame = false
local gameData = nil

local t1 = {}

local t2 = {}

local MMRbefore1 = 0
local MMRbefore2 = 0


-- Basic start function

function Start()
	if started == false then
		started = true
		print("Started")

		MatchmakingService:StartGame(gameData.gameCode)

		-- Simple teams for a 1v1.

		local p = game.Players:GetPlayers()

		table.insert(t1, p[1])

		table.insert(t2, p[2])
		
		local rating1 = MatchmakingService:GetPlayerRating(p[1], "RankedTest2")
		local ratingnu1 = MatchmakingService:ToRatingNumber(rating1)
		local ratingnus1 = ratingnu1 * 15
		local ratingnum1 = math.ceil(ratingnus1)
		MMRbefore1 = ratingnum1
		
		local rating2 = MatchmakingService:GetPlayerRating(p[2], "RankedTest2")
		local ratingnu2 = MatchmakingService:ToRatingNumber(rating2)
		local ratingnus2 = ratingnu2 * 15
		local ratingnum2 = math.ceil(ratingnus2)
		MMRbefore2 = ratingnum2
		
		p[1].Character:FindFirstChild("HumanoidRootPart").CFrame = game.Workspace.Arena.TeleportPlr.CFrame
		p[2].Character:FindFirstChild("HumanoidRootPart").CFrame = game.Workspace.Arena.TeleportPlr2.CFrame
	
	end
end

-- YOU MUST CALL UpdateRatings BEFORE THE GAME IS CLOSED. YOU CANNOT PUT THIS IN BindToClose!

function EndGame(winner)
	if endgame == false then
		endgame = true
		MatchmakingService:UpdateRatings("RankedTest2", {if winner == 1 then 1 else 2, if winner == 2 then 1 else 2}, {t1, t2})

		for i, v in ipairs(game.Players:GetPlayers()) do
			if table.find(t1,v) == 1 then
				if winner == 1 then
					local Data1 = DataStore("PB",v)
					local amount = math.random(45,75)
					local amaz = 75 * 2
					local MPS = game:GetService("MarketplaceService")
					local GPI = 41074223
					local ifprem = false
					local ifvip = false
					
					if MPS:UserOwnsGamePassAsync(v.UserId, GPI) then
						Data1:Increment(amaz,0)	
						ifvip = true
					end
					if v.MembershipType == Enum.MembershipType.Premium then
						if ifvip == true then
							
						else
							ifprem = true
							Data1:Increment(amaz,0)
						end
					end
					if ifvip == false then
						if ifprem == false then
							Data1:Increment(amount,0)
						end
					end
					
					local clone = game.ReplicatedStorage.EndScreen:Clone()
					clone.Frame.Results.Won.Text = "You won!"
					clone.Frame.Results.Made.Text = "MMR: "..MMRbefore1
					clone.Frame.Results.ImageLabel.Image = "rbxassetid://9428519351"
					clone.Parent = v.PlayerGui
					local label = clone.Frame.Results.Made
					local arrow = clone.Frame.Results.ImageLabel
					local rating1 = MatchmakingService:GetPlayerRating(v, "RankedTest2")
					local ratingnu1 = MatchmakingService:ToRatingNumber(rating1)
					local ratingnus1 = ratingnu1 * 15
					local ratingnum1 = math.ceil(ratingnus1)
					local tweenInfoWon = TweenInfo.new(
						0.5, -- The time the tween takes to complete
						Enum.EasingStyle.Linear, -- The tween style.
						Enum.EasingDirection.Out, -- EasingDirection
						0, -- How many times you want the tween to repeat. If you make it less than 0 it will repeat forever.
						false, -- Reverse?
						0 -- Delay
					)
					local tweenInfoArrow = TweenInfo.new(
						0.2, -- The time the tween takes to complete
						Enum.EasingStyle.Linear, -- The tween style.
						Enum.EasingDirection.Out, -- EasingDirection
						0, -- How many times you want the tween to repeat. If you make it less than 0 it will repeat forever.
						false, -- Reverse?
						0 -- Delay
					)
					
					local tween = TweenService:Create(label, tweenInfoWon, {TextTransparency = 1})
					local tween2 = TweenService:Create(label, tweenInfoWon, {TextTransparency = 0})
					local tween3 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 1})
					local tween4 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 0})
					local tween5 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 1})
					local tween6 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 0})
					
					local function arrowtween()
						repeat
							tween3:Play()
							wait(0.5)
							tween4:Play()
							wait(0.5)
							tween5:Play()
							wait(0.5)
							tween6:Play()
							wait(0.5)
						until wait(3)
					end
					tween:Play()
					wait(0.8)
					clone.Frame.Results.Made.Text = "MMR: "..ratingnum1
					tween2:Play()
					arrowtween:Play()
					wait(5)
					v:Kick()
				end
				if winner == 2 then
					local Data1 = DataStore("PB",v)
					local amount = math.random(1,45)
					local amaz = 45 * 2
					local MPS = game:GetService("MarketplaceService")
					local GPI = 41074223
					local ifprem = false
					local ifvip = false

					if MPS:UserOwnsGamePassAsync(v.UserId, GPI) then
						Data1:Increment(amaz,0)	
						ifvip = true
					end
					if v.MembershipType == Enum.MembershipType.Premium then
						if ifvip == true then

						else
							ifprem = true
							Data1:Increment(amaz,0)
						end
					end
					if ifvip == false then
						if ifprem == false then
							Data1:Increment(amount,0)
						end
					end
					
					local clone = game.ReplicatedStorage.EndScreen:Clone()
					clone.Frame.Results.Won.Text = "You lost :("
					clone.Frame.Results.Made.Text = "MMR: "..MMRbefore1
					clone.Frame.Results.ImageLabel.Image = "rbxassetid://9428495112"
					clone.Parent = v.PlayerGui
					local label = clone.Frame.Results.Made
					local arrow = clone.Frame.Results.ImageLabel
					local rating1 = MatchmakingService:GetPlayerRating(v, "RankedTest2")
					local ratingnu1 = MatchmakingService:ToRatingNumber(rating1)
					local ratingnus1 = ratingnu1 * 15
					local ratingnum1 = math.ceil(ratingnus1)
					local tweenInfoLost = TweenInfo.new(
						0.5, -- The time the tween takes to complete
						Enum.EasingStyle.Linear, -- The tween style.
						Enum.EasingDirection.Out, -- EasingDirection
						0, -- How many times you want the tween to repeat. If you make it less than 0 it will repeat forever.
						false, -- Reverse?
						0 -- Delay
					)
					local tweenInfoArrow = TweenInfo.new(
						0.2, -- The time the tween takes to complete
						Enum.EasingStyle.Linear, -- The tween style.
						Enum.EasingDirection.Out, -- EasingDirection
						0, -- How many times you want the tween to repeat. If you make it less than 0 it will repeat forever.
						false, -- Reverse?
						0 -- Delay
					)

					local tween = TweenService:Create(label, tweenInfoLost, {TextTransparency = 1})
					local tween2 = TweenService:Create(label, tweenInfoLost, {TextTransparency = 0})
					local tween3 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 1})
					local tween4 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 0})
					local tween5 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 1})
					local tween6 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 0})
					
					local function arrowtween()
						repeat
							tween3:Play()
							wait(0.5)
							tween4:Play()
							wait(0.5)
							tween5:Play()
							wait(0.5)
							tween6:Play()
							wait(0.5)
						until wait(3)
					end
				
					wait(1.8)
					tween:Play()
					wait(0.8)
					clone.Frame.Results.Made.Text = "MMR: "..ratingnum1
					tween2:Play()
					arrowtween()
					wait(5)
					v:Kick()
				end
			end
			if table.find(t2,v) then
				if winner == 2 then
					local Data1 = DataStore("PB",v)
					local amount = math.random(45,75)
					local amaz = 75 * 2
					local MPS = game:GetService("MarketplaceService")
					local GPI = 41074223
					local ifprem = false
					local ifvip = false

					if MPS:UserOwnsGamePassAsync(v.UserId, GPI) then
						Data1:Increment(amaz,0)	
						ifvip = true
					end
					if v.MembershipType == Enum.MembershipType.Premium then
						if ifvip == true then

						else
							ifprem = true
							Data1:Increment(amaz,0)
						end
					end
					if ifvip == false then
						if ifprem == false then
							Data1:Increment(amount,0)
						end
					end	
					
					local clone = game.ReplicatedStorage.EndScreen:Clone()
					clone.Frame.Results.Won.Text = "You won!"
					clone.Frame.Results.Made.Text = "MMR: "..MMRbefore2
					clone.Frame.Results.ImageLabel.Image = "rbxassetid://9428519351"
					clone.Parent = v.PlayerGui
					local label = clone.Frame.Results.Made
					local arrow = clone.Frame.Results.ImageLabel
					local rating1 = MatchmakingService:GetPlayerRating(v, "RankedTest2")
					local ratingnu1 = MatchmakingService:ToRatingNumber(rating1)
					local ratingnus1 = ratingnu1 * 15
					local ratingnum1 = math.ceil(ratingnus1)
					local tweenInfoWon = TweenInfo.new(
						0.5, -- The time the tween takes to complete
						Enum.EasingStyle.Linear, -- The tween style.
						Enum.EasingDirection.Out, -- EasingDirection
						0, -- How many times you want the tween to repeat. If you make it less than 0 it will repeat forever.
						false, -- Reverse?
						0 -- Delay
					)
					local tweenInfoArrow = TweenInfo.new(
						0.2, -- The time the tween takes to complete
						Enum.EasingStyle.Linear, -- The tween style.
						Enum.EasingDirection.Out, -- EasingDirection
						0, -- How many times you want the tween to repeat. If you make it less than 0 it will repeat forever.
						false, -- Reverse?
						0 -- Delay
					)

					local tween = TweenService:Create(label, tweenInfoWon, {TextTransparency = 1})
					local tween2 = TweenService:Create(label, tweenInfoWon, {TextTransparency = 0})
					local tween3 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 1})
					local tween4 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 0})
					local tween5 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 1})
					local tween6 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 0})
					
					local function arrowtween()
						repeat
							tween3:Play()
							wait(0.5)
							tween4:Play()
							wait(0.5)
							tween5:Play()
							wait(0.5)
							tween6:Play()
							wait(0.5)
						until wait(3)
					end
					
					wait(1.8)
					tween:Play()
					wait(0.8)
					clone.Frame.Results.Made.Text = "MMR: "..ratingnum1
					tween2:Play()
					arrowtween()
					wait(5)
					v:Kick()
					end
				if winner == 1 then
					local Data1 = DataStore("PB",v)
					local amount = math.random(1,45)
					local amaz = 75 * 2
					local MPS = game:GetService("MarketplaceService")
					local GPI = 41074223
					local ifprem = false
					local ifvip = false

					if MPS:UserOwnsGamePassAsync(v.UserId, GPI) then
						Data1:Increment(amaz,0)	
						ifvip = true
					end
					if v.MembershipType == Enum.MembershipType.Premium then
						if ifvip == true then

						else
							ifprem = true
							Data1:Increment(amaz,0)
						end
					end
					if ifvip == false then
						if ifprem == false then
							Data1:Increment(amount,0)
						end
					end
					
					
					local clone = game.ReplicatedStorage.EndScreen:Clone()
					clone.Frame.Results.Won.Text = "You lost :("
					clone.Frame.Results.Made.Text = "MMR: "..MMRbefore2
					clone.Frame.Results.ImageLabel.Image = "rbxassetid://9428495112"
					clone.Parent = v.PlayerGui
					local label = clone.Frame.Results.Made
					local arrow = clone.Frame.Results.ImageLabel
					local rating1 = MatchmakingService:GetPlayerRating(v, "RankedTest2")
					local ratingnu1 = MatchmakingService:ToRatingNumber(rating1)
					local ratingnus1 = ratingnu1 * 15
					local ratingnum1 = math.ceil(ratingnus1)
					local tweenInfoWon = TweenInfo.new(
						0.5, -- The time the tween takes to complete
						Enum.EasingStyle.Linear, -- The tween style.
						Enum.EasingDirection.Out, -- EasingDirection
						0, -- How many times you want the tween to repeat. If you make it less than 0 it will repeat forever.
						false, -- Reverse?
						0 -- Delay
					)
					local tweenInfoArrow = TweenInfo.new(
						0.2, -- The time the tween takes to complete
						Enum.EasingStyle.Linear, -- The tween style.
						Enum.EasingDirection.Out, -- EasingDirection
						0, -- How many times you want the tween to repeat. If you make it less than 0 it will repeat forever.
						false, -- Reverse?
						0 -- Delay
					)

					local tween = TweenService:Create(label, tweenInfoWon, {TextTransparency = 1})
					local tween2 = TweenService:Create(label, tweenInfoWon, {TextTransparency = 0})
					local tween3 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 1})
					local tween4 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 0})
					local tween5 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 1})
					local tween6 = TweenService:Create(arrow, tweenInfoArrow, {ImageTransparency = 0})
					
					local function arrowtween()
						repeat
							tween3:Play()
							wait(0.5)
							tween4:Play()
							wait(0.5)
							tween5:Play()
							wait(0.5)
							tween6:Play()
							wait(0.5)
						until wait(3)
					end
					
					wait(1.8)
					tween:Play()
					wait(0.8)
					clone.Frame.Results.Made.Text = "MMR: "..ratingnum1
					tween2:Play()
					arrowtween()
					wait(5)
					v:Kick()
				end
			end
		end
	end
end

game.Players.PlayerAdded:Connect(function(player)

	if not gameData then

		gameData = MatchmakingService:GetGameData()

	end

	if #game.Players:GetPlayers() >= 2 then
		if started == false then
		Start()
		print(gameData.started)
		end
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	if table.find(t1, player) == 1 then
		local winner = 2
		EndGame(winner)
	else
		local winner = 1
		EndGame(winner)
	end
	wait()
end)

Thank you for making this module, everything works perfectly except for my rating going below zero. I am on (V2.0.2)

When I updated to open skill I removed the 0 bound because I believed it was unnecessary. This is because the way openskill works is that it uses multiple values to represent a player. This would make it hard to put a cap on since if one value is low, it does not necessarily mean that their rating is actually below 0 because there’s multiple values that represent the player’s returned ordinal skill. Is this behavior causing trouble?

1 Like

Ohh alright that makes much more sense. I show the user their MMR in my game, any way I could stop it from showing a negative number? I know I could set it to 0 if it’s below 0 but that wouldn’t make much sense. I might just not show the user their MMR then. Thank you for the quick response and this module is amazing.

Edit: I also forgot to say when I had a negative number and I tried to queue with someone that had a positive number, it never found a match? Not sure if I did something wrong there.

This happens because it only searches close to the same value (in pockets of 10). It expands every 10 seconds, but you can set that here: Main Documentation - Matchmaking Service. As for not showing a negative number, you could have a transformation function that adds a static value to their rating that you’re showing that you think is low enough that no one will perform bad enough to go under that value. This also makes it seem like they start higher

1 Like

Ohh! I always thought that it would queue between 50 rating, but that’s actually pretty smart. Thank you for solving my issue! I should have probably checked the documentation, thanks!

1 Like

Is there no problem in using the same place the instance servers use when a player gets teleported with TeleportService (for singleplayer)? Because certain functions like :SetIsGameServer(true) still get called

Is it possible to party users who are in separate servers together?

MMS doesn’t handle parties, so if you can make a way that can do cross server parties, yes it is possible to queue a party cross server using player ids: MatchmakingService:QueuePartyId(players, ratingType, map)

https://github.com/steven4547466/MatchmakingService/blob/master/matchmakingservice.lua#L1108

2 Likes

Hi, since yesterday I’m having this error when someone joins the queue


image