Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Why am I not able to pass a dictionary through RemoteFunction?

According to this Devforum post and this ScriptingHelpers answer, I should be able to pass in a dictionary so long as it is only a dictionary not mixed with an array. I can still pair an array with a dictionary key though. However, when I call my RemoteFunction to get a table of inventory items generated by the server, all the tables are empty.

Server Code:

ReplicatedStorage = game.ReplicatedStorage
PlayerStorageEvents = ReplicatedStorage.PlayerStorageEvents
ServerStorage = game.ServerStorage

PlayerStorageEvents.GetInventory.OnServerInvoke = function(player)
	--Generate the dictionary that will be sent back
	local storage = {
		["Inventory"] = {},
		["Equipment"] = {},
		["ActiveItems"] = {}
	}

	--Get the player's storage
	local playerStorage = ServerStorage.PlayerStorage:FindFirstChild(player.Name)

	--Populate the table with all the elements in these folders
	if playerStorage ~= nil then
		for i,v in pairs(playerStorage.Equipment:GetChildren()) do
			storage["Equipment"][i] = v
		end

		for i,v in pairs(playerStorage.ActiveItems:GetChildren()) do
			storage["ActiveItems"][i] = v
		end

		for i,v in pairs(playerStorage.Inventory:GetChildren()) do
			storage["Inventory"][i] = v
		end
	end

	return storage

end

Yet all these commands:

print(#game.ReplicatedStorage.PlayerStorageEvents.GetInventory:InvokeServer())
print(#game.ReplicatedStorage.PlayerStorageEvents.GetInventory:InvokeServer()["Inventory"])

return 0 and all these commands:

print(game.ReplicatedStorage.PlayerStorageEvents.GetInventory:InvokeServer()["Inventory"][0])

return nil

1 answer

✓ Accepted answer

Unfortunately, because the client has no access to ServerStorage, if the server returns instances that are in there, the client will treat that as nil.

However, there is a workaround. You can try using a table as the storage itself. Here's how it works:

  1. Declare a variable, which will be a table value (or dictionary), as the central inventory storage for all players.
  2. The key (index) to access the values of the table will be the player (object). The value will be similar to the storage variable you declared in line 7.
-- Example. This adds a storage entry to the central storage for use later.
local Players = game:GetService("Players")
local CentralStorage = {}

Players.PlayerAdded:Connect(function(player)
	CentralStorage[player] = { -- player could be any Player.
		["Inventory"] = {},
		["Equipment"] = {},
		["ActiveItems"] = {}
	}
end
  1. To get the inventory of a player, simply return CentralStorage[player], where the player will be the one that is passed as the first argument/parameter as a result of RemoteFunction being invoked.
  2. Since we are using a dictionary, the way we insert the items into this storage will be different. We will use the table.insert() method to add the new items into the right part(s) of the storage.

Here is the code to get a player's inventory.

ReplicatedStorage = game.ReplicatedStorage
PlayerStorageEvents = ReplicatedStorage.PlayerStorageEvents
ServerStorage = game.ServerStorage

local CentralStorage = {} -- Since I do not know what and when the items will be inserted, I will leave this blank for now.
-- Use table.insert(CentralStorage[player][section], item) to add items.

PlayerStorageEvents.GetInventory.OnServerInvoke = function(player)
	return CentralStorage[player] -- Simply return the dictionary returned using the player as the index.
end

I hope this method will work. Remember, you need to change how the items will be inserted if you are ever going to use this. If you have any more problems, feel free to make a comment below. Thanks.

This discussion is preserved as it was. New answers, comments, and votes are closed.