Remote function always returning nil

Or well, I meant the part on the server with the function

Ah, My mistake there. Here is the full analyticsService code

repeat task.wait() until game:GetService("ReplicatedStorage"):FindFirstChild("FunctionStorage")

---------------------------------- || Variables || ----------------------------------

local field = {} ; self = setmetatable({},field) ; field.__index = field 
local HttpService = game:GetService("HttpService")
local MarketplaceService = game:GetService("MarketplaceService")

---------------------------------- || Methods || ----------------------------------

function field:getInfo()
	local Votes
	local Details
	local Info = MarketplaceService:GetProductInfo(game.PlaceId)


		Votes = HttpService:JSONDecode(HttpService:GetAsync("https://games.roproxy.com/v1/games/"..game.GameId.."/votes"))
		Details = HttpService:JSONDecode(HttpService:GetAsync(`https://games.roproxy.com/v1/games?universeIds={game.GameId}`))

	return {
		["Thumbnail"] = "rbxassetid://".. Info.IconImageAssetId,

		["Name"] = Details.name or "N/A",

		["Description"] = Details.description,

		-- Stats

		["Active"] = Details.playing or "N/A",
		["Visits"] = Details.visits or 0,
		["Favorites"] = Details.favoritedCount or "N/A",


		["Creator"] = Details["creator"],
		["Updated"] = Info.Updated,
		["Created"] = Info.Created,

		-- Votes

		["Likes"] = Votes.upVotes or "N/A",
		["Dislikes"] = Votes.downVotes or "N/A",
	}

end

game:GetService("ReplicatedStorage"):WaitForChild("FunctionStorage"):WaitForChild("Request").OnServerInvoke = function(player,Request)
	warn(player,Request)
	if Request == "Statistics" then
		local Info = field:getInfo()
		print(Info)
		warn("Getting Info!")
		return Info
	end
end

---------------------------------- || RBX Signals || ----------------------------------

return field

If I may ask, why are you doing weird metatable stuff for a static function?

I just like to be able to use : when making functions.

You still can without a metatable

I might be missing it, but 2 things i’d change.

  1. Seperate your function calls and you REALLY need to not code like that…
local ReplicatedStorage = game:getService("ReplicatedStorage")
local FunctionStorage = ReplicatedStorage:WaitForChild("FunctionStorage")
--Create a local function
local function GetInfo(player, Request)
--code
FunctionStorage.Request.OnserverInvoke = GetInfo

2nd, I dont think you are aware of 2 things, number 1 things returned between client and server are automatically switched to a string even if you return a number. You are returning a table and to return a table you need to follow this article:

You can’t just return tables between client and server they have zero knowledge of what was made in that table. But if you insert it into a table and just reutrn that main table you go around the issue, you are returning the table itself as it is defined, and I never have seen that but I am sure it can be done. I would take the much easier route.

2 Likes

Ah, I didn’t know that, well when Phase 2 of this panel comes out I’ll keep that in mind (I’m going to keep it like this for constancy.)

1 Like

I feel like if you are not even getting a print of that first ‘warn’ then its not even calling the function on the server. Are you sure the server and client are both looking at the same remotefunction?

On the server I see you set the path specific …

game:GetService("ReplicatedStorage"):WaitForChild("FunctionStorage"):WaitForChild("Request").OnServerInvoke = function(player,Request)

On the client what path are you using for the remotefunction?

self["Stats"] = FunctionStorage:FindFirstChild("Request"):InvokeServer("Statistics")

where does “FunctionStorage” point to?

1 Like

What do you mean by this?

They are looking at the same remote function.

1 Like

They’re asking how you’ve defined ‘FunctionStorage’ in your local script.

1 Like

In the client code in the first post, you have FunctionStorage:FindFirstChild()…

Where does FunctionStorage point to? Is it a variable holding part of the path?

Ah, I have defined it like this:

local FunctionStorage = game:GetService("ReplicatedStorage"):WaitForChild("FunctionStorage")

Since when did remotes convert everything to strings?

2 Likes

Can you provide the local script?

Here the client side is, please ignore most of these function’s.

repeat task.wait() until game:GetService("ReplicatedStorage"):FindFirstChild("FunctionStorage")

---------------------------------- || Variables || ----------------------------------

