14 Replies - 797 Views - Last Post: 12 June 2017 - 01:15 PM Rate Topic: -----

#1 Splashsky  Icon User is offline

  • D.I.C Regular

Reputation: 8
  • View blog
  • Posts: 284
  • Joined: 25-August 13

Best Way to Handle Player Inventory?

Posted 11 June 2017 - 06:20 PM

Hey guys! I've got a simple question about a system I'm trying to build for my simple game.

Background on the Game
An HTML5/PHP/AJAX multi-user-dungeon using primarily text and images on dynamic web pages as their interactions with the game world. Designed to hopefully be moved into Electron, where I can port it to all platforms as a native desktop app, but at the moment it simply stands as a tech demo and a learning project. Each item can have a quality value (Poor to Excellent) which can change their base stats by a margin, as well as the chance to be upgraded for an amount statically proportional to the item's stats.

The Issue
Before I get started creating the database structures for my game, there's been one thing that's bugged me for a very long time; player inventories. The thing about them is how to manage them appropriately, especially when said items may have unique properties (an upgrade to a base stat) that are separate from the base stats of said item. I've had trouble figuring out the best way to assign a player an inventory with a limited number of slots, and fill those slots with the potentially unique items they pick up.

The Environment
I want to keep this as MySQL as possible. Maybe mix in some MongoDB (maybe?) or some text-files or JSON/XML files to contain all the information for base items and base creatures and the like. I'm doing the server-side scripting all through PHP, using PHP 7.1+.

The Idea
Okay, so this is my simplistic idea of how to go about this. (column names do not reflect what I intend to name the columns 100%)
The Player Table (contains player data vs user data like usernames and passwords)
- pID (PK), uID (FK to user table entry), ... other things like attack, defense, hp/maxhp, etc
The Item Table
- iID (PK), ... things like effects and base stats and item type
The Inventory Table
- invenID (PK), pID (FK to player table entry), slotsFilled, maxSlots
The User Items Table
- uiID (PK), invenID (FK to inventory table entry), ... things like quality of item, upgrade levels, transferable status, etc

So, my goal here is to ask for y'alls brains in figuring out a solution/idea/feedback for what I'm trying to accomplish here. c:

Is This A Good Question/Topic? 0
  • +

Replies To: Best Way to Handle Player Inventory?

#2 modi123_1  Icon User is offline

  • Suitor #2
  • member icon



Reputation: 13483
  • View blog
  • Posts: 53,820
  • Joined: 12-June 08

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 06:45 AM

Seems reasonable. Maybe add some 'date added' to the inventory table.. and if everyone has the same volume of inventory that could either be baked into the code or that value could be stored on the 'player table' if, when ever, that could change. Like TF2's expanding backpack.
Was This Post Helpful? 0
  • +
  • -

#3 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon


Reputation: 6979
  • View blog
  • Posts: 14,598
  • Joined: 16-October 07

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 07:44 AM

Well, you need to figure out how you're going to model your objects before you can deal with a player inventory.

For games, I like the think of every object as existing somewhere. Even if that somewhere is limbo. This works well in a text adventure type thing where the objects need to be all setup and then found or moved. However, it's still applicable to something with dynamic loot.

Ultimately, you create a thing at a location and then, in game, you can move the location. This really helps from dropping stuff and even if you want to destroy, you have trash as a location. In order for this to work, your player must also be considered a location. Thus, everything at location player is in their inventory.

Now, rather than think location, think container. Things are inside things, even if the things they're inside are towns, houses, rooms, etc.

You have the idea of enhancements, upgrades, etc? What if an inventory object is also a container? This can get confusing, but it does make things wonderfully flat. Keeping in mind that a thing must only exist in one place at a time will save you a lot of head scratching. That's not to saw you can't have multiple instances of things, just that each instance is somewhere.
Was This Post Helpful? 0
  • +
  • -

#4 Splashsky  Icon User is offline

  • D.I.C Regular

