Description: I’m developing a game that empowers users to create and share their own unique experiences. The “Friend Join Tab” feature is a crucial element of this vision, allowing players to effortlessly connect with friends and explore each other’s creations. However, the presence system, which tracks friends’ online status and session availability, is malfunctioning.
Why is this Feature Necessary? The Friend Join Tab is integral to the social and creative aspects of the game. By enabling users to join friends’ sessions, the feature fosters collaboration, creativity, and community-building within the game. Without it, the game’s core philosophy—bringing people together to share and enjoy their creations—falls short.
Steps to Reproduce:
- Launch the Friend Join Tab within the game.
- Attempt to check friends’ presence or join their sessions.
- Observe that the presence system is not functioning correctly.
What is the Issue? Presence data does not update in real-time or accurately reflect friends’ availability, making it impossible to join sessions.
Solutions Tried So Far:
- Debugged presence logic for tracking online status and session availability.
- Verified server communication and API integration for presence updates.
- Reviewed documentation but the problem persists.
Additional Details:
- This issue may stem from delayed presence updates or misconfigured event handling.
My code
local Players = game:GetService("Players")
local HttpService = game:GetService("HttpService")
local TeleportService = game:GetService("TeleportService")
local DataStoreService = game:GetService("DataStoreService")
local gameModeDataStore = DataStoreService:GetDataStore("GameModeDataStore")
local screenGui = script.Parent
local template = screenGui.explorer.main.friends.scroll.template
local scroll = screenGui.explorer.main.friends.scroll
local refreshBtn = screenGui.explorer.refresh
local function getGameModeByUserId(userId: number)
local success, placeId, jobId = pcall(function()
return TeleportService:GetPlayerPlaceInstanceAsync(userId)
end)
if success and placeId and jobId then
local gameMode
success, gameMode = pcall(function()
return gameModeDataStore:GetAsync(jobId)
end)
if success and gameMode then
return gameMode, jobId
else
return nil, jobId
end
end
return nil, nil
end
local function teleportToServer(player: Player, targetUserId: number)
local gameMode, jobId = getGameModeByUserId(targetUserId)
if gameMode and jobId then
print(player.Name, "is teleporting to server hosting:", gameMode)
local success, err = pcall(function()
TeleportService:TeleportToPlaceInstance(game.PlaceId, jobId, player)
end)
if not success then
warn("Teleport failed:", err)
end
end
end
local function getFriends(player: Player)
local friendPages = Players:GetFriendsAsync(player.UserId)
local friendIds = {}
local function iteratePages(pages)
return coroutine.wrap(function()
repeat
for _, item in ipairs(pages:GetCurrentPage()) do
coroutine.yield(item)
end
pages:AdvanceToNextPageAsync()
until pages.IsFinished
end)
end
for friend in iteratePages(friendPages) do
table.insert(friendIds, friend.UserId)
end
return friendIds
end
local function getPlayersPlaying(player: Player)
local function splitChunks(array, size)
local chunks = {}
for i = 1, #array, size do
local chunk = {}
for j = i, math.min(i + size - 1, #array) do
table.insert(chunk, array[j])
end
table.insert(chunks, chunk)
end
return chunks
end
local function checkPresence(userIds)
local apiEndpoint = "https://presence.roproxy.com/v1/presence/users"
local results = {}
local batches = splitChunks(userIds, 100)
for _, batch in ipairs(batches) do
local body = HttpService:JSONEncode({ userIds = batch })
local success, response = pcall(function()
return HttpService:PostAsync(apiEndpoint, body, Enum.HttpContentType.ApplicationJson)
end)
if success then
local decoded = HttpService:JSONDecode(response)
table.insert(results, decoded)
else
warn("Presence check failed:", response)
end
end
return results
end
local friendIds = getFriends(player)
local presenceResults = checkPresence(friendIds)
local currentUniverseId = 130901771589509 -- YOUR universe ID here
local onlineFriends = {}
for _, batch in ipairs(presenceResults) do
for _, presence in ipairs(batch.userPresences or {}) do
if presence.universeId == currentUniverseId then
table.insert(onlineFriends, presence.userId)
end
end
end
return onlineFriends
end
local function setupProfile(clone: Frame, userId: number, localPlayer: Player)
local successName, username = pcall(function()
return Players:GetNameFromUserIdAsync(userId)
end)
if not successName then username = "Unknown" end
local successImg, thumb = pcall(function()
return Players:GetUserThumbnailAsync(userId, Enum.ThumbnailType.AvatarThumbnail, Enum.ThumbnailSize.Size420x420)
end)
if not successImg then thumb = "rbxasset://textures/ui/GuiImagePlaceholder.png" end
local gameMode, _ = getGameModeByUserId(userId)
clone.mugshot.Image = thumb
clone.person.Text = username
clone.game.Text = gameMode or "Unknown"
clone.MouseButton1Click:Connect(function()
teleportToServer(localPlayer, userId)
end)
clone.Visible = true
clone.Parent = scroll
end
local function setupProfiles(player: Player)
for _, child in ipairs(scroll:GetChildren()) do
if child:IsA("GuiObject") and child.Name ~= "template" then
child:Destroy()
end
end
for _, userId in ipairs(getPlayersPlaying(player)) do
local clone = template:Clone()
setupProfile(clone, userId, player)
end
end
-- ✅ Use LocalScript-compatible player reference
local CurrentPlayer = screenGui.Parent.Parent
if not CurrentPlayer then
warn("Couldn't resolve current player!")
else
setupProfiles(CurrentPlayer)
refreshBtn.MouseButton1Click:Connect(function()
setupProfiles(CurrentPlayer)
end)
end
Added way to many console prints for debugging