local field = {} ; playerStorage = {} ; self = setmetatable({},field) ; field.__index = field 
local Services = require(script.Parent.Parent.Services)
local FunctionStorage = game:GetService("ReplicatedStorage"):WaitForChild("FunctionStorage")
local player = game.Players.LocalPlayer

---------------------------------- || Methods || ----------------------------------

function field:Convert(number)
	local days = math.floor(number / (60 * 60 * 24)) % 7
	local hours = math.floor(number / (60 * 60)) % 24
	local minutes = math.floor(number / 60) % 60
	local seconds = number % 60

	local output = ""

	if days > 0 then
		output = output .. days .. "d "
	end

	if hours > 0 then
		output = output .. hours .. "h "
	end

	if minutes > 0 then
		output = output .. minutes .. "m "
	end

	output = output .. seconds .. "s"

	return output
end


function field:GetInfoAsync()
	self["Services"] =  require(script.Parent.Parent.Services)

	self["Stats"] = FunctionStorage:FindFirstChild("Request"):InvokeServer("Statistics")

	task.wait()

	if self["Stats"] == nil then
		warn("Stats | Nil ", self["Stats"])
		task.wait(0.8)
		if self["Stats"] == nil then
			field:GetInfoAsync()
		end
	end
	
	task.wait()

	self["UI"] = script.Parent.Parent.Parent

	warn(self["Stats"])

	self["UI"].Panel.Pages.Home.Stats.Likes.TextLabel.Text = self["Stats"].Likes
	self["UI"].Panel.Pages.Home.Stats.Players.TextLabel.Text = self["Stats"].Visits
	self["UI"].Panel.Pages.Home.Stats.Uptime.TextLabel.Text = field:Convert(math.floor(workspace.DistributedGameTime))

	task.delay(1,function()
		self:GetInfoAsync()
	end)
end

function field:GlobalChat()
	local GlobalChatService = Services.GlobalChatService
	self["UI"] = script.Parent.Parent.Parent

	self["UI"].Panel.Pages.Home.GlobalChat.Frame.Send.MouseButton1Click:Connect(function()
		if playerStorage[player.UserId].db then if playerStorage[player.UserId].db == true then return end end

		playerStorage[player.UserId].db = true
		warn(self["UI"].Panel.Pages.Home.GlobalChat.Frame.TextBox.Text)
		GlobalChatService:filter(self["UI"].Panel.Pages.Home.GlobalChat.Frame.TextBox.Text,player)	
		task.delay(3,function()
			playerStorage[player.UserId].db = false
		end)			
	end)
end

function field:AdminList()
	local Admins = 	FunctionStorage:FindFirstChild("Request"):InvokeServer({["Dict"] = "Admins"})

	task.wait(.7)
	if Admins == nil then 
		warn("Admins is nil :()")
		task.wait(.8)
		field:AdminList()
	end

	self["UI"] = script.Parent.Parent.Parent

	local Administrators = self["UI"].Panel.Pages.Home.Administrators

	for _,admin in pairs(Admins) do
		local ranks = require(script.Parent.Parent.Parent.Parent.Parent.Ranks)
		if not ranks[admin.Rank] then continue end

		local Clone = Administrators.ScrollingFrame.Template:Clone()

		pcall(function()
			Clone.ImageLabel.Image = game:GetService("Players"):GetUserThumbnailAsync(admin.UserId,Enum.ThumbnailType.HeadShot,Enum.ThumbnailSize.Size352x352)
		end)			

		Clone.TextLabel.Text = admin.Rank
		Clone.You.Text = admin.Username

		Clone.Parent = Administrators.ScrollingFrame
		Clone.Visible = true

		-- Add admin information (join date,name,description,e.c.t)

	end
end

function field:AdminInformationList()
	local Admins = 	FunctionStorage:FindFirstChild("Request"):InvokeServer({["Dict"] = "Admins"})


	self["UI"] = script.Parent.Parent.Parent
	local AdminInfo = self["UI"].Panel.Pages.Home.AdminInfo

	for _,admin in pairs(Admins) do
		local ranks = require(script.Parent.Parent.Parent.Parent.Parent.Ranks)
		if not ranks[admin.Rank] then continue end

		local Clone = AdminInfo.ScrollingFrame.Template:Clone()
		pcall(function()
			Clone.ImageLabel.Image = game:GetService("Players"):GetUserThumbnailAsync(admin.UserId,Enum.ThumbnailType.HeadShot,Enum.ThumbnailSize.Size352x352)
		end)			

		Clone.Rank.Text = admin.Rank
		Clone:FindFirstChild("Name").Text = admin.Username

		Clone.Parent = AdminInfo.ScrollingFrame
		Clone.Visible = true

		-- Add status

	end
