Help with getting on the right tracks in advanced item ID storing, equipping, removing and so on

Hello, I’ve been working on a module that can give and remove items from your inventory, however, I have no idea how to implement this to a datastore, neither do I know how to let’s say equip a duplicate item that I have in my inventory, how does the server know which one to pick?

Can anyone please help me get on the right tracks in saving item id’s in datastore, equipping the right itemID that was selected if there is multiple itemID’s with the same name…

Lets say I have a table with all the playersInformation in my game:

local playerData = {
    ["CraftDualMine"] = {
        Items = {
            ['2'] = {
                 Level = 0,
                 Enchantments = nil
            },
            ['2'] = {
                 Level = 1,
                 Enchantments = nil
            }
        }
    }
}

If I would want to remove the right ID “2” from the player’s inventory, how can I achieve that if I only want to delete that one. How can I achieve that??

Simplified: Can someone please get me on the right tracks of advanced item ID storing, that you can equip, remove, add and so on.

3 Likes

The way I’ve handled saving items for my games has been to save it as a list of IDs. For example, if they have items 1 and 3, then the save would be {1, 3} which can be loaded and added to their inventory when they join again.

Then everything usually works from there - if you remove an ID from the table, it removes that item; if you add it, it adds; etc.
Only thing is it doesn’t work with duplicates - how does that work in your game? I’ve never had a point where I needed duplicate IDs in inventory.

1 Like

I didn’t mean duplicating ID’S in that way (my fault of not mentioning it properly)
I meant that it work with duplicate ID’S
Let’s say this is a table

local playerData = {
    ["CraftDualMine"] = {
        Items = {
            ['2'] = {
                 Level = 0,
                 Enchantments = nil
            },
            ['2'] = {
                 Level = 1,
                 Enchantments = nil
            }
        }
    }
}

What if I have two of those, how can I properly equip the right one?

1 Like

I think in that case the best option would be to base it off of index (you’d have to keep that in mind while you deal with UI & whatever else is involved).

Basically, what I would probably break it down into would be:


local playerData = {
    ["CraftDualMine"] = {
        Items = {
            ['2'] = {
                {
                     Level = 0,
                     Enchantments = nil
                },
                {
                      Level = 0,
                     Enchantments = nil
                 }
            }
        }
    }
}

From there, you’d go 2[1] or 2[2] to distinguish them.

As for saving that into a data store, the simplest thing would be JSON encoding. Then you can save & load the JSON data directly from there.

Edit: I’m also wondering about the ‘2’ here. what is CraftDualMine and what is the 2 for? My assumption is 2 relates to a specific item and CraftDualMine is an item class that contains these items. Let me know if it’s different as you may need another answer for this

1 Like

CraftDualMine is the player, the number 2 is an item ID, and item is a class containing all the items that the player has.

1 Like

It’s best practice to organize your storage system in the same way you would access it in your game. or at least I would think so… So you could have some kind of inventory space id and store the item id with the item’s data itself:

local playerData = {
	-- user specific
	["CraftDualMine"] = {
		-- category of storage
		Items = {
			-- inventory slot
			[1] = {
				-- item data
				ItemId = '2',
				Level = 0,
				Enchantments = {}
			},
			-- [2] = {...}, ...
		}	
	}
}
1 Like

Yeah, that looks clean, but it still doesn’t solve my problem that’s equipping/removing an item with the same ID as another item (in this case the user had 2 of the same sword)

1 Like

That is a smart layout, but how can the script determine if I clicked on 2[1] or 2[2]?

1 Like
local playerData = {
	-- user specific
	["CraftDualMine"] = {
		-- category of storage
		Items = {
			-- inventory slot
			[1] = {
				-- item data
				ItemId = '2',
				Level = 0,
				Enchantments = {}
			},
			-- [2] = {...}, ...
		}

        EquipSlot = 1;
	}
}
2 Likes

I don’t understand the context.

Shouldn’t swords of the same type be in different slots anyways. Let’s say each sword had different enchantments. You can’t really differentiate between the two. It’s best to have swords as unstackable items that take up different slots. Then you can save which slot has the equipped item.

