19 Mar, 2013, Idealiad wrote in the 21st comment:
Votes: 0
Sorressean said:
each component would get it's own table and ID. So you could do an association of objects to components (objid, componentid), but you have no way of knowing which ID you're actually using.


Could you explain that a little more? I'm pretty inexperienced with RDBs so I'm probably missing something. It seems like if you have objects in memory,

Obj1
Components: comp1, comp2

Obj2
Components: comp2, comp3

And you have DB tables

Component1
Obj1 dataA dataB dataC

Component2
Obj1 dataA dataB dataC
Obj2 dataA dataB dataC

Component3
Obj2 dataA dataB dataC

Then it looks straightforward to load the correct components to objects.
19 Mar, 2013, Sorressean wrote in the 22nd comment:
Votes: 0
yeah. Each component would have a separate table. Container would look like:
capacity|weight|…
so each component could get an ID, but you have no way of associating an id with a specific object. you could have a components table that has id|objid|componentid, but you don't know which component table to reference.
19 Mar, 2013, Idealiad wrote in the 23rd comment:
Votes: 0
Each component type only has one table. The onlykey is the object uuid. That key is in every component table. Each object has a list of components. What could be easier? Tell me what is wrong here.


edit:

Just want to expand on this. I'm not understanding the problem so maybe it's one of my assumptions…

Say you have some object data in a table like

ObjectID | Name | ComponentList

So you load those into memory and now you have,

Object1
ID1
'A fireproof container'
ComponentList: fireproof, container

Object2
ID2
'A waterproof container'
ComponentList: container, waterproof

So you have component tables like

Fireproof
Container
Waterproof

And now you load that data into the objects, where a component table looks like:

ObjID | dataA | dataB

Say the fireproof container gets enchanted and now it's also waterproof. You add that component to Object1. The code creates a new row in the table for Waterproof with ID1 and the appropriate data.

That's what I'm talking about, so where am I going wrong?
19 Mar, 2013, Nathan wrote in the 24th comment:
Votes: 0
I think that example model is flawed, because container and waterproof are more like a property of something than a component. A better example might be a sword where the blade, hilt, and crosspiece are considered components of any given sword.

ObjectID | Name | ComponentList

Object1
ID1
'A longsword'
ComponentList: hilt, crosspiece, blade1

Object2
ID2
'A shortsword'
ComponentList: hilt, crosspiece, blade2



Maybe I misunderstand, but wouldn't there be a single component table with all possible components and a single
object table (holding the data that is then loaded into memory)? For the example above:

Components
id | name
—+———–
0 | hilt
1 | crosspiece
2 | blade1
3 | blade2

Objects
id | name | components
—+————+————————–
1 | longsword | hilt, crosspiece, blade1
2 | shortsword | hilt, crosspiece, blade2

but you'd see the object table as below, because each value in the components is an id (or collection of ids)
into the components table.

Objects
id | name | components
—+————+———–
1 | longsword | 0, 1, 2
2 | shortsword | 0, 1, 3
19 Mar, 2013, quixadhal wrote in the 25th comment:
Votes: 0
Being a fairly experienced DBA myself, I'm curious why you think having multiple tables is bad?

Let's say you have a player object with an inventory that contains weapons, armor, and misc objects. For simplicity, no containers, but that's just another layer…

create table object_types (
id integer primary key not null,
name unique text not null
);

insert into object_types(id, name) values (1, 'player');
insert into object_types(id, name) values (2, 'weapon');
insert into object_types(id, name) values (3, 'armor');
insert into object_types(id, name) values (4, 'misc');

create table uuids (
uuid text primary key not null
);

create table players (
uuid text unique not null references uuids(uuid),
name text unique not null
);

create table weapons (
uuid text unique not null references uuids(uuid),
name text unique not null
);

create table armors (
uuid text unique not null references uuids(uuid),
name text unique not null
);

create table misc_objects (
uuid text unique not null references uuids(uuid),
name text unique not null
);

create table player_inventories (
player_uuid integer not null references players(uuid),
object_type_id integer not null references object_types(id),
object_uuid integer not null references uuids(uuid)
);


So, with that table structure, your player might have a sword and a set of gloves. Since you want a uuid to be unique across all items, when you create
a new thing you make one of those first, then you make an object of the right type and associate it.

insert into uuids(uuid) values ('uuid-with-dashes-1'); – whatever algorithm makes a unique uuid

