OnClientEvent only partially/sometimes works

Works only sometimes, one or both client scripts don’t work 70% of the time. I’m trying to do a thing where when the saved data loads (or if theres no data its just an empty table), it sends that to the client, I’m pretty sure the script fires FireClient() properly, but not OnClientEvent, somehow, or table.find randomly breaks (i did print statements) No errors in output. I made this topic late so don’t expect an immediate answer. I see no reason why it sometimes doesn’t work???

The 2 client scripts

ShopSystem:

local player = game:GetService("Players").LocalPlayer

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Emotes = script.Parent.Parent.Parent.Parent.Emotes.Frame.Emotes

for _, item in ipairs(script.Parent:GetChildren()) do
	if item:IsA("Frame") and item.Name == "item" then
		item.ItemName.Text = item.emoteName.Value
		item.ItemPrice.Text = item.price.Value.." Classic Coins"

		ReplicatedStorage.ShopSystem.ShopInfo.OnClientEvent:Connect(function(BoughtItems)
			if table.find(BoughtItems, item.emoteName.Value) then
				item.Loading.Visible = false
				item.Bought.Visible = true
			else
				item.Loading.Visible = false
				item.Buy.Visible = true
			end
		end)
		
		item.Buy.MouseButton1Click:Connect(function()
			if player.leaderstats["Classic Coins"].Value < item.price.Value then
				item.Buy.Text = "Not enough coins!"
				task.wait(1)
				item.Buy.Text = "Buy"
			else
				ReplicatedStorage.ShopSystem.BuyItem:FireServer(item.emoteName.Value, item.price.Value)
				item.Buy.Visible = false
				item.Bought.Visible = true
				item.Bought.Text = "Successfully bought emote!"
				for _, emoteItem in ipairs(Emotes:GetChildren()) do
					if emoteItem:IsA("Frame") and emoteItem.emoteName.Value == item.emoteName.Value then
						emoteItem.Visible = true
						Emotes.NoEmotes.Visible = false
					end
				end
				task.wait(1)
				item.Bought.Text = "Bought"
			end
		end)
	end
end

EmoteSystem:

local player = game:GetService("Players").LocalPlayer

local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")
local animation = script:WaitForChild("Animation")

local ReplicatedStorage = game:GetService("ReplicatedStorage")

for _, item in ipairs(script.Parent:GetChildren()) do
	if item:IsA("Frame") and item.Name == "item" then
		item.ItemName.Text = item.emoteName.Value

		ReplicatedStorage.ShopSystem.ShopInfo.OnClientEvent:Connect(function(BoughtItems)
			if table.find(BoughtItems, item.emoteName.Value) then
				item.Parent.NoEmotes.Visible = false
				item.Visible = true
			end
		end)
		
		item.Equip.MouseButton1Click:Connect(function()
			script.Parent.Parent.Visible = false
			animation.AnimationId = "rbxassetid://"..item.emoteId.Value
			local animationtrack = animator:LoadAnimation(animation)
			animationtrack.Looped = false
			animationtrack:Play()
		end)
	end
end
Server script
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("ShopSystem")

local Players = game:GetService("Players")

local BuyItem = game:GetService("ReplicatedStorage").ShopSystem.BuyItem
local ShopInfo = game:GetService("ReplicatedStorage").ShopSystem.ShopInfo

local BoughtItems = {}

local function SavePlayerData(player)
	local success, errormessage = pcall(function()
		DataStore:SetAsync(player.UserId, BoughtItems[player.UserId])
	end)

	if not success then
		warn("Error while saving data for "..player.UserId..": "..errormessage)
	end
end

Players.PlayerAdded:Connect(function(player)
	local success, data = pcall(function()
		return DataStore:GetAsync(player.UserId)
	end)
	
	if success then
		if data then
			BoughtItems[player.UserId] = data
			ShopInfo:FireClient(player, data)
		else
			BoughtItems[player.UserId] = {}
			ShopInfo:FireClient(player, {})
		end
	else
		warn("Error while getting data for "..player.UserId.."!")
		BoughtItems[player.UserId] = {}
		ShopInfo:FireClient(player, {})
	end
end)

Players.PlayerRemoving:Connect(function(player)
	SavePlayerData(player)
	task.wait()
	BoughtItems[player.UserId] = nil
end)