The script should select the first entry. If you want players to be able to choose what item out of the stack, I’d recommend adding a sub-gui that lets players choose either the first entry, second entry, etc. although this could get a bit big depending on how big you let them stack it.

Also I agree with Nezuo; weapons should always take up a unique slot in the inventory.

Yeah, that’s what I’m trying to achieve, but how can I save which slot that has the equipped item? I’m going to try something out and see if it works.

In the code I previously sent, it has another value in the player’s data. EquipSlot… This would be set to the index of the currently equipped weapon in the data.

local EquippedWeapon = Data.Items[Data.EquipSlot]

This might be of use

You can use this to create unique ids for items in your inventory.
For your case:

local httpService = game:GetService("HttpService")
local playerData = {
	["CraftDualMine"] = {
		Items = {
			[httpService:GenerateGUID(false)] = {
				ItemId = '2',
				Level = 0,
				Enchantments = {}
			},
		}
	}
}

This helps you know which item to equip based on the id, while also keeping the itemid.

3 Likes

I was thinking about doing this before, I just didn’t understand how I could use it for my inventory GUI…

You just fetch for the item by having a function to grab an item passing the id. Another way of doing it is instead of storing id, store the name of the item instead. This is just storing the item, but for the inventory, use a remote function returning the players data and just loop through it.

Hey there, CraftDualMine.

There’s a really neat table structure called Json!

In summary, Json can convert a table in a string and the back to a table again.
As you know, Datastores can store Strings!

Heres some code to help you out:

local playerData = {
 ["CraftDualMine"] = {
        Items = {
            ['2'] = {
                 Level = 0,
                 Enchantments = nil
            },
            ['2'] = {
                 Level = 1,
                 Enchantments = nil
            }
        }
    }
}

local jsonString = game:GetService("HttpService"):JSONDecode(playerData)
print(jsonString)

-- Now lets convert it back to a Table

local JsonTable = game:GetService("HttpService"):JSONEncode(jsonString)

Json is so awesome! It also works with other languages too such as C#, and Java.
More about JSON! JSON Introduction

Happy coding!
Best regards,

  • DrBaja
1 Like

maybe not be the best method but this is what I do

I generate a unique serial everytime I add a item to the players inventory and use it as a Key and have the ItemID as a value

the layout ends up something like

[523424] = {ID = 1}

I use this ID method because I can make changes to an item’s info in the item table and all inventory items will use the new info

Datastores can save tables btw

	function PlayerData:ItemSerialSearch(Serial)
		
		for Key, Item in pairs(self.Stats.Inventory) do

			if Key == Serial then
				return Key, Item
			end
		end
	
	end
	-- loops through inventory and returns a item with the Serial provided if it exists
	
	function PlayerData:GenerateSerial()
		local Serial = false
		while not Serial do
			
			local function RandomSerial()
				local RandomNum = math.random(1, 999999)
				local Exists = false
				
				if self:ItemSerialSearch(RandomNum) then
					Exists = true
				end
				
				if not Exists then Serial = RandomNum end
			end
			
		RandomSerial()		
		wait()
		end
		
		return Serial
	end
	-- generates a unique serial for a item
	
	function PlayerData:AddItem(ID)
		local Item = Info:GetItem(ID)
		if Item then
			self.Stats.Inventory[self:GenerateSerial()] = {ID = ID}
		end
	end
	-- adds a item to the inventory
	
	function PlayerData:RemoveItem(Serial)
		local Key = self:ItemSerialSearch(Serial)
		
		if Key then
			self.Stats.Inventory[Key] = nil
		end
	end	

I then have a table for all item info with IDs

function Info:GetItem(ID)
	for _, Item in pairs(self.Items) do
		local ItemCheck = Item.ID == ID
		if ItemCheck then
			return Item
		end		
	end
end

Info.Items = {
	
	{
	ID = 1,
	Name = "Staff",
	CritChance = 7,
	Type = "Staff",
	MinDMG = 6,
	MaxDMG = 11,
	Price = 350,
	Model = ItemFolder:WaitForChild("Staff")
	}
				
}
1 Like

You can JSON an array or a dictionary and save it to a DataStore but I don’t see the point of doing that. Not only do DataStores accept raw tables as save values but the value you pass to DataStores is transformed into a JSON-like format in the backend.

1 Like