Reputation: 8
  • View blog
  • Posts: 284
  • Joined: 25-August 13

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 08:07 AM

Thankfully, nothing as complicated as having containers within the inventory! It's basically one inventory that starts at 12 slots and can be expanded over time via upgrades, so the only container is the inventory and possibly guild banks (but that's along ways off). The inventory essentially comes down to a glorified list of items with fancy images to represent what's in their inventory.

Basically this:
Posted Image
Was This Post Helpful? 0
  • +
  • -

#5 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon


Reputation: 6979
  • View blog
  • Posts: 14,598
  • Joined: 16-October 07

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 09:14 AM

Looks like you already have two inventories. One, what the player has on them. Two, what the player is actually wearing. Along with a business game rule that two items of the same type may not be worn at the same time. Or maybe slot constraints?

Or perhaps you logically have 13 inventories. The player's self and 12 others with a capacity of one that can only hold a specific item type.

So:
Location:
0 Limbo
1 Player
2 Chest
3 Head

Item:
1 0 Mail Halburk
2 1 Hide Halburk
3 1 Studded Leather Lorica 
4 1 Studded Leather Lorica 
5 0 Studded Leather Lorica 
6 2 Steel Breastplate



Or, maybe:
Location:
0 Limbo 0
1 World 0
2 Rivendell 1
3 Player 2
4 Inventory 3
5 Player Slots 3
6 Chest 5
5 Head 5

Item:
1 0 Mail Halburk
2 4 Hide Halburk
3 4 Studded Leather Lorica 
4 4 Studded Leather Lorica 
5 0 Studded Leather Lorica 
6 6 Steel Breastplate



Now, each player in the game is their own location and all items belonging to that player get grouped under them. More, every critter, npc, whatever, as has its own collection of things.

Regardless of what you do, 12 static slots is NOT the way to go. It's particularly not a database way to go. Don't do this:
PlayerId Name Slot1 Slot2 Slot3 Slot4 Slot5 Slot6
     100 Bob    341  null  null   231  null  null



Do this:
PlayerId Name
     101 Alice

PlayerId Slot ItemId
101         1    341
101         4    231



Hope this helps.
Was This Post Helpful? 0
  • +
  • -

#6 modi123_1  Icon User is offline

  • Suitor #2
  • member icon



Reputation: 13483
  • View blog
  • Posts: 53,820
  • Joined: 12-June 08

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 09:18 AM

I am not following how 13 inventories work into it all..
Was This Post Helpful? 0
  • +
  • -

#7 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon


Reputation: 6979
  • View blog
  • Posts: 14,598
  • Joined: 16-October 07

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 09:49 AM

View Postmodi123_1, on 12 June 2017 - 11:18 AM, said:

I am not following how 13 inventories work into it all..


An inventory being a container for stuff.

Hmm... looking back on this, it looks like the inventory has 12 total slots. I assumed the 12 slots where equipment slots. So, yes, that was confusing of me: sorry. Now, how the hell do you they equip things?

Note, armour can take up to any number of slots: 5 per arm (gauntlet, wrist, elbow, upper arm, shoulder), 4 per leg (thigh, knee, shin, foot), 6 on the torso (head, face, jaw, neck, chest, codpeice). And, of course, in magic game land you have rings, necklaces, rabbit feet, etc.
Was This Post Helpful? 0
  • +
  • -

#8 modi123_1  Icon User is offline

  • Suitor #2
  • member icon



Reputation: 13483
  • View blog
  • Posts: 53,820
  • Joined: 12-June 08

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 09:56 AM

Seems to be way more nuanced in armor than any typical game... but so it goes.
Was This Post Helpful? 0
  • +
  • -

#9 Splashsky  Icon User is offline

  • D.I.C Regular

Reputation: 8
  • View blog
  • Posts: 284
  • Joined: 25-August 13

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 10:06 AM

