How to send over models from Server to client?

I want to make a script that takes a player inventory and essentially turns it into a table using strings(model names) Example bellow
image
into this
image
If there are better inventory sorting methods out there that store a lot of values in other values please let me know I’m just trying to come up with ideas on my own at the moment

Edit -
Forgot to say that the inventory system is in ServerStorage to hide it from explotation

1 Like

I haven’t tested this, but it should work.

local folder = -- Path to your folder
local t = {} -- The table

local function insertChildren(inst,tab)
    for _, c in inst:GetChildren() do
        tab[c.Name .. " - " .. c.Value] = {} -- c should be a StringValue as it will hold it's type (Like "Sight - Attachment")
        if #c:GetChildren() > 0 then
            insertChildren(c,tab[c.Name])
        end
    end
end

insertChildren(folder,t)

I’d normally do pretty much OOP to set that up
there’d be a table that stores “items” and each item would have a different class like M4A1 or something more generic like Gun
each class would have a hardcoded schema/fileset to search for, so you’d specifically check for Magazine and store the value of the magazine inside the object


but if you want an unstructured setup similar to yours that converts the instances to a table, I’d have something like this

inventory = {}

storeItem(item)
   itemData = {}
   addField(item, itemData)
   table.insert(inventory, itemData) -- using table.insert in case you have similar items like 2 M4A1s

addField(child, parent)
   fieldData = { child.Value, {} } --[1] is the value assuming it's scalar like "M4A1" or 30; and [2] is for any nested fields like isArmorPiercing
   parent[child.Name] = fieldData --the index in parent is the fieldname, like "name" or "color" or "isArmorPiercing"
   for each child in child
      addField(child, fieldData)

-- example usage
storeItem(game.ServerStorage["On Sling"].M4A1)

and then I’d also store the instances a bit cleaner like

Assault Rifle - a StringValue representing an assault rifle  - name=Assault Rifle, value=M4A1
   Extra - a CFrameValue representing where gun attachments are attached - value=some object CFrame
   Grip - a CFrameValue representing where users' hands attach to - value=some object CFrame
   Magazine - an IntValue representing how much ammo is left - value=the ammo left
      Bullet Type - anything because this is an array and it isnt a scalar value - value=anything
         Armor Piercing - a BoolValue representing if the bullets are armor piercing - value=boolean
         Drop Rate - a NumberValue representing maybe the number of studs a bullet drops by per second of airtime - value=some number like 1

this would result in a table like

inventory = {
   [1] = {
      ["Assault Rifle"] = {
         "M4A1",
         {
            Extra = { CFrame.new(...), {} },
            Grip = { CFrame.new(...), {} },
            Magazine = {
               30,
               {
                  ["Bullet Type"] = {
                     null,
                     {
                        ["Armor Piercing"] = { true, {} },
                        ["Drop Rate"] = { 1, {} }
                     }
                  }
               }
            }
         }
      }
   }
}

you could add a bit more to remove the redundant data and turn {1, {}} to just 1 also


Also note that I prefer doing it with OOP because you’d have less redundancy from not needing to store Grip, Extra, Armor Piercing, Drop Rate for each M4A1. That data that’s shared between each is stored separately only once
I would also strictly use in-code inventory systems and not use Value instances like StringValue and IntValue at all by just storing the table and working directly with it

I don’t see any use case where this method would make sense. If you want to send models from server to client, just copy the Gun and move it to Replicated Storage, then let the client know, “Hey! Your gun is in replicated storage!” And then let the client take it out of there.

1 Like

Yes, this is actually a pretty good idea.

gun.Parent = game.ReplicatedStorage
RE:FireClient(plr)
gun.Parent = game.ServerStorage

Make it a RemoteFunction that the client needs to answer first, this prevents the gun from getting removed before the client could get it.

Doesn’t ReplicatedStorage replicate for all players? The assets that I use are actually rather big (entire cars) and sending it to ReplicatedStorage might lag everyone in the server. Why should the rest receive the asset for nothing?

I only want to send models to the users that require a specific model and I can’t find a way to do that. I’ve tried to insert models directly into a viewport in playerGUI from server but that hasn’t worked. Remote functions/events don’t send models at all.

I think parenting the model to workspace in an obscure position is better? Since the client is not going to “load” it until the player gets close. Am I correct on this? Or does ReplicatedStorage not have the downside I’m imagining…

1 Like

Best method is rather complicated, you have to send the asset as a compiled string, and reconstruct it on the client, this way other clients don’t receive the data, and it doesn’t require extra data being sent through packets on the internet for high ping as a result. Only issue is it gets rather complicated as the models get more and more complex, hence temporary solution is storing the data on the client, and sending a key to access the data on the client to reconstruct it from the ground up, but ultimately less ping and less data being sent over the internet, but also reduces total memory usage on the client. But this is a rather annoying system to set up. So it’s a choice between optimal memory usage versus memory consumption for convenience.

Wait wait wait. Hold on… just a minute…
Send models as a compiled string? You can do that? How do you do that? I would love to do that actually. This compiled string doesn’t have to originate from the game server either does it? I could set up a webserver and use HttpService?