add gs
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"lint": {
|
||||
"SameLineStatement": "fatal",
|
||||
"LocalShadow": "fatal",
|
||||
"FunctionUnused": "fatal",
|
||||
"ImportUnused": "fatal"
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
local Players = game:GetService("Players")
|
||||
local CoreGuiService = game:GetService("CoreGui")
|
||||
local RobloxReplicatedStorage = game:GetService("RobloxReplicatedStorage")
|
||||
|
||||
local RobloxGui = CoreGuiService:FindFirstChild("RobloxGui")
|
||||
local CoreGuiModules = RobloxGui:FindFirstChild("Modules")
|
||||
local CommonModules = CoreGuiModules:FindFirstChild("Common")
|
||||
|
||||
local Rigging = require(CommonModules:FindFirstChild("RagdollRigging"))
|
||||
local HumanoidReadyUtil = require(CommonModules:FindFirstChild("HumanoidReadyUtil"))
|
||||
|
||||
local deathType = game:DefineFastString("DeathTypeValue", "Classic")
|
||||
|
||||
-- Replicate this to clients so all clients make the same choice
|
||||
local DeathTypeValue = Instance.new("StringValue")
|
||||
DeathTypeValue.Name = "DeathType"
|
||||
DeathTypeValue.Value = deathType
|
||||
DeathTypeValue.Parent = RobloxReplicatedStorage
|
||||
|
||||
-- Everything below is in support of ragdoll death
|
||||
if deathType ~= "Ragdoll" then
|
||||
return
|
||||
end
|
||||
|
||||
-- { [player: Player] = humanoid: Humanoid, ... }
|
||||
local riggedPlayerHumanoids = {}
|
||||
|
||||
-- Create remote event for the client to notify the server that it went ragdoll. The server
|
||||
-- never disables joints authoritatively until the client acknowledges that it has already
|
||||
-- broken it's own joints non-authoritatively, started simulating the ragdoll locally, and
|
||||
-- should already be sending physics data.
|
||||
local remote = Instance.new("RemoteEvent")
|
||||
remote.Name = "OnRagdoll"
|
||||
remote.OnServerEvent:Connect(function(remotePlayer, humanoid)
|
||||
if humanoid and riggedPlayerHumanoids[remotePlayer] == humanoid then
|
||||
local character = humanoid and humanoid.Parent
|
||||
if character and character:IsA("Model") then
|
||||
Rigging.disableMotors(character, humanoid.RigType)
|
||||
end
|
||||
-- One time, one way.
|
||||
riggedPlayerHumanoids[remotePlayer] = nil
|
||||
end
|
||||
end)
|
||||
remote.Parent = RobloxReplicatedStorage
|
||||
|
||||
HumanoidReadyUtil.registerHumanoidReady(function(player, character, humanoid)
|
||||
local ancestryChangedConn
|
||||
local function disconnect()
|
||||
ancestryChangedConn:Disconnect()
|
||||
if riggedPlayerHumanoids[player] == humanoid then
|
||||
riggedPlayerHumanoids[player] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Handle connection cleanup on remove
|
||||
ancestryChangedConn = humanoid.AncestryChanged:Connect(function(_child, parent)
|
||||
if not game:IsAncestorOf(parent) then
|
||||
disconnect()
|
||||
end
|
||||
end)
|
||||
|
||||
-- We will only disable specific joints
|
||||
humanoid.BreakJointsOnDeath = false
|
||||
|
||||
-- Server creates ragdoll joints on spawn to allow for seamless transition even if death is
|
||||
-- initiated on the client. The Motor6Ds keep them inactive until they are disabled.
|
||||
Rigging.createRagdollJoints(character, humanoid.RigType)
|
||||
riggedPlayerHumanoids[player] = humanoid
|
||||
end)
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
-- ServerLeaderstats.lua
|
||||
-- Authors: WallsAreForClimbing (2020)
|
||||
-- Description: Tracks leaderstat creation order
|
||||
|
||||
local LEADERSTATS_NAME = "leaderstats"
|
||||
local REPLICATED_ATTRIBUTE_NAME = "LeaderstatsOrder"
|
||||
|
||||
local Players = game:GetService("Players")
|
||||
local RobloxReplicatedStorage = game:GetService("RobloxReplicatedStorage")
|
||||
|
||||
local FFlagFallbackLeaderstatOrdering = game:DefineFastFlag("FallbackLeaderstatOrdering", false)
|
||||
|
||||
local statOrder = {}
|
||||
local statCount = 0
|
||||
|
||||
local updateStats do
|
||||
if FFlagFallbackLeaderstatOrdering then
|
||||
|
||||
-- We should never need to enable this code.
|
||||
-- It is a fallback in-case there is an issue
|
||||
-- using attributes.
|
||||
|
||||
-- StringValue Fallback
|
||||
local HttpService = game:GetService("HttpService")
|
||||
local valueInstance = Instance.new("StringValue")
|
||||
|
||||
valueInstance.Name = REPLICATED_ATTRIBUTE_NAME
|
||||
valueInstance.Parent = RobloxReplicatedStorage
|
||||
|
||||
function updateStats()
|
||||
valueInstance.Value = HttpService:JSONEncode(statOrder)
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- Attributes
|
||||
function updateStats()
|
||||
RobloxReplicatedStorage:SetAttribute(REPLICATED_ATTRIBUTE_NAME, statOrder)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
updateStats()
|
||||
|
||||
local function addLeaderstat(statName)
|
||||
if statOrder[statName] then
|
||||
return
|
||||
end
|
||||
statOrder[statName] = statCount
|
||||
statCount += 1
|
||||
updateStats()
|
||||
end
|
||||
|
||||
local function waitUntilRemoved(instance)
|
||||
repeat
|
||||
local _, parent = instance.AncestryChanged:Wait()
|
||||
until not parent
|
||||
end
|
||||
|
||||
local function fastSpawn(f, ...)
|
||||
return coroutine.wrap(f)(...)
|
||||
end
|
||||
|
||||
local function isValidStat(obj)
|
||||
return obj:IsA("StringValue") or obj:IsA("IntValue") or obj:IsA("BoolValue") or obj:IsA("NumberValue") or
|
||||
obj:IsA("DoubleConstrainedValue") or obj:IsA("IntConstrainedValue")
|
||||
end
|
||||
|
||||
local function isValidContainer(instance)
|
||||
return instance:IsA("ValueBase") or instance:IsA("Folder") or instance:IsA("Configuration") or instance:IsA("Model")
|
||||
end
|
||||
|
||||
local threads = {}
|
||||
|
||||
local function leaderstatsAdded(instance)
|
||||
local listeners = {}
|
||||
|
||||
local function childAdded(child)
|
||||
if not isValidStat(child) then
|
||||
return
|
||||
end
|
||||
local nameChanged = child:GetPropertyChangedSignal("Name"):Connect(function()
|
||||
addLeaderstat(child.Name)
|
||||
end)
|
||||
addLeaderstat(child.Name)
|
||||
listeners[child] = nameChanged
|
||||
waitUntilRemoved(child)
|
||||
nameChanged:Disconnect()
|
||||
listeners[child] = nil
|
||||
end
|
||||
|
||||
listeners.ChildAdded = instance.ChildAdded:Connect(childAdded)
|
||||
|
||||
for _, child in ipairs(instance:GetChildren()) do
|
||||
fastSpawn(childAdded, child)
|
||||
end
|
||||
|
||||
threads[instance] = coroutine.running()
|
||||
coroutine.yield()
|
||||
for _, listener in pairs(listeners) do
|
||||
listener:Disconnect()
|
||||
end
|
||||
end
|
||||
|
||||
local function leaderstatsRemoved(instance)
|
||||
local thread = threads[instance]
|
||||
if thread then
|
||||
coroutine.resume(thread)
|
||||
end
|
||||
threads[instance] = nil
|
||||
end
|
||||
|
||||
local function playerChildNameChanged(instance)
|
||||
if instance.Name == LEADERSTATS_NAME then
|
||||
leaderstatsAdded(instance)
|
||||
else
|
||||
leaderstatsRemoved(instance)
|
||||
end
|
||||
end
|
||||
|
||||
local function playerChildAdded(instance)
|
||||
if not isValidContainer(instance) then
|
||||
return
|
||||
end
|
||||
local nameChanged = instance:GetPropertyChangedSignal("Name"):Connect(function ()
|
||||
playerChildNameChanged(instance)
|
||||
end)
|
||||
fastSpawn(playerChildNameChanged, instance)
|
||||
waitUntilRemoved(instance)
|
||||
nameChanged:Disconnect()
|
||||
if instance.Name == LEADERSTATS_NAME then
|
||||
leaderstatsRemoved(instance)
|
||||
end
|
||||
end
|
||||
|
||||
local function playerAdded(player)
|
||||
local childAdded = player.ChildAdded:Connect(playerChildAdded)
|
||||
for _, instance in ipairs(player:GetChildren()) do
|
||||
fastSpawn(playerChildAdded, instance)
|
||||
end
|
||||
waitUntilRemoved(player)
|
||||
childAdded:Disconnect()
|
||||
end
|
||||
|
||||
Players.PlayerAdded:Connect(playerAdded)
|
||||
|
||||
for _, player in ipairs(Players:GetPlayers()) do
|
||||
fastSpawn(playerAdded, player)
|
||||
end
|
||||
+393
@@ -0,0 +1,393 @@
|
||||
--[[
|
||||
// FileName: PlayerlistModule.lua
|
||||
// Version 1.0
|
||||
// Written by: jmargh
|
||||
// Description: Implements social features that need to be ran on the server
|
||||
|
||||
// TODO
|
||||
We need to get module script working on the server. When we get that working
|
||||
This should be moved to a module, and http helper functions should be moved
|
||||
to a utility module.
|
||||
]]
|
||||
local HttpService = game:GetService('HttpService')
|
||||
local HttpRbxApiService = game:GetService('HttpRbxApiService')
|
||||
local Players = game:GetService('Players')
|
||||
local RobloxReplicatedStorage = game:GetService('RobloxReplicatedStorage')
|
||||
local RunService = game:GetService('RunService')
|
||||
local Chat = game:GetService("Chat")
|
||||
|
||||
local GET_MULTI_FOLLOW = "user/multi-following-exists"
|
||||
|
||||
-- Maximum amount of follow notifications that a player is allowed to send to another player.
|
||||
local MAX_FOLLOW_NOTIFICATIONS_BETWEEN = 5
|
||||
|
||||
local PlayerToRelationshipMap = {}
|
||||
|
||||
-- Special groups that have leaderboard icons.
|
||||
local SPECIAL_GROUPS = {
|
||||
Admin = {GroupId = 1200769},
|
||||
Intern = {GroupId = 2868472, GroupRank = 100},
|
||||
Star = {GroupId = 4199740},
|
||||
SpanishLocalizationExpert = {GroupId = 4265462, GroupRank = 252},
|
||||
BrazilianLocalizationExpert = {GroupId = 4265456, GroupRank = 252},
|
||||
FrenchLocalizationExpert = {GroupId = 4265443, GroupRank = 252},
|
||||
GermanLocalizationExpert = {GroupId = 4265449, GroupRank = 252},
|
||||
}
|
||||
|
||||
if game.CreatorType == Enum.CreatorType.Group then
|
||||
SPECIAL_GROUPS.PlaceCreator = {GroupId = game.CreatorId, GroupRank = 255}
|
||||
end
|
||||
|
||||
-- Map of which special groups a player is in.
|
||||
local PlayerToGroupDetailsMap = {}
|
||||
|
||||
-- Map of player to if they can manage the current place.
|
||||
local PlayerToCanManageMap = {}
|
||||
|
||||
game:DefineFastFlag("RemoveInGameFollowingServer", false)
|
||||
|
||||
--[[ Remotes ]]--
|
||||
local RemoteEvent_FollowRelationshipChanged
|
||||
local RemoteEvent_NewFollower
|
||||
local RemoteFunc_GetFollowRelationships
|
||||
if not game:GetFastFlag("RemoveInGameFollowingServer") then
|
||||
RemoteEvent_FollowRelationshipChanged = Instance.new('RemoteEvent')
|
||||
RemoteEvent_FollowRelationshipChanged.Name = "FollowRelationshipChanged"
|
||||
RemoteEvent_FollowRelationshipChanged.Parent = RobloxReplicatedStorage
|
||||
|
||||
RemoteEvent_NewFollower = Instance.new("RemoteEvent")
|
||||
RemoteEvent_NewFollower.Name = "NewFollower"
|
||||
RemoteEvent_NewFollower.Parent = RobloxReplicatedStorage
|
||||
|
||||
RemoteFunc_GetFollowRelationships = Instance.new('RemoteFunction')
|
||||
RemoteFunc_GetFollowRelationships.Name = "GetFollowRelationships"
|
||||
RemoteFunc_GetFollowRelationships.Parent = RobloxReplicatedStorage
|
||||
end
|
||||
|
||||
local RemoteEvent_CanChatWith = Instance.new("RemoteEvent")
|
||||
RemoteEvent_CanChatWith.Name = "CanChatWith"
|
||||
RemoteEvent_CanChatWith.Parent = RobloxReplicatedStorage
|
||||
|
||||
local RemoteEvent_SetPlayerBlockList = Instance.new('RemoteEvent')
|
||||
RemoteEvent_SetPlayerBlockList.Name = 'SetPlayerBlockList'
|
||||
RemoteEvent_SetPlayerBlockList.Parent = RobloxReplicatedStorage
|
||||
|
||||
local RemoteEvent_UpdatePlayerBlockList = Instance.new('RemoteEvent')
|
||||
RemoteEvent_UpdatePlayerBlockList.Name = 'UpdatePlayerBlockList'
|
||||
RemoteEvent_UpdatePlayerBlockList.Parent = RobloxReplicatedStorage
|
||||
|
||||
local RemoteEvent_PlayerGroupDetails = Instance.new('RemoteEvent')
|
||||
RemoteEvent_PlayerGroupDetails.Name = 'NewPlayerGroupDetails'
|
||||
RemoteEvent_PlayerGroupDetails.Parent = RobloxReplicatedStorage
|
||||
|
||||
local RemoveEvent_NewPlayerCanManageDetails = Instance.new('RemoteEvent')
|
||||
RemoveEvent_NewPlayerCanManageDetails.Name = 'NewPlayerCanManageDetails'
|
||||
RemoveEvent_NewPlayerCanManageDetails.Parent = RobloxReplicatedStorage
|
||||
|
||||
--[[ Helper Functions ]]--
|
||||
local function decodeJSON(json)
|
||||
local success, result = pcall(function()
|
||||
return HttpService:JSONDecode(json)
|
||||
end)
|
||||
if not success then
|
||||
print("decodeJSON() failed because", result, "Input:", json)
|
||||
return nil
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
local function rbxApiPostAsync(path, params, throttlePriority, contentType, httpType)
|
||||
local success, result = pcall(function()
|
||||
return HttpRbxApiService:PostAsync(path, params, throttlePriority, contentType, httpType)
|
||||
end)
|
||||
--
|
||||
if not success then
|
||||
local label = string.format("%s: - path: %s, \njson: %s", tostring(result), tostring(path), tostring(params))
|
||||
return nil
|
||||
end
|
||||
|
||||
return decodeJSON(result)
|
||||
end
|
||||
|
||||
--[[
|
||||
// Return - table
|
||||
Key: FollowingDetails
|
||||
Value: Arrary of details
|
||||
Key: UserId1
|
||||
Value: number - userId of new client
|
||||
Key: UserId2
|
||||
Value: number - userId of other client
|
||||
Key: User1FollowsUser2
|
||||
Value: boolean
|
||||
Key: User2FollowsUser1
|
||||
Value: boolean
|
||||
]]
|
||||
local function getFollowRelationshipsAsync(uid)
|
||||
if RunService:IsStudio() then
|
||||
return
|
||||
end
|
||||
|
||||
local otherUserIdTable = {}
|
||||
for _,player in pairs(Players:GetPlayers()) do
|
||||
if player.UserId > 0 then
|
||||
table.insert(otherUserIdTable, player.UserId)
|
||||
end
|
||||
end
|
||||
|
||||
if #otherUserIdTable > 0 and uid and uid > 0 then
|
||||
local jsonPostBody = {
|
||||
userId = uid;
|
||||
otherUserIds = otherUserIdTable;
|
||||
}
|
||||
jsonPostBody = HttpService:JSONEncode(jsonPostBody)
|
||||
|
||||
if jsonPostBody then
|
||||
return rbxApiPostAsync(GET_MULTI_FOLLOW, jsonPostBody,
|
||||
Enum.ThrottlingPriority.Default, Enum.HttpContentType.ApplicationJson,
|
||||
Enum.HttpRequestType.Players)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function createRelationshipObject(user1FollowsUser2, user2FollowsUser1)
|
||||
local object = {}
|
||||
object.IsFollower = user2FollowsUser1
|
||||
object.IsFollowing = user1FollowsUser2
|
||||
object.IsMutual = user1FollowsUser2 and user2FollowsUser1
|
||||
|
||||
return object
|
||||
end
|
||||
|
||||
local function updateAndNotifyClients(resultTable, newUserIdStr, newPlayer)
|
||||
local followingDetails = resultTable["FollowingDetails"]
|
||||
if followingDetails then
|
||||
local relationshipTable = PlayerToRelationshipMap[newUserIdStr] or {}
|
||||
|
||||
for i = 1, #followingDetails do
|
||||
local detail = followingDetails[i]
|
||||
local otherUserId = detail["UserId2"]
|
||||
local otherUserIdStr = tostring(otherUserId)
|
||||
|
||||
local followsOther = detail["User1FollowsUser2"]
|
||||
local followsNewPlayer = detail["User2FollowsUser1"]
|
||||
|
||||
relationshipTable[otherUserIdStr] = createRelationshipObject(followsOther, followsNewPlayer)
|
||||
|
||||
-- update other use
|
||||
local otherRelationshipTable = PlayerToRelationshipMap[otherUserIdStr]
|
||||
if otherRelationshipTable then
|
||||
local newRelationship = createRelationshipObject(followsNewPlayer, followsOther)
|
||||
otherRelationshipTable[newUserIdStr] = newRelationship
|
||||
|
||||
local otherPlayer = Players:GetPlayerByUserId(otherUserId)
|
||||
if otherPlayer then
|
||||
-- create single entry table (keep format same) and send to other client
|
||||
local deltaTable = {}
|
||||
deltaTable[newUserIdStr] = newRelationship
|
||||
RemoteEvent_FollowRelationshipChanged:FireClient(otherPlayer, deltaTable)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
PlayerToRelationshipMap[newUserIdStr] = relationshipTable
|
||||
RemoteEvent_FollowRelationshipChanged:FireClient(newPlayer, relationshipTable)
|
||||
end
|
||||
end
|
||||
|
||||
--[[ Connections ]]--
|
||||
if not game:GetFastFlag("RemoveInGameFollowingServer") then
|
||||
function RemoteFunc_GetFollowRelationships.OnServerInvoke(player)
|
||||
local uid = player.UserId
|
||||
local uidStr = tostring(player.UserId)
|
||||
if uid and uid > 0 and PlayerToRelationshipMap[uidStr] then
|
||||
return PlayerToRelationshipMap[uidStr]
|
||||
else
|
||||
return {}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Map: { UserId -> { UserId -> NumberOfNotificationsSent } }
|
||||
local FollowNotificationsBetweenMap = {}
|
||||
|
||||
local function isPlayer(value)
|
||||
return typeof(value) == "Instance" and value:IsA("Player")
|
||||
end
|
||||
|
||||
-- client fires event to server on new follow
|
||||
if not game:GetFastFlag("RemoveInGameFollowingServer") then
|
||||
RemoteEvent_NewFollower.OnServerEvent:connect(function(player1, player2, player1FollowsPlayer2)
|
||||
if not isPlayer(player1) or not isPlayer(player2) or type(player1FollowsPlayer2) ~= "boolean" then
|
||||
return
|
||||
end
|
||||
|
||||
local userId1 = tostring(player1.UserId)
|
||||
local userId2 = tostring(player2.UserId)
|
||||
|
||||
local user1map = PlayerToRelationshipMap[userId1]
|
||||
local user2map = PlayerToRelationshipMap[userId2]
|
||||
|
||||
local sentNotificationsMap = FollowNotificationsBetweenMap[userId1]
|
||||
if sentNotificationsMap then
|
||||
if sentNotificationsMap[userId2] then
|
||||
sentNotificationsMap[userId2] = sentNotificationsMap[userId2] + 1
|
||||
if sentNotificationsMap[userId2] > MAX_FOLLOW_NOTIFICATIONS_BETWEEN then
|
||||
-- This player is likely trying to spam the other player with notifications.
|
||||
-- We won't send any more.
|
||||
return
|
||||
end
|
||||
else
|
||||
sentNotificationsMap[userId2] = 1
|
||||
end
|
||||
end
|
||||
|
||||
if user1map then
|
||||
local relationTable = user1map[userId2]
|
||||
if relationTable then
|
||||
relationTable.IsFollowing = player1FollowsPlayer2
|
||||
relationTable.IsMutual = relationTable.IsFollowing and relationTable.IsFollower
|
||||
|
||||
local delta = {}
|
||||
delta[userId2] = relationTable
|
||||
RemoteEvent_FollowRelationshipChanged:FireClient(player1, delta)
|
||||
-- this should be updated, but current NotificationScript listens to this
|
||||
if player1FollowsPlayer2 then
|
||||
RemoteEvent_NewFollower:FireClient(player2, player1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if user2map then
|
||||
local relationTable = user2map[userId1]
|
||||
if relationTable then
|
||||
relationTable.IsFollower = player1FollowsPlayer2
|
||||
relationTable.IsMutual = relationTable.IsFollowing and relationTable.IsFollower
|
||||
|
||||
local delta = {}
|
||||
delta[userId1] = relationTable
|
||||
RemoteEvent_FollowRelationshipChanged:FireClient(player2, delta)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local function sendPlayerAllGroupDetails(player)
|
||||
for userId, groupDetails in pairs(PlayerToGroupDetailsMap) do
|
||||
RemoteEvent_PlayerGroupDetails:FireClient(player, userId, groupDetails)
|
||||
end
|
||||
end
|
||||
|
||||
local function getPlayerGroupDetails(player)
|
||||
local newGroupDetails = {}
|
||||
for groupKey, groupInfo in pairs(SPECIAL_GROUPS) do
|
||||
if groupInfo.GroupRank ~= nil then
|
||||
local isInGroupSuccess, isInGroupValue = pcall(function() return player:GetRankInGroup(groupInfo.GroupId) >= groupInfo.GroupRank end)
|
||||
newGroupDetails[groupKey] = isInGroupSuccess and isInGroupValue
|
||||
else
|
||||
local isInGroupSuccess, isInGroupValue = pcall(function() return player:IsInGroup(groupInfo.GroupId) end)
|
||||
newGroupDetails[groupKey] = isInGroupSuccess and isInGroupValue
|
||||
end
|
||||
end
|
||||
if player.Parent then
|
||||
local uidStr = tostring(player.UserId)
|
||||
PlayerToGroupDetailsMap[uidStr] = newGroupDetails
|
||||
RemoteEvent_PlayerGroupDetails:FireAllClients(uidStr, newGroupDetails)
|
||||
end
|
||||
end
|
||||
|
||||
local function sendCanChatWith(newPlayer)
|
||||
for _, player in ipairs(Players:GetPlayers()) do
|
||||
local success, canChat = pcall(function()
|
||||
return Chat:CanUsersChatAsync(newPlayer.UserId, player.UserId)
|
||||
end)
|
||||
RemoteEvent_CanChatWith:FireClient(newPlayer, player.UserId, success and canChat)
|
||||
RemoteEvent_CanChatWith:FireClient(player, newPlayer.UserId, success and canChat)
|
||||
end
|
||||
end
|
||||
|
||||
local function sendPlayerAllCanManage(player)
|
||||
for userId, canManage in pairs(PlayerToCanManageMap) do
|
||||
RemoveEvent_NewPlayerCanManageDetails:FireClient(player, userId, canManage)
|
||||
end
|
||||
end
|
||||
|
||||
local function getPlayerCanManage(player)
|
||||
local canManage = false
|
||||
if player.UserId > 0 then
|
||||
local canManageSuccess, canManageResult = pcall(function()
|
||||
local url = string.format("/users/%d/canmanage/%d", player.UserId, game.PlaceId)
|
||||
return HttpRbxApiService:GetAsync(url, Enum.ThrottlingPriority.Default, Enum.HttpRequestType.Default, true)
|
||||
end)
|
||||
if canManageSuccess and type(canManageResult) == "string" then
|
||||
-- API returns: {"Success":BOOLEAN,"CanManage":BOOLEAN}
|
||||
-- Convert from JSON to a table
|
||||
-- pcall in case of invalid JSON
|
||||
local success, result = pcall(function()
|
||||
return HttpService:JSONDecode(canManageResult)
|
||||
end)
|
||||
if success and result.CanManage == true then
|
||||
canManage = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if player.Parent then
|
||||
local uidStr = tostring(player.UserId)
|
||||
PlayerToCanManageMap[uidStr] = canManage
|
||||
RemoveEvent_NewPlayerCanManageDetails:FireAllClients(uidStr, canManage)
|
||||
end
|
||||
end
|
||||
|
||||
local function onPlayerAdded(newPlayer)
|
||||
sendPlayerAllGroupDetails(newPlayer)
|
||||
if newPlayer.UserId > 0 then
|
||||
coroutine.wrap(getPlayerGroupDetails)(newPlayer)
|
||||
end
|
||||
|
||||
sendPlayerAllCanManage(newPlayer)
|
||||
coroutine.wrap(getPlayerCanManage)(newPlayer)
|
||||
|
||||
sendCanChatWith(newPlayer)
|
||||
|
||||
if not game:GetFastFlag("RemoveInGameFollowingServer") then
|
||||
local uid = newPlayer.UserId
|
||||
if uid > 0 then
|
||||
local uidStr = tostring(uid)
|
||||
FollowNotificationsBetweenMap[uidStr] = {}
|
||||
|
||||
local result = getFollowRelationshipsAsync(uid)
|
||||
|
||||
if result then
|
||||
updateAndNotifyClients(result, uidStr, newPlayer)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RemoteEvent_SetPlayerBlockList.OnServerEvent:Connect(function(player, blockList)
|
||||
player:AddToBlockList(blockList)
|
||||
end)
|
||||
|
||||
RemoteEvent_UpdatePlayerBlockList.OnServerEvent:Connect(function(player, userId, block)
|
||||
player:UpdatePlayerBlocked(userId, block)
|
||||
end)
|
||||
|
||||
Players.PlayerAdded:connect(onPlayerAdded)
|
||||
for _,player in pairs(Players:GetPlayers()) do
|
||||
onPlayerAdded(player)
|
||||
end
|
||||
|
||||
Players.PlayerRemoving:connect(function(prevPlayer)
|
||||
local uid = tostring(prevPlayer.UserId)
|
||||
if PlayerToRelationshipMap[uid] then
|
||||
PlayerToRelationshipMap[uid] = nil
|
||||
FollowNotificationsBetweenMap[uid] = nil
|
||||
end
|
||||
if PlayerToGroupDetailsMap[uid] then
|
||||
PlayerToGroupDetailsMap[uid] = nil
|
||||
end
|
||||
if PlayerToCanManageMap[uid] ~= nil then
|
||||
PlayerToCanManageMap[uid] = nil
|
||||
end
|
||||
end)
|
||||
Reference in New Issue
Block a user