Hi! I am creating a team system called packs and I have made a remote function that will open another players team request gui so they can accept it or deny it, but none of the print functions print. Cna someone help me.
Script in ServerScriptService:
local replicatedStorage = game:GetService("ReplicatedStorage")
local RF = replicatedStorage:WaitForChild("OpenPackRequest")
local function openGui(localPlayer, player)
print("ATTEMPTING TO OPEN GUI")
local packRequestGui = player.PlayerGui.PacksGui.PackRequest
packRequestGui.Visible = true
print("GUI OPENED")
packRequestGui.PackInfoText.Text = localPlayer.Name .." invited you to join the pack".. localPlayer.Team.Name ..". Do you accept?"
packRequestGui.NoButton.MouseButton1Click:Connect(function()
packRequestGui.Visible = false
return "No"
end)
packRequestGui.YesButton.MouseButton1Click:Connect(function()
packRequestGui.Visible = false
return "Yes"
end)
wait(10)
packRequestGui.Visible = false
return "No"
end
RF.OnServerInvoke = openGui
LocalScript, a descendant of Player Gui:
PlayerFrameClone.AddToTeam.MouseButton1Click:Connect(function()
if player.PlayerGui.PacksGui.PackRequest.Visible == true then return end
if player.Team == nil then
if plr.Team ~= nil then
local result = RF:InvokeServer(player)
if result == "Yes" then
--Add Player to team (NOTE: plr is the local player and player is the targeted player
end
end
end
end
end)
I’m also assuming for the start of the local script that “PlayerFrameClone” and player AND plr is mentioned. But you also use “player” and then “plr.”
When you are returning “No” or “Yes” from the mousebutton1click events, you are returning it to the connection, and not to the function. You can fix it by doing something like that
packRequestGui.PackInfoText.Text = localPlayer.Name .." invited you to join the pack".. localPlayer.Team.Name ..". Do you accept?"
local returned
packRequestGui.NoButton.MouseButton1Click:Connect(function()
packRequestGui.Visible = false
returned = "No"
end)
packRequestGui.YesButton.MouseButton1Click:Connect(function()
packRequestGui.Visible = false
returned = "Yes"
end)
local t = 0
repeat
t += 1
wait() until t >= 10 or returned
packRequestGui.Visible = false
return returned or "No"
end
It seems like a bad approach, but you can try improving it
OnServerInvoke is a callback, not a a RBXScriptSignal. You can’t call :Connect() on a callback and there is nothing wrong with RF.OnServerInvoke = openGui.
As @Jxl_s has said, you should be using :FireServer and :FireClient instead. The server is no longer able to edit the PlayerGuis of individual clients since filtering enabled was introduced. The server is able to edit PlayerGuis of individual clients, but that doesn’t mean you should do so. GUIs should be handled on the client, never on the server.
Your filtering enabled-compatible code should look something like this:
-- server script --
local replicatedStorage = game:GetService("ReplicatedStorage")
local packRequest = replicatedStorage:WaitForChild("OpenPackRequest")
local packAccept = replicatedStorage:WaitForChild("AcceptPackRequest")
packRequest.OnServerEvent:Connect(function(requestingPlayer, targetPlayer)
-- fire a remote to the targetPlayer to setup their guis, with the requestingPlayer as an argument passed
local response = packAccept:InvokeClient(targetPlayer, requestingPlayer)
-- maybe someone more experienced with remotes can come up with a solution that doens't need InvokeClient, I can't think of any way to not use it in this case
-- (roblox wiki says to avoid using InvokeClient as it can cause issues for the server)
if response == true then
-- change player's team
targetPlayer.Team = requestingPlayer.Team
end
-- fire the remote to the requestingPlayer with a boolean that tells wether or not the pack request to targetPlayer was accepted
packRequest:FireClient(requestingPlayer, targetPlayer, response)
end)
-- local script --
local replicatedStorage = game:GetService("ReplicatedStorage")
local packRequest = replicatedStorage:WaitForChild("OpenPackRequest")
local packAccept = replicatedStorage:WaitForChild("AcceptPackRequest")
local packRequestGui = game.Players.LocalPlayer.PlayerGui.PacksGui.PackRequest
packRequest.OnClientEvent:Connect(function(response, targetPlayer)
if response == true then
-- targetPlayer accepted your pack request!
end
end)
packAccept.OnClientInvoke:Connect(function(requestingPlayer)
print("ATTEMPTING TO OPEN GUI")
packRequestGui.Visible = true
print("GUI OPENED")
-- using string.format is usually better for performance, and I personally think
-- that it looks cleaner than lots .. of .. concatenate .. operators
packRequestGui.PackInfoText.Text = string.format("%s invited you to join the pack %s. Do you accept?", requestingPlayer.Name, requestingPlayer.Team.Name)
-- we have to use a bindable event here since we want to wait for a response
-- if we put the return inside the MouseButton1Click function, it's only going to return the value to the
-- MouseButton1Click function (as @Jxl_s also mentioned), instead of returning the value to the Invoke request
local responseEvent = Instance.new("BindableEvent")
-- you could also use the variable method they suggested, although I wouldn't reccomend using it
-- not a fan of repeat wait() until ... loops (uses wait(), can cause unnesscary yielding)
-- when connecting an event/RBXScriptSignal, it returns an RBXScriptConnection object which can be used to
-- disconnect the function when it isn't needed anymore (very good for preventing memory leaks)
local NoButton = packRequestGui.NoButton.MouseButton1Click:Connect(function()
packRequestGui.Visible = false
responseEvent:Fire(false) -- fire the BindableEvent with the parameter false (declining the pack request)
end)
local YesButton = packRequestGui.YesButton.MouseButton1Click:Connect(function()
packRequestGui.Visible = false
responseEvent:Fire(true) -- fire the BindableEvent with the parameter true (accepting the pack request)
end)
-- using a delay function here to avoid infinitely waiting for a response
-- it essentially allows us to run several lines of code simultaneously,
-- allowing us to create timeouts for yielding functions
delay(10, function()
if responseEvent then -- checks if the responseEvent variable still exists (isn't nil), if not then nothing happens
responseEvent:Fire(false) -- fire the responeEvent with the parameter false, automatically declining the pack request
end
end)
-- bindable events are just like real events, calling :Wait() will yield until the event
-- is fired and returns the arguments passed to it
local response = responseEvent.Event:Wait() -- wait for the event to be fired
responseEvent:Destroy() -- here we call :Destroy() and set responseEvent to nil, after the event has been fired
responseEvent = nil -- in order to have the delay function not do anything to avoid an error, we set the responseEvent variable to nil
-- disconnecting the NoButton and YesButton functions, this is so they don't again fire in the future
-- and cause errors, and to prevent a memory leak from the two unused functions
NoButton:Disconnect()
YesButton:Disconnect()
-- and finally we're done, put a print just for some debugging incase i got
-- anything wrong, and then we return the response to the server (true for pack request accepted, false for declined)
print("RESPONSE:", response)
return response
end)
Did some testing and turns out you’re right, whoops. Edited the post to reflect that. But you should still be handling GUIs on the client instead of the server to reduce load on the server and improve responsiveness for the client.