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.
- 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.
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.)
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?
What do you mean by this?
They are looking at the same remote function.
They’re asking how you’ve defined ‘FunctionStorage’ in your local script.
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?
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
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
14:29:15.150 ▶ Stats | Nil nil (x4) - Client - Home:46
It seems it’s still returning nil
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