I have been working on a chat GUI recently, but every time the OnServerEvent event fired for a remote event in ReplicatedStorage, it ran the connected function multiple times. Here's the code:
--Local script
local main = script.Parent:WaitForChild("Main")
local container = main:WaitForChild("Container")
local chatbox = main:WaitForChild("ChatBoxContainer"):WaitForChild("ChatBox")
local sendbutton = main:WaitForChild("SendButton")
local chatev = game.ReplicatedStorage:WaitForChild("Chat")
local serverchatev = game.ReplicatedStorage:WaitForChild("Chat")
local adminchatev = game.ReplicatedStorage:WaitForChild("Chat")
local chats = {}
local function isadmin()
return game.Players.LocalPlayer.Name == "AppleBLOXIAN" or game.Players.LocalPlayer.Name == "BlizzardBOY390"
end
local function calculatesize(text)
local chat = Instance.new("TextLabel")
chat.BackgroundTransparency = 1
chat.Size = UDim2.new(1,0,0,25)
chat.Font = Enum.Font.SourceSans
chat.Text = text
chat.TextSize = 25
chat.TextXAlignment = Enum.TextXAlignment.Left
chat.TextYAlignment = Enum.TextYAlignment.Top
if chat.TextBounds.X > 494 then
chat.Size = chat.Size + UDim2.new(0,0,0,(chat.TextBounds.X/494)*25)
end
return chat.Size
end
local function focuslost(e)
if e then
if isadmin() then
adminchatev:FireServer(game.Players.LocalPlayer.Name,chatbox.Text)
chatbox.Text = 'Press "/" or click here to chat'
else
chatev:FireServer(game.Players.LocalPlayer.Name,chatbox.Text)
chatbox.Text = 'Press "/" or click here to chat'
end
end
end
local function onClick()
if isadmin() then
adminchatev:FireServer(game.Players.LocalPlayer.Name,chatbox.Text)
chatbox.Text = 'Press "/" or click here to chat'
else
chatev:FireServer(game.Players.LocalPlayer.Name,chatbox.Text)
chatbox.Text = 'Press "/" or click here to chat'
end
end
local function makechat(plrname,msg)
local chat = Instance.new("TextLabel")
chat.BackgroundTransparency = 1
chat.Size = calculatesize(plrname..": "..msg)
chat.Font = Enum.Font.SourceSans
chat.Text = plrname..": "..msg
chat.TextSize = 25
chat.TextXAlignment = Enum.TextXAlignment.Left
chat.TextYAlignment = Enum.TextYAlignment.Top
chat.Position = (function()
if #chats == 0 then
return UDim2.new(0,0,0,0)
else
return chats[#chats].Position + UDim2.new(0,0,0,chats[#chats].Size.Y.Offset)
end
end)()
chat.Parent = container
container.CanvasSize = container.CanvasSize + UDim2.new(0,0,0,chat.Size.Y.Offset)
container.CanvasPosition = container.CanvasPosition + Vector2.new(0,chat.Size.Y.Offset)
chats[#chats+1] = chat
end
chatbox.FocusLost:connect(focuslost)
sendbutton.MouseButton1Click:connect(onClick)
chatev.OnClientEvent:connect(makechat)
adminchatev.OnClientEvent:connect(makechat)
serverchatev.OnClientEvent:connect(makechat)
game.StarterGui:SetCoreGuiEnabled(Enum.CoreGuiType.Chat,false)
--Server script
local chatev = game.ReplicatedStorage:WaitForChild("Chat")
local serverchatev = game.ReplicatedStorage:WaitForChild("Chat")
local adminchatev = game.ReplicatedStorage:WaitForChild("Chat")
chatev.OnServerEvent:connect(function(plr,plrname,msg)
msg = game:GetService("Chat"):FilterStringForBroadcast(msg,plr)
chatev:FireAllClients(plrname,msg)
end)
adminchatev.OnServerEvent:connect(function(plr,plrname,msg)
adminchatev:FireAllClients(plrname,msg)
end)
game.Players.PlayerAdded:connect(function(plr)
serverchatev:FireServer("Server",plr.Name.." has joined the game.")
end)
game.Players.PlayerRemoving:connect(function(plr)
serverchatev:FireServer("Server",plr.Name.." has left the game.")
end)

1 comment
You could pass a unique id as an argument to the remote, and store it on the server. You can then make sure there are no duplicates by iterating through the array of stored id's. You should only let entries in the array last as long as the message appears on your chat ui; the array could become quite large and inconvenient to iterate through.