as it goes, they have 9 "equipped" slots, and anywhere from 12 to 100s of slots in their inventory/backpack. It goes helmet, torso, legs, gloves, main hand and off hand, rune and ring and necklace. In order to equip an item, they click on it from their inventory page and it assigns itself to the appropriate place and swaps places with the old piece of equipment. It is no longer considered to be in their inventory when it's equipped.

This post has been edited by iLiTH: 12 June 2017 - 10:40 AM

Was This Post Helpful? 0
  • +
  • -

#10 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon


Reputation: 6979
  • View blog
  • Posts: 14,598
  • Joined: 16-October 07

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 10:38 AM

Cool. I'm currently addicted to Skyrim. Their slots are basically head, necklace, body, bracers/gauntlets, feet, and only one ring. With a weapon on shield in either hand. Curiously, the concept of off hand is not in play.

Sorry if I was confusing or overly technical. However, I can warn you that these kind of things get far more complex than you expect far more quickly than you might. Thinking "data driven" can save you from some of it. If you can store your logic in your database and have no special exceptions in code, you'll ultimately be happier.

This post has been edited by baavgai: 12 June 2017 - 10:40 AM

Was This Post Helpful? 0
  • +
  • -

#11 modi123_1  Icon User is offline

  • Suitor #2
  • member icon



Reputation: 13483
  • View blog
  • Posts: 53,820
  • Joined: 12-June 08

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 10:46 AM

Oh Skyrim.. I remember putting a crap ton of time into that one. So much that I killed everything evil, explored everywhere (as in combed the landscapes for interesting things), dominated all the guilds, and finally went off to finish the game only to find the world's folk were not appropriately appreciative of what I did.. so I set off to cleanse those folk. Hahaha..
Was This Post Helpful? 0
  • +
  • -

#12 jon.kiparsky  Icon User is offline

  • Chinga la migra
  • member icon


Reputation: 10681
  • View blog
  • Posts: 18,289
  • Joined: 19-March 11

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 11:37 AM

Putting the armor discussion aside for a moment to simplify, I think the idea of a nested "Container" hierarchy is the right one. Things which are Containers in a game like Zork would include the player's inventory, any room, a cabinet or chest located in a room (a fixed container, you can't carry it around), a sack or a bag (containers which can be carried), the inventory of other non-player characters, and objects which surprisingly turn out to contain other objects (for example, the jeweled egg)
The tricky bit is going to be the business logic restricting what objects can go in what containers - for example, you don't want to put a sea chest into a lunchbag. That requires you to model in some way the commonsense (ie, difficult) notion of volume. You'll have to think about how much verisimilitude you require - for example, you can put an egg into a lunchbag, and you can probably put a dozen eggs into a lunchbag, but you probably can't put a gross of eggs into a lunchbag. Most zorkalikes worry about volume up to "you can't put the elephant into the mason jar" but once you've got that far, they're done. You can put as many things in the sack as you have things, as long as each thing fits in on its own you're fine.



Now, returning to the armor issue, it seems to me that your easiest solution to this is to have Wearable items. Each Wearable has a type, and you have business logic that says you can only wear one helmet at a time, but you can wear as many rings as you have fingers, and so forth. This allows the act of Wearing an item to be a lot simpler, and it also helps you distinguish between a helmet that you're wearing and one that you're carrying. It's likely that in the end you'll share some logic between wearing and carrying, since there will be some similarities there, but I think it's easiest to think of them as separate while you're thinking about requirements and design.
Was This Post Helpful? 0
  • +
  • -

#13 Splashsky  Icon User is offline

  • D.I.C Regular

Reputation: 8
  • View blog
  • Posts: 284
  • Joined: 25-August 13

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 12:44 PM

Okay, so I've got this down conceptually! The thing I'm curious about now is how to build the MySQL DB structure for all of this.
Was This Post Helpful? 0
  • +
  • -

#14 jon.kiparsky  Icon User is offline

  • Chinga la migra
  • member icon


