Best way to access objects that are stored on the server from the client?

Not really sure how to phrase the title, but to elaborate:

I’m currently working on a game, and while it’s intended to be highly cooperative and PvE, I’m still trying to put into practice some secure coding methods.

I have a library of items currently in ServerScriptService, set up like so:

image

This library used to be in ReplicatedStorage, which made it much easier to access, but to my understanding is unsafe.

  • The Inventory folder houses various information and assets to be used in my spatial grid inventory system
  • The Prop folder houses a model of the item that will be placed in workspace when the item is dropped from an inventory, for example
  • The Tool folder houses the functional tool of the item to be used in gameplay.

Less importantly, the PropSetup script is there to handle automatic welding of the props for each item at runtime.

Inside each prop is a script to handle being clicked on and sending a request to the inventory to be added, with a parameter passing the “Inventory” folder. This is done through a RemoteFunction; Server → Client → Server:

Server:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")

script.Parent.InteractConnect.OnServerEvent:Connect(function(player)
	local success = ReplicatedStorage.InventoryComm.AttemptAddItem:InvokeClient(player, ServerScriptService.ItemLibrary.Items.FAL.Inventory)
	if success then
		script.Parent.Parent:Destroy()
	end
end)

Client:

replicatedStorage.InventoryComm.AttemptAddItem.OnClientInvoke = function(item)
	print(item)
	local ConfigClone = item.Config:Clone()

Client error:

Unfortunately, as I now understand, the client cannot see any objects passed from the server. My old understanding was that you just couldn’t index anything server-only from the client, but that is untrue.

I can get around this by cloning the object from the same server script, parenting it somewhere replicated and then sending that over but I feel like that’s super unlucrative.

I also thought about making two different folders, one placed in ReplicatedStorage with less critical information like inventory information and the prop, and then I thought that if an exploiter had access to the prop, they could “spawn” the prop in and then pick it up so it is placed in the custom inventory, and then equip it to gain access to the tool that way.

What’s the best process here? Did I go the wrong route of hoping to handle a lot of the information on the client (passing the whole “Inventory” folder), rather than only passing what is needed? I’m open to reformat my code, only passing values and whatnot. Thanks in advance.

i think the best way is to use ReplicatedStorage, im sorry but it is how it works, you can’t just ban every single exploiter in roblox.

I don’t believe the viewport stuff should be in server storage at all. It’s unnecessarily making things more complicated.

Also the concern for replicated storage being “unsafe” is rather in terms of asset stealing, and code leaking.

if they are already at the point where they can spawn a tool and have it replicate to the server, then they already have full control over your game.

Your only true option as a dev is to protect your remotes, a.k.a sanity checks.

which in simple terms means make the server validate that the information received from the client makes sense.

Cause otherwise I believe this over-engineering is potentially just gonna slow down your development and not reap any significant rewards

1 Like