end


function field:Search()
	local Commands = FunctionStorage:FindFirstChild("Request"):InvokeServer({["Dict"] = "Commands"})

	local CustomCommandList = Commands[1]
	local CommandList = Commands[2]

	self["UI"] = script.Parent.Parent.Parent.Parent


	self["UI"].Panel.Pages.Home.SearchBar.MouseButton1Click:Connect(function()
		self["PopUp"] = script.Parent.Parent.UI.PopUps:FindFirstChild("Search"):Clone()

		for _,Command in pairs(CommandList) do
			self["Clone"] = self["PopUp"].Main.Container.Commands.Options.Template:Clone()

			self["Clone"].Title.Text = Command.Name
			self["Clone"].Name = Command.Name
			self["Clone"].Parent = self["PopUp"].Main.Container.Commands.Options
			self["Clone"].Visible = true
			playerStorage[player.UserId].SelectedCommand = nil

			self["Clone"].MouseButton1Click:Connect(function()
				playerStorage[player.UserId].SelectedCommand = self["Clone"].Name
			end)

			self["PopUp"].Main.Container.Creator.Create.MouseButton1Click:Connect(function()
				if playerStorage[player.UserId].SelectedCommand == nil then return end

				local selectedCommand = playerStorage[player.UserId].SelectedCommand

				CommandList[selectedCommand].Function(player)

			end)			

		end
	end)
end

---------------------------------- || RBX Signals || ----------------------------------

field:GetInfoAsync()
field:GlobalChat()	
field:AdminList()
field:AdminInformationList()
field:Search()

return field
1 Like

Didn’t Work

I know, I was just doing that for testing. I don’t know why I do that but I do.

I have attempted that here is the code.

repeat task.wait() until game:GetService("ReplicatedStorage"):FindFirstChild("FunctionStorage")

---------------------------------- || Variables || ----------------------------------

local field = {} ; self = setmetatable({},field) ; field.__index = field 
local HttpService = game:GetService("HttpService")
local MarketplaceService = game:GetService("MarketplaceService")
local ReplicatedStorage = game:getService("ReplicatedStorage")
local FunctionStorage = ReplicatedStorage:WaitForChild("FunctionStorage")

---------------------------------- || Methods || ----------------------------------

function field:getInfo(player, Request)
	local Votes
	local Details
	local Info = MarketplaceService:GetProductInfo(game.PlaceId)


	Votes = HttpService:JSONDecode(HttpService:GetAsync("https://games.roproxy.com/v1/games/"..game.GameId.."/votes"))
	Details = HttpService:JSONDecode(HttpService:GetAsync(`https://games.roproxy.com/v1/games?universeIds={game.GameId}`))

	return {
		["Thumbnail"] = "rbxassetid://".. Info.IconImageAssetId,

		["Name"] = Details.name or "N/A",

		["Description"] = Details.description,

		-- Stats

		["Active"] = Details.playing or "N/A",
		["Visits"] = Details.visits or 0,
		["Favorites"] = Details.favoritedCount or "N/A",


		["Creator"] = Details["creator"],
		["Updated"] = Info.Updated,
		["Created"] = Info.Created,

		-- Votes

		["Likes"] = Votes.upVotes or "N/A",
		["Dislikes"] = Votes.downVotes or "N/A",
	}

end

FunctionStorage.Request.OnserverInvoke = field:getInfo()

---------------------------------- || RBX Signals || ----------------------------------

return field
1 Like

14:29:15.150 ▶ Stats | Nil nil (x4) - Client - Home:46

It seems it’s still returning nil :pensive:

Slight correction, when passing tables to the client, you need to change it tostring(data) if you are iterating through a table, or else it will return something unwanted. I found this out when doing MonsterDevz tutorial on clicker simulator. It causes errors as the way client and servers talk it will automatically change the way the client recieved that information unless you type tostring(data)

Could you send the link to that video? (The one you found this out from if possible.)

I’ve always been able to pass tables normally, unless it’s a metatable