Reputation: 10681
  • View blog
  • Posts: 18,289
  • Joined: 19-March 11

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 01:09 PM

Yeah... about that...
I personally would really want to see you using some sort of ORM for this. Basically, the reasoning is this: good engineering practice is going to require that you isolate your SQL from the language in which you're actually executing. You don't want to be writing code that generates strings that become other code - that's just a really bad place to be. So in order to get this, you're going to either invent an ORM, or you're going to use one that already exists, and it's much better, in general, to use stuff that already exists.

You say you want to do this in PHP - god knows why, but I suppose you have your reasons - so I can't help you figure out what tool you want to use here, but find something that allows you treat the DB as a consequence of your models*, and your life will be much better.
If no such tool exists for your language of choice, choose another language.


* what this means is, you create a Container class, and you define some fields on that class, and the ORM reads this class and turns it into a database table with the appropriate columns, and then provides methods allowing you to express the CRUD instructions that you are interested in performing as methods on that class, not as hand-written or generated SQL.
Was This Post Helpful? 0
  • +
  • -

#15 baavgai  Icon User is offline

  • Dreaming Coder
  • member icon


Reputation: 6979
  • View blog
  • Posts: 14,598
  • Joined: 16-October 07

Re: Best Way to Handle Player Inventory?

Posted 12 June 2017 - 01:15 PM

Ah, the database... you might be putting the cart before the horse with that one. You want to know the kind of stuff you want to store. It's actually a pretty good Object Oriented design problem: and RDBMS' sort of suck at that.

I'd start with an EAV type thing, probably. This offers kind of the opposite, sucky RDBMS but ultimate flexibility of data: https://en.wikipedia...0%93value_model

Most of your NoSQL thingies do something like this. So does LDAP and by extention Active Directory.

So, everything, and I do mean everything, can be described with key value pairs. Keeping mind that a value can be a reference to another value.

I have a centeral datastore for lookups that literally has this one table:
CREATE TABLE [eav].[key_store](
	[entity_id] [uniqueidentifier] NOT NULL,
	[key_name] [varchar](250) NOT NULL,
	[key_value] [varchar](500) NOT NULL
)



Indeed, LDAP is some of the data I store there:
set @typeName = 'ad.Group'
  
SELECT NewId() as [entity_id], 'ad.Group' as typeName, a.distinguishedName, a.sAMAccountName, a.displayName, a.cn
  into #load
  FROM OPENQUERY(  ADSI, 
    '<LDAP://dc=pvsc,dc=com>;(&(objectCategory=group));distinguishedName,displayName,cn,sAMAccountName,company; subtree'
    ) a


insert into eav.key_store select [entity_id], 'type', typeName from #load
insert into eav.key_store select [entity_id], 'ad.distinguishedName', distinguishedName from #load where distinguishedName is not null
insert into eav.key_store select [entity_id], 'ad.cn', cn from #load where cn is not null
insert into eav.key_store select [entity_id], 'ad.sAMAccountName', cn from #load where sAMAccountName is not null
insert into eav.key_store select [entity_id], 'ad.displayName', displayName from #load where displayName is not null



Pulling it out, now, that's the interesting part:
select a.[entity_id], 
    b.key_value as cn,
    c.key_value as sAMAccountName,
    d.key_value as displayName,
    e.key_value as distinguishedName
  from eav.key_store a
    left join eav.key_store b on a.[entity_id]=b.[entity_id] and b.[key_name]='ad.cn'
    left join eav.key_store c on a.[entity_id]=c.[entity_id] and c.[key_name]='ad.sAMAccountName'
    left join eav.key_store d on a.[entity_id]=d.[entity_id] and d.[key_name]='ad.displayName'
    left join eav.key_store e on a.[entity_id]=e.[entity_id] and e.[key_name]='ad.distinguishedName'
  where a.[key_name]='type' and a.[key_value]='ad.Group'


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1