mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-05 05:07:48 +00:00
287 lines
8.6 KiB
Lua
287 lines
8.6 KiB
Lua
--[[
|
|
// FriendsData.lua
|
|
|
|
// Caches the current friends pagination to used by anyone in the app
|
|
// polls every POLL_DELAY and gets the latest pagination
|
|
|
|
// TODO:
|
|
Need polling to update friends. How are we going to handle all the cases
|
|
like the person you're selecting going offline, etc..
|
|
]]
|
|
local CoreGui = game:GetService("CoreGui")
|
|
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
|
|
local Modules = GuiRoot:FindFirstChild("Modules")
|
|
local Players = game:GetService('Players')
|
|
local HttpService = game:GetService('HttpService')
|
|
local PlatformService = nil
|
|
pcall(function() PlatformService = game:GetService('PlatformService') end)
|
|
|
|
local Http = require(Modules:FindFirstChild('Http'))
|
|
local Utility = require(Modules:FindFirstChild('Utility'))
|
|
local EventHub = require(Modules:FindFirstChild('EventHub'))
|
|
local UserData = require(Modules:FindFirstChild('UserData'))
|
|
local SortData = require(Modules:FindFirstChild('SortData'))
|
|
local Strings = require(Modules:FindFirstChild('LocalizedStrings'))
|
|
|
|
-- NOTE: This is just required for fixing Usernames in auto-generatd games
|
|
local GameData = require(Modules:FindFirstChild('GameData'))
|
|
local ConvertMyPlaceNameInXboxAppFlag = Utility.IsFastFlagEnabled("ConvertMyPlaceNameInXboxApp")
|
|
|
|
local FriendsData = {}
|
|
|
|
|
|
local pollDelay = Utility.GetFastVariable("XboxFriendsPolling")
|
|
if pollDelay then
|
|
pollDelay = tonumber(pollDelay)
|
|
end
|
|
|
|
local POLL_DELAY = pollDelay or 30
|
|
local STATUS = {
|
|
UNKNOWN = "Unknown";
|
|
ONLINE = "Online";
|
|
OFFLINE = "Offline";
|
|
AWAY = "Away";
|
|
}
|
|
|
|
local isOnlineFriendsPolling = false
|
|
local myCurrentFriendsData = nil
|
|
local updateEventCns = {}
|
|
|
|
local function filterXboxFriends(friendsData)
|
|
local titleId = PlatformService and tostring(PlatformService:GetTitleId()) or ''
|
|
local onlineRobloxFriendsData = {}
|
|
local onlineRobloxFriendsUserIds = {}
|
|
local onlineFriendsData = {}
|
|
-- filter into two list, those online in roblox and those online
|
|
-- for those online, also get their roblox userId
|
|
for i = 1, #friendsData do
|
|
local data = friendsData[i]
|
|
if data["status"] and data["status"] == STATUS.ONLINE then
|
|
if data["rich"] then
|
|
-- get rich presence table, last entry is most recent activity from user
|
|
local richTbl = data["rich"]
|
|
richTbl = richTbl[#richTbl]
|
|
if richTbl["titleId"] == titleId then
|
|
table.insert(onlineRobloxFriendsData, data)
|
|
table.insert(onlineRobloxFriendsUserIds, data["robloxuid"])
|
|
else
|
|
table.insert(onlineFriendsData, data)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- now get roblox friends presence in roblox
|
|
local robloxPresence = {}
|
|
if #onlineRobloxFriendsUserIds > 0 then
|
|
local jsonTable = {}
|
|
jsonTable["userIds"] = onlineRobloxFriendsUserIds
|
|
local jsonPostBody = HttpService:JSONEncode(jsonTable)
|
|
robloxPresence = Http.GetUsersOnlinePresenceAsync(jsonPostBody)
|
|
if robloxPresence and robloxPresence["UserPresences"] then
|
|
robloxPresence = robloxPresence["UserPresences"]
|
|
end
|
|
end
|
|
|
|
-- now append roblox presence data to each users data
|
|
for i = 1, #onlineRobloxFriendsData do
|
|
if robloxPresence[i] then
|
|
local data = onlineRobloxFriendsData[i]
|
|
-- make sure we have the right person
|
|
for j = 1, #robloxPresence do
|
|
local rbxPresenceData = robloxPresence[j]
|
|
local rbxUserId = rbxPresenceData["VisitorId"]
|
|
if rbxUserId == data["robloxuid"] then
|
|
if rbxPresenceData["IsOnline"] == true then
|
|
local placeId = rbxPresenceData["PlaceId"]
|
|
local lastLocation = rbxPresenceData["LastLocation"]
|
|
|
|
-- If the lastLocation for a user is some user place with a GeneratedUsername in it
|
|
-- then replace it with the actual creator name!
|
|
if ConvertMyPlaceNameInXboxAppFlag and placeId and lastLocation and GameData:ExtractGeneratedUsername(lastLocation) then
|
|
local gameCreator = GameData:GetGameCreatorAsync(placeId)
|
|
if gameCreator then
|
|
lastLocation = GameData:GetFilteredGameName(lastLocation, gameCreator)
|
|
end
|
|
end
|
|
|
|
-- If the user is not in a featured game, then hide their presence
|
|
if placeId and not SortData:IsFeaturedGameAsync(placeId) then
|
|
data["IsPrivateSession"] = true
|
|
lastLocation = Strings:LocalizedString("PrivateSessionPhrase")
|
|
end
|
|
|
|
data["PlaceId"] = placeId
|
|
data["LastLocation"] = lastLocation
|
|
end
|
|
-- remove from list and gtfo
|
|
table.remove(robloxPresence, j)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- now sort those in roblox
|
|
table.sort(onlineRobloxFriendsData, function(a, b)
|
|
if a["PlaceId"] and b["PlaceId"] then
|
|
return a["display"] < b["display"]
|
|
end
|
|
if a["PlaceId"] then
|
|
return true
|
|
end
|
|
if b["PlaceId"] then
|
|
return false
|
|
end
|
|
|
|
return a["display"] < b["display"]
|
|
end)
|
|
|
|
-- now sort all other friends
|
|
table.sort(onlineFriendsData, function(a, b)
|
|
return a["display"] < b["display"]
|
|
end)
|
|
|
|
-- now concat tables
|
|
for i = 1, #onlineFriendsData do
|
|
onlineRobloxFriendsData[#onlineRobloxFriendsData + 1] = onlineFriendsData[i]
|
|
end
|
|
|
|
return onlineRobloxFriendsData
|
|
end
|
|
|
|
--[[
|
|
// Returns table with an array with the key friends
|
|
// Keys
|
|
// xuid - number, xbox user id
|
|
// gamertage - string, users gamertag
|
|
// display - string, users display name (depends on user settings, could be same as gamertag)
|
|
// robloxuid - number, users roblox userId
|
|
// status - string (Online, Away, Offline, Unknown)
|
|
// rich - array of rich presence, might currently be empty?
|
|
// timestamp - number, UTC timestamp of record
|
|
// device - string, XboxOne, Windows8, etc.
|
|
// title - string, of game
|
|
// playing - boolean, are they playing the game
|
|
// presence - string, rich presence string from that title
|
|
]]
|
|
local function fetchXboxFriendsAsync()
|
|
local success, result = pcall(function()
|
|
if PlatformService then
|
|
return PlatformService:BeginFetchFriends(Enum.UserInputType.Gamepad1)
|
|
end
|
|
end)
|
|
if success then
|
|
return HttpService:JSONDecode(result)
|
|
else
|
|
print("fetchXboxFriends failed because", result)
|
|
end
|
|
end
|
|
|
|
local function getOnlineFriends()
|
|
if UserSettings().GameSettings:InStudioMode() then
|
|
-- Roblox Friends - leaving this in for testing purposes in studio
|
|
local result = Http.GetOnlineFriendsAsync()
|
|
if not result then
|
|
-- TODO: Error code
|
|
return nil
|
|
end
|
|
--
|
|
local myOnlineFriends = {}
|
|
|
|
for i = 1, #result do
|
|
local data = result[i]
|
|
local friend = {
|
|
Name = Players:GetNameFromUserIdAsync(data["VisitorId"]);
|
|
UserId = data["VisitorId"];
|
|
LastLocation = data["LastLocation"];
|
|
PlaceId = data["PlaceId"];
|
|
LocationType = data["LocationType"];
|
|
GameId = data["GameId"];
|
|
}
|
|
table.insert(myOnlineFriends, friend)
|
|
end
|
|
|
|
local function sortFunc(a, b)
|
|
if a.LocationType == b.LocationType then
|
|
return a.Name:lower() < b.Name:lower()
|
|
end
|
|
return a.LocationType > b.LocationType
|
|
end
|
|
|
|
table.sort(myOnlineFriends, sortFunc)
|
|
|
|
return myOnlineFriends
|
|
elseif game:GetService('UserInputService'):GetPlatform() == Enum.Platform.XBoxOne then
|
|
-- Xbox Friends
|
|
local myXboxFriends = fetchXboxFriendsAsync()
|
|
local myOnlineFriends = {}
|
|
if myXboxFriends then
|
|
myXboxFriends = myXboxFriends["friends"]
|
|
myOnlineFriends = filterXboxFriends(myXboxFriends)
|
|
end
|
|
|
|
return myOnlineFriends
|
|
end
|
|
end
|
|
|
|
--[[ Public API ]]--
|
|
FriendsData.OnFriendsDataUpdated = Utility.Signal()
|
|
|
|
local isFetchingFriends = false
|
|
function FriendsData.GetOnlineFriendsAsync()
|
|
-- can only make one call into PlatformService:BeginFetchFriends() at a time
|
|
while isFetchingFriends do
|
|
wait()
|
|
end
|
|
-- we have current data, this will be updated when polling
|
|
if myCurrentFriendsData then
|
|
return myCurrentFriendsData
|
|
end
|
|
isFetchingFriends = true
|
|
|
|
myCurrentFriendsData = getOnlineFriends()
|
|
-- spawn polling on first request
|
|
if not isOnlineFriendsPolling then
|
|
FriendsData.BeginPolling()
|
|
end
|
|
|
|
isFetchingFriends = false
|
|
|
|
return myCurrentFriendsData
|
|
end
|
|
|
|
function FriendsData.BeginPolling()
|
|
if not isOnlineFriendsPolling then
|
|
isOnlineFriendsPolling = true
|
|
local requesterId = UserData:GetRbxUserId()
|
|
spawn(function()
|
|
wait(POLL_DELAY)
|
|
while requesterId == UserData:GetRbxUserId() do
|
|
myCurrentFriendsData = getOnlineFriends()
|
|
FriendsData.OnFriendsDataUpdated:fire(myCurrentFriendsData)
|
|
wait(POLL_DELAY)
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
|
|
-- we make connections through this function so we can clean them all up upon
|
|
-- clearing the friends data
|
|
function FriendsData.ConnectUpdateEvent(cbFunc)
|
|
local cn = FriendsData.OnFriendsDataUpdated:connect(cbFunc)
|
|
table.insert(updateEventCns, cn)
|
|
end
|
|
|
|
function FriendsData.Reset()
|
|
isOnlineFriendsPolling = false
|
|
myCurrentFriendsData = nil
|
|
for index,cn in pairs(updateEventCns) do
|
|
cn = Utility.DisconnectEvent(cn)
|
|
updateEventCns[index] = nil
|
|
end
|
|
print('FriendsData: Cleared last users FriendsData')
|
|
end
|
|
|
|
return FriendsData
|