What is the most efficient way of creating items in a ui shop?

Greetings,

I am creating a ui shop, and i thought this would be a good chance to review my usual approach and see if there is a more efficient approach so I am here to ask for advice
Here is my usual approach

module.items =  {
	["Item"] = {Price = 100, ImageId = "", Rarity = "Common"}
	["Item"] = {Price = 100, ImageId = "", Rarity = "Common"}
	["Item"] = {Price = 100, ImageId = "", Rarity = "Common"}
	["Item"] = {Price = 100, ImageId = "", Rarity = "Common"}
	["Item"] = {Price = 100, ImageId = "", Rarity = "Common"}
}

I would manually list all the items in a dictionary, specifying stuff like their price and the image of the item and so on, and then the gui script would use this info to create a frame for each item

Now i am faced with potentially 100s of items to be listed in the shop and am questioning if this is the best way of doing this?

Any advice would be greatly appreciated, thank you for your time

Theres a simple thing you can do:

for _,v : TextButton in pairs(guiButtons) do
	local connection = function()
		--what ever you check here
		local Tool = ReplicatedStorage:WaitForChild("Tools"):WaitForChild(v.Name):Clone()
		Tool.Parent = Player.Backpack
	end
	
	v.MouseButton1Click:Connect(connection)
end

mmm, are you responding to the wrong post or? I don’t see the connection between your suggestion and my question

When I’m iterating through items, I like to reference the place where they’re stored. For me, that’s in ServerStorage. I’m not sure if that’s an option for you, but it would work like this:

  1. In ServerStorage, create a folder for the shop’s items.
  2. Put those items in it.
  3. For each item, add an Attribute for each bit of shop data. You might want to have Rarity be a number to make it easier to process.

The shop pseudo-code now looks like this. Keep in mind, you’ll need to set up some client-server interactions to let a GUI access server resources. This is just a broad-strokes idea.

for _,v in pairs(ServerStorage.ShopItems:GetChildren()) do
    local price = v:GetAttribute("Price")
    local rarity = v:GetAttribute("Rarity")
    local image_id = v:GetAttribute("ImageId")
    if price==nil or rarity==nil or image_id == nil then
        warn("Missing data for "..v.Name..". Skipping it.")
    else
        --Build your GUI elements here using those references.
    end
end

Upsides:

  • It’s very easy to add new items to the shop. No code editing required for new stuff, just drop it in.
  • If an item has some data missing, it doesn’t crash your code, and it doesn’t get a shop icon, so players can’t buy incomplete stuff.
  • It’s easy to set up the shop GUI. You’ve already got a reference to the item, so just have your code clone it into the player’s inventory when it’s bought.

Downsides:

  • If you’ve got multiple shops that share some, but not all, of their inventory, you’d have to store multiples of some items.
  • If a player is laggy, the shop could be laggy, depending on how you implement, because it’s asking the server what to display.

There are probably better ways of doing this, but that’s my way. Maybe someone will chime in with a better way, and I’ll learn something!

2 Likes

You can’t access ServerStorage or its children from the client [ that’s why this server is great for storing important stuff, to prevent exploiters], so you better use remotes to access the items on the server.

Right. I was just throwing together a quick example, there would be events and server-client logic.

1 Like

Along with @deggy 's suggestion, i would normally put a remote function that would be fired whenever the player ops up the shop gui sending something like the shop’s name through it, so that the server can check if there’s any folder in serverstorage with the same name and show the items that should be shown in a dictionary form

2 Likes

Here is what I usually do -

1.I name each button in the shop in the item’s name.
2.I iterate through all of them, and when someone presses on any of them,I invoke the server, and provide the name as an argument.
3.On the server, I check if the player has enough stats to buy it, check for the item in the items folder and eventually let him buy it from there.

1 Like

Ooh, I like that. Send a numeric ShopID or something to the server, it can look through its folders and respond with a dictionary that corresponds to the shop’s inventory. You could use that to limit player purchases of some items, too - check the player’s level (or other criteria) and just don’t send stuff with a RequiredLevel Attribute that’s too high. Since it’s all server-authoritative, bad-actor clients won’t even be able to see shop items they aren’t supposed to have yet.

2 Likes

Yeah, this is a great way to do that, now you dont need to store your items in replicated storage and fear of exploiters accessing your tools.
[Tho, they might still be able to take players’ tools, but not the tools from server storage]

No this is a efficient way. Because you don’t have to do this:

your method is the most efficient

i would not change it

you could have 10000s of items in the table and luas hash function is very fast so accessing a item inside the table will be almost instant

1 Like

wouldn’t this result in having to “remake” the items each time the player swaps from shop to inventory for example?

well i am already doing this in a sense, the only thing exploiters will find in RS is a bunch of tables with some strings and numbers, all the tools these table reference are in server storage

If your shop is static (items aren’t added or removed during runtime), you can get the shop dictionary once, make the shop based on it, and just refer to it client-side the rest of the time to reduce lag. That won’t work if items are added or removed from the shop while the game runs, though.