Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local lookForGameEvent = game.ReplicatedStorage.LookForGameEvent
- local rankedList = require(game.ServerStorage.MatchmakingRankedListModule)
- local ratingData = game:GetService("DataStoreService"):GetDataStore("RatingData")
- local teleportService = game:GetService("TeleportService")
- local arenaPlaceTemplateId = 667393809
- -- Table to hold the queue of players looking for a game
- local matchMakingQueue = {}
- -- Add player's id to the queue as well as the time that they entered the queue
- local addToMMQueue = function(playerId, enteredTime)
- local data = {}
- data.UserId = playerId
- data.EnteredQueue = enteredTime
- table.insert(matchMakingQueue, data)
- end
- -- Remove player from the queue
- local removeFromMMQueue = function(playerId)
- for i, playerData in pairs(matchMakingQueue) do
- if playerData.UserId == playerId then
- table.remove(matchMakingQueue, i)
- return
- end
- end
- end
- -- Handle player joining the game. If they are a new player we need to give them
- -- an initial rank. For existing players we need to fetch their rank from our
- -- DataStore. Lastly, we want to display the player's rank in the Leaderboard
- game.Players.PlayerAdded:connect(function(player)
- local playerData = {}
- -- Create a default rating of 1500 if the player's data is not in the DataStore
- ratingData:UpdateAsync(player.userId, function(oldValue)
- local newValue = oldValue
- if not newValue then
- newValue = {Rating = 1500}
- end
- return newValue
- end)
- playerData.Score = ratingData:GetAsync(tostring(player.userId)).Rating
- -- Display rating in Leaderboard
- local leaderstats = Instance.new("Model", player)
- leaderstats.Name = "leaderstats"
- local displayRating = Instance.new("IntValue", leaderstats)
- displayRating.Name = "Rating"
- displayRating.Value = playerData.Score
- end)
- -- Adds player both to queue and list to search for match
- local function playerSearchingForMatch(userId, rank)
- local now = os.time()
- addToMMQueue(userId, now)
- rankedList:AddPlayer(userId, rank, now)
- end
- -- Remove player from list and queue when they leave the game
- game.Players.PlayerRemoving:connect(function(player)
- removeFromMMQueue(player.userId)
- rankedList:RemovePlayer(player.userId)
- end)
- -- Handle remote event to either add or remove player from the queue
- lookForGameEvent.OnServerEvent:connect(function(player, lookingForGame)
- if lookingForGame then
- print(player.Name .. " now looking for game")
- local enteredTime = os.time()
- playerSearchingForMatch(player.userId, player.leaderstats.Rating.Value)
- else
- print(player.Name .. " has left the queue")
- removeFromMMQueue(player.userId)
- rankedList:RemovePlayer(player.userId)
- end
- end)
- -- Returns a rank range to search through based on time waiting in the queue.
- -- If player has been waiting too long just return math.huge so the player can
- -- be matched with anyone.
- local getRange = function(timeWaiting)
- if timeWaiting < 10 then
- return 100
- elseif timeWaiting >=10 and timeWaiting < 20 then
- return 200
- elseif timeWaiting >=20 and timeWaiting <= 35 then
- return 300
- end
- return math.huge
- end
- -- Creates place for game and teleports both players to it
- local startGame = function(playerAId, playerBId)
- local message = ""
- print("starting game with " .. playerAId .. " and " .. playerBId)
- -- Get both player objects
- local playerA = nil
- local playerB = nil
- for _, player in pairs(game.Players:GetPlayers()) do
- if player.userId == playerAId then
- playerA = player
- end
- if player.userId == playerBId then
- playerB = player
- end
- end
- -- Create arena place and get its id
- local arenaPlaceId = game:GetService("AssetService"):CreatePlaceAsync(
- "Arena place for " .. playerA.Name .. " and " .. playerB.Name, arenaPlaceTemplateId)
- -- Bind OnTeleport event to playerA (who is teleported first). If that teleport is successful
- -- then we want playerB to be teleported to the same instance
- local connection = playerA.OnTeleport:connect(function(teleportState, placeId)
- if teleportState == Enum.TeleportState.Started then
- local teleportStarted = os.time()
- -- Keep checking if playerA has arrived in other instance.
- while true do
- local success, error, placeId, arenaInstanceId = teleportService:GetPlayerPlaceInstanceAsync(playerAId)
- -- If playerA is in the correct place then we can teleport playerB there as well
- if placeId == arenaPlaceId then
- teleportService:TeleportToPlaceInstance(arenaPlaceId, arenaInstanceId, playerB)
- return
- end
- wait()
- end
- end
- end)
- wait(1)
- -- Teleport playerA to the arena
- teleportService:Teleport(arenaPlaceId, playerA)
- end
- -- Matchmaking loop. Cycles about every 5 seconds to match players.
- while true do
- local now = os.time()
- -- Cycle through queue, try to find players in range
- for _, mmData in pairs(matchMakingQueue) do
- print("attempting to find match for " .. mmData.UserId)
- -- Get rank range to search
- local range = getRange(now - mmData.EnteredQueue)
- -- Use list to find a player in player's rank range
- local otherPlayerId = rankedList:FindPlayerInRange(mmData.UserId, range)
- if otherPlayerId then
- -- Another player was found. Remove both players from the queue and list so they
- -- can't be matched with anyone else
- print("found player: " .. otherPlayerId)
- rankedList:RemovePlayer(mmData.UserId)
- rankedList:RemovePlayer(otherPlayerId)
- removeFromMMQueue(mmData.UserId)
- removeFromMMQueue(otherPlayerId)
- -- Start game with the two players. This function can take some times, so start a
- -- coroutine so the loop can continue.
- local thread = coroutine.create(function() startGame(mmData.UserId, otherPlayerId) end)
- coroutine.resume(thread)
- end
- end
- wait(5)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement