I am going to make an Inventory system but I can't even think about the algorithm. I need some suggestions.
This is how I think about it;
- Create an empty Inventory table for the player in SQL when he connects for his first time ** if it isn't his first time then send his inventory table with nets for clientside gui
- On player try to pick an item, start a net to server about it and do checks & if ok then write it to the Inventory table for the player
- Reply with a net from server to the player who picked the item to update his clientside inventory table for GUI
- Do all these communication with nets when player drop/pickup/remove things from/to his inventory.
I don't think my plan is efficient so I need help.
Create a new table per player? That sounds like bad practice to me.
[QUOTE=mdeceiver79;51906517]Create a new table per player? That sounds like bad practice to me.[/QUOTE]
Do you have any other idea? I mean inserting into a big table by the way. Not creating it
Inventory table:
item_uid (unique ref to that inv item)
item_entity (what is it?)
item_player (who is carrying it)
I may be underthinking this but you then need function for
picking stuff up:
check if item can be picked up
check if player is allowed to pick up (arrested, dead, full inv)
remove entity
create new row in inventory table
dropping stuff ( item_uid <int> item you wish to drop )
does that item exist in their inventory ie is item_player = player for item_uid = item_uid
are they allowed to drop?
remove row
create entity
I have never created an inventory addon so there could be better ways of doing it. I'm just saying what comes to my mind.
Firstly, you would need to create a new row per player not a new table as, some what, mentioned above.
You can store the players current inventory on the server by setting a player variable like player.inventory = {}. When ever the player attempts to add something to their inventory, send a net message to the server, do your validity checks, and add it to their inventory table, then send a net message back telling them to update the table on their end too. When you update the players table, you will also have to update the players inventory in the sql table. Which you could do by using tabletojson and storing it in a text field or something.
When the player first connects and you need to send them their inventory, you would run an sql query and set ply.inventory = jsontotable(query data) Then send them a net message with their inventory and update the table variable on the clients side.
[QUOTE=Nick78111;51906571]I have never created an inventory addon so there could be better ways of doing it. I'm just saying what comes to my mind.
Firstly, you would need to create a new row per player not a new table as, some what, mentioned above.
You can store the players current inventory on the server by setting a player variable like player.inventory = {}. When ever the player attempts to add something to their inventory, send a net message to the server, do your validity checks, and add it to their inventory table, then send a net message back telling them to update the table on their end too. When you update the players table, you will also have to update the players inventory in the sql table. Which you could do by using tabletojson and storing it in a text field or something.
When the player first connects and you need to send them their inventory, you would run an sql query and set ply.inventory = jsontotable(query data) Then send them a net message with their inventory and update the table variable on the clients side.[/QUOTE]
I think it should be done as you said. Thanks
[editline]3rd March 2017[/editline]
[QUOTE=mdeceiver79;51906563]Inventory table:
item_uid (unique ref to that inv item)
item_entity (what is it?)
item_player (who is carrying it)
I may be underthinking this but you then need function for
picking stuff up:
check if item can be picked up
check if player is allowed to pick up (arrested, dead, full inv)
remove entity
create new row in inventory table
dropping stuff ( item_uid <int> item you wish to drop )
does that item exist in their inventory ie is item_player = player for item_uid = item_uid
are they allowed to drop?
remove row
create entity[/QUOTE]
Thanks, that makes sense as well.
[QUOTE=Nick78111;51906571]
When the player first connects and you need to send them their inventory, you would run an sql query and set ply.inventory = jsontotable(query data) Then send them a net message with their inventory and update the table variable on the clients side.[/QUOTE]
Storing things as json in sql is bad practice, because if you store it as json and you want to query all players who have a specific item, you wont be able to do that.
He should definitely do what mdeceiver79 said, instead of storing as json.
[QUOTE=Metamist;51916084]Storing things as json in sql is bad practice, because if you store it as json and you want to query all players who have a specific item, you wont be able to do that.
He should definitely do what mdeceiver79 said, instead of storing as json.[/QUOTE]
If he doesn't plan on querying every player that has ever joined his server, I don't really see a problem.
[QUOTE=Nick78111;51916429]If he doesn't plan on querying every player that has ever joined his server, I don't really see a problem.[/QUOTE]
As Metamist says it's bad practice, it also brings issues with concurrency, if you one of your queries uses an outdated json-blob for the players items will go missing or duplicated. You also need to send the entire inventory with each and every edit instead of just saying which item is to be added or removed from the table. In the end it brings a lot of issues.
you can first check if the table exists then check if the player's invetory exists in the table easy just check wat the value returns.
This function creates an inventory table:
[lua]function Player:CreateInventory()
local Inventory = {}
for i=1,32 do
table.insert(Inventory, {Slot = 0, ID = 0, Quantity = 0, Ref = "" })
end
return Inventory
end[/lua]
This sets an item on a designated slot:
[lua]function Player:SetItem(slot, id, quantity)
self.Inventory[slot].Slot = slot
self.Inventory[slot].ID = id
self.Inventory[slot].Quantity = quantity
self.Inventory[slot].Ref = ITEM_DB[tonumber(id)].Ref
end[/lua]
This function gives an item to a player, if he doesn't already have the item in the inventory it puts it to a unassigned slot:
[lua]
function Player:GiveItem(id, quantity)
local inv = self.Inventory
for k, v in pairs(self.Inventory) do
if v.ID == id then
inv[k].Slot = k
inv[k].Quantity = v.Quantity + quantity
break
end
if v.ID == 0 then
inv[k] = {Slot = k, ID = id, Quantity = quantity, Ref = ITEM_DB[id].Ref}
break
end
end
end[/lua]
Removing an item :
[lua]
function Player:RemoveItem(id, quantity)
local inv = self.Inventory
for k, v in pairs(inv) do
if v.ID == id then
local quant = v.Quantity
if (quant - quantity) > 0 then
inv[k].Quantity = v.Quantity - quantity
break
elseif (quant - quantity) <= 0 then
self:ClearSlot(v.Slot)
break
end
break
end
end
end[/lua]
This changes an item with an other slot or another item(Item is in the 2nd slot, you want to put it into the 30th slot):
[lua]function Player:ChangeItemSlot(oldslot, newslot) --If there's an item in the newslot, switch it
local inv = self.Inventory
if newslot > 32 && oldslot > 32 then
print('Slot number is too high')
return
elseif oldslot == newslot then
print("Can't have the same slot number!")
return
elseif oldslot > newslot then
local old = oldslot
oldslot = newslot
newslot = old
end
for k, v in pairs(inv) do
if self:SlotIsEmpty(newslot) then
self:SetItem(newslot, v.ID, v.Quantity)
self:ClearSlot(oldslot)
break
end
if not self:SlotIsEmpty(newslot) then
local oldid, oldquantity = inv[newslot].ID, inv[newslot].Quantity
self:SetItem(newslot, v.ID, v.Quantity)
self:SetItem(oldslot, oldid, oldquantity)
break
end
end
end[/lua]
And some utility functions :
[lua]function Player:SlotIsEmpty(slot)
local inv = self.Inventory
if inv[slot].ID == 0 then
return true
else
return false
end
end
function Player:ClearSlot(slot)
local inv = self.Inventory
for k,v in pairs(inv) do
if v.Slot == slot then
inv[k] = {Slot = 0, ID = 0, Quantity = 0, Ref = ""}
break
end
end
end[/lua]
And finally to create the inventory:
[lua]function GM:PlayerInitialSpawn(ply)
ply.Inventory = ply:CreateInventory()
end[/lua]
I don't recommend that you copy and paste this(It's probably not going to work), but it can give you an idea on how to design an inventory system.
Sorry, you need to Log In to post a reply to this thread.