BuyItem.OnServerEvent:Connect(function(player, emoteName, emotePrice)
	local Leaderstats = player:WaitForChild("leaderstats")
	local ClassicCoins = Leaderstats:FindFirstChild("Classic Coins")
	
	if ClassicCoins and ClassicCoins.Value >= emotePrice then
		ClassicCoins.Value = ClassicCoins.Value - emotePrice

		if not BoughtItems[player.UserId] then
			BoughtItems[player.UserId] = {}
		end
		
		table.insert(BoughtItems[player.UserId], emoteName)
	
		SavePlayerData(player)
	else
		warn(player.Name.." doesn't have enough Classic Coins to buy "..emoteName)
	end
end)

If you’re wondering in the scripts why I checked if the player has enough coins twice, it’s just to double check

Behaviors

Expected behavior: (it should say Buy for items I didn’t buy, and Bought for items I bought)


(image below is pretty self-explanatory)

Actual behavior in-game: (its stuck on loading forever, except bought? or “Buy” if I didn’t buy it, and it’s just the first item??)


(it shouldn’t say that I have no emotes if I have bought any emotes)

1 Like

In ShopSystem, try placing the ShopInfo.OnClientEvent outside the for loop and assign the value of the data in a seperate variable.

local player = game:GetService("Players").LocalPlayer

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Emotes = script.Parent.Parent.Parent.Parent.Emotes.Frame.Emotes

local Data
ReplicatedStorage.ShopSystem.ShopInfo.OnClientEvent:Connect(function(BoughtItems)
    Data = BoughtItems
end)

repeat wait() until player:GetAttribute("DataLoaded") -- Wait for the OnClientEvent to fire

for _, item in ipairs(script.Parent:GetChildren()) do
	if item:IsA("Frame") and item.Name == "item" then
		item.ItemName.Text = item.emoteName.Value
		item.ItemPrice.Text = item.price.Value.." Classic Coins"

			if table.find(Data, item.emoteName.Value) then
				item.Loading.Visible = false
				item.Bought.Visible = true
			else
				item.Loading.Visible = false
				item.Buy.Visible = true
			end

Also, at the end of the PlayerAdded event in the server script, add

player:SetAttribute("DataLoaded",true)

in order to make sure that the OnClientEvent has ran brefore entering the for loop.

Try the same for the EmoteSystem.

Thank you for your help, ShopSystem works, but now I sometimes get this error in EmotesSystem:

invalid argument #1 to 'find' (table expected, got nil)

Script:

local player = game:GetService("Players").LocalPlayer

local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
local animator = humanoid:WaitForChild("Animator")
local animation = script:WaitForChild("Animation")

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Data

ReplicatedStorage.ShopSystem.ShopInfo.OnClientEvent:Connect(function(BoughtItems)
	Data = BoughtItems
end)

repeat wait() until player:GetAttribute("DataLoaded")

for _, item in ipairs(script.Parent:GetChildren()) do
	if item:IsA("Frame") and item.Name == "item" then
		item.ItemName.Text = item.emoteName.Value

		if table.find(Data, item.emoteName.Value) then
			item.Parent.NoEmotes.Visible = false
			item.Visible = true
		end

		item.Equip.MouseButton1Click:Connect(function()
			script.Parent.Parent.Visible = false
			animation.AnimationId = "rbxassetid://"..item.emoteId.Value
			local animationtrack = animator:LoadAnimation(animation)
			animationtrack.Looped = false
			animationtrack:Play()
		end)
	end
end

Update: Added print statement and it sometimes doesn’t print, so must be OnClientEvent again, for EmoteSystem.

ReplicatedStorage.ShopSystem.ShopInfo.OnClientEvent:Connect(function(BoughtItems)
	print("OnClientEvent happened")
	Data = BoughtItems
end)

Try replacing
repeat wait() until plr:GetAttribute(DataLoaded)
with
repeat wait() until Data

Sorry for the late reply :slight_smile:

It’s alright, at least you replied.

A bit better but it still sometimes doesn’t work, so I just used seperate remote events, and it somehow works perfectly.

1 Like

That’s good to hear, glad to help atleast a bit :smiley:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.