insert into players(name, uuid) values ('sorressean', 'uuid-with-dashes-1');
insert into weapons (name, uuid) values ('longsword', 'uuid-with-dashes-21');
insert into armors(name, uuid) values ('chainmail gloves', 'uuid-with-dashes-37');
insert into misc_objects(name, uuid) values ('apple', 'uuid-with-dashes-117');

Now that the items exist, you can fill the inventory.

insert into player_inventories(player_uuid, object_type_id, object_uuid) values ('uuid-with-dashes-1', 2, 'uuid-with-dashes-21');
insert into player_inventories(player_uuid, object_type_id, object_uuid) values ('uuid-with-dashes-1', 3, 'uuid-with-dashes-37');
insert into player_inventories(player_uuid, object_type_id, object_uuid) values ('uuid-with-dashes-1', 4, 'uuid-with-dashes-117');


When you pull data out, you can join the tables to get your data in a more useful way. If you do it often, define a view so you don't need to type as much.

NOTE: You can choose to use the object_type_id to pull only from the players table joined with the appropriate object table, *OR* you can join ALL the tables and just have NULL's returned for the tables that are the wrong type.
19 Mar, 2013, Nathan wrote in the 26th comment:
Votes: 0
Idealiad said:
Sorressean said:
each component would get it's own table and ID. So you could do an association of objects to components (objid, componentid), but you have no way of knowing which ID you're actually using.


Could you explain that a little more? I'm pretty inexperienced with RDBs so I'm probably missing something. It seems like if you have objects in memory,

Obj1
Components: comp1, comp2

Obj2
Components: comp2, comp3

And you have DB tables

Component1
Obj1 dataA dataB dataC

Component2
Obj1 dataA dataB dataC
Obj2 dataA dataB dataC

Component3
Obj2 dataA dataB dataC

Then it looks straightforward to load the correct components to objects.


In this case it appears that you have a table for each component that lists the objects that have it? Not sure I get what dataA, dataB, dataC are supposed to hold.
19 Mar, 2013, Idealiad wrote in the 27th comment:
Votes: 0
@Nathan, dataA, dataB, etcetera are just the properties of the component. So for a container it might be capacity, maxSize, etcetera.

I think whether you consider Fireproof a component or not is more a consequence of what you mean when you say 'component'; in a "component system" usually alldata is contained in components.

You could have a table that associates component ids to components, but this seems largely unnecessary to me if you can just put the component type list in the object.
19 Mar, 2013, Sorressean wrote in the 28th comment:
Votes: 0
First, a component is a feature of an object. So: lets take the worn component:
id|location
now for the container component:
id|capacity|weight

So when a builder creates a virtual object, they attach the worn component and the container component to make a backpack, then edit attributes on that component.
So now, my objects need to store a reference to each component.
As someone pointed out you could somehow just store a component list, maybe in a components table:
id|objid|componentid
but you need some way of determining what table it belongs to. For example an id of 3 might mean it needs a worn or container component whose ID is 3.
there really isn't a way to model this from within sql itself unless you have a table per component that links object ids with component ids.
19 Mar, 2013, Idealiad wrote in the 29th comment:
Votes: 0
@Sorressean, why don't you just store the component list on the virtual object. The virtual object is saved in a table like ObjID | ComponentList. Why do you need component IDs?
19 Mar, 2013, plamzi wrote in the 30th comment:
Votes: 0
Sorressean said:
I've explained why I actualy can't use a databvase.
Someone's random one-off "just store components in a table" doesn't work all that well; each component would get it's own table and ID. So you could do an association of objects to components (objid, componentid), but you have no way of knowing which ID you're actually using.

I like the API idea, but it's something that would be incredibly slow to use for updating and retrieving data for the mud. It would honestly be easier to handle sql stuff on the c++ side rather than going to a script that would actually do the same.


As someone who has been storing everything in the game (including all kinds of item states) in MySQL, I think the obstacles you are perceiving have to do entirely with your approach to the problem. You can't just over-impose your object-oriented code logic on the database and declare that it won't do. Learn some new things about database schema design and I'm sure that you'll discover it's flexible enough to store and return anything you need, the way you need it.

P. S.
If you're having trouble designing tables for entities with lots of properties, serializing them for storage is not a bad punt. I find that it can save a lot of time, it keeps the number of tables down, and depending on how you store the data, it can also give you a way to edit items directly in the database because the string may be human-readable.
20.0/30