Knit: How to replicate tables from a service to the client?

Hello. I tried putting a table in the Client table of a Knit service, but it didn’t replicate. I tried using a function to return the table, but it returned some random Promise stuff. I also tried using RemoteProperties, but I wasn’t able to figure out how to set them properly since I’m using dictionaries. Is there any other method of doing this? Thanks.

One way is you can encode your tables into json using HttpService | Roblox Creator Documentation and then decode them afterwards.

JSONEncode

JSONDecode

I don’t think that will help because the underlying issue is that the table purely isn’t accessible from the client, and I don’t think encoding/decoding will help with that

Yes encode the tables on the server, then using remotes you can send the now encoded json data to the client, which then can be decoded on the client.

I tried doing something similar without decoding it, but it would always just return some random Promise gibberish instead. Will this prevent that?

You used json encode and decode? What data are you sending to the client?

No, I just returned the table without decoding or encoding. I’m sending a dictionary of multiplayer lobbies

does the table contain any objects/instances or just numbers/strings/booleans?

Nope, just strings, numbers, and bools.

Ok so try it with the json encode and decode functions, just converts all of the structure of the dictionary into a string in json form then turns the string back in lua dictionary afterwards.

I’ll try this as soon as I can, I’m not at my PC right now.

Did you try creating a Knit Remote Signal with Knit.CreateSignal() in the Client table?, otherwise be aware that remote events have limitations with mixed tables

I already tried returning the table via functions, it doesn’t really work. I will try the JSONEncode thing though and see if that changes it

also that isn’t “random promise stuff” that is actually the correct value you are trying to obtain, the difference is that instead of yielding the current thread until the value is retrieved from the server, a promise object is created, what you had to do was just

local service = Knit.GetService('yourservice')

service:GetTable():andThen(function(value)
	--value is the table you were trying to obtain
	--everything you wanted to do with the value can be done here
	print(value[1])
end)

I tried this already, it just returned the exact same thing, which was Promise(Saved)
Edit: I’m dumb, I did that on the server side. Lemme try it again

Tried this, it just prints nil.

Can i see your server and local script?

Yeah. These are just snippets since they’re sandwiched in with a lot of other stuff but it’s the core idea of what’s happening.
Client

local Lobbies
LobbyService.GetLobbies():andThen(function(val)
	Lobbies = val[1] -- prints as nil when I try
end)

Server

function LobbyService.Client.GetLobbies()
    return LobbyService.Client.Lobbies -- I'm aware it's still "on the Client" (even though it isn't) but I'll change that once I get it working in the first place
end

Its unusual to me, its there a necessary reason why you are calling all your methods with dots instead of colons?

Also this practice doesn’t seem correct. You say you are aware that since lobbies is in the client table you shouldn’t need to call the function for that same client table, however that client table doesn’t listen for changes, and shouldn’t constantly be changed either. Its main purpose is for sending starting values and objects like RemoteSignals.

Heres a snippet on how to properly do the communication if it serves any help:

--//LobbyService (server)

local Knit = require(game:GetService('ReplicatedStorage').Packages.Knit)

local LobbyService = Knit.CreateService{
	Name = script.Name,
	Client = {}
}


function LobbyService:KnitInit()
	self.Lobbies = {'lobby1','lobby2'} --do whatever here to get your lobbies
end

function LobbyService.Client:GetLobbies()
	return LobbyService.Lobbies
end

function LobbyService:KnitStart()
	print('lobby start')
end

return LobbyService
--//LobbyController(Client)
local Knit = require(game:GetService('ReplicatedStorage').Packages.Knit)

local NewController = Knit.CreateController{
	Name  = script.Name
}

function NewController:KnitInit()
	
end

function NewController:KnitStart()
	print('controller start')
	
	Knit.OnStart():andThen(function()
		local LobbyService = Knit.GetService('LobbyService')
		
		LobbyService:GetLobbies():andThen(function(tabl)
			
			print('GOT VALUE',tabl[1])
			
		end)
		
	end)
end

return NewController

Showcase of it working properly:

1 Like

Thank you so much! And I was calling my functions with dots because I didn’t need the player from them

That makes sense

1 Like