This describes the Game Items (how they are managed on server -> loading,item generation, saving), but also adding a new item, item editing, deletion and management.
In order to understand this complex topic, lets have a look at the item-related classes and see what they do.
The Item classes' relationships are summarized in the following class diagram:
The user-level description of item functionality (general oveview / items guide for users) can be found.
In order to work with game items, there are 3 phases that we can be in.
Eighter we are loading/saving the items from / to sql database,
or we are sending the item via network,
or we are working with the items in real gameplay.
For all of these phases there are different sets of classes, and the classes allow conversion between one to another.
So why do we need 3 sets of classes for representing item, why can not be just have one, which can also send itself to client and be saved to database?
Unfortunatelly, when loading item from database, foreign key IDs must be loaded aswell, and later assemble the entire item using these IDs (match correct item prototype data with item stat generation intervals data). Additionally, when item is loaded for player, we load inventory ID, inventory position, etc., but in real gameplay, this is no longer needed, as the item instance is already parented to correct inventory class instance.
These inventory IDs, positions within inventory, and FK IDs would be completelly useless for the real gameplay, and they would just be confusing programeer:
,,Well, in CharacterOwnedItem there is inventory ID....well it is important I guess, if it is here...isn't it?"
However, some classes do not need another class representation for the other phases, such as StatsDAO, which can be sent to client, saved to database, and also is used in real gameplay...
The situation is depicted by following class diagram:
Here you can see, that CharacterOwnedItemDAO can be converted to CharacterOwnedItem. Also, CharacterOwnedItem can be converted to ItemPacket.
Let's now have a look on each of these classes, understanding what they do:
We start with saving / loading phase.
This takes place, whenever item is supposed to be loadedd / saved from / to sql database.
Rule of thumb: Classes for loading / saving reflect the SQL database tables
The situation usually is, that we want to load all items that some player owns. For that, we select all from CharacterOwnedItem table, and Instances table, and then (if item has foreign key defined), we proceed to Stats table, Weapon info table, sockets table etc.
As result, we assemble CharacterOwnedItemDAO, into which we nest all the other DAO classes, and we return the CharacterOwnedItemDAO to caller.
So, once data from all the tables is loaded, we get CharacterOwnedItemDAO. Using that, we get ItemPrototypeDAO (because we know the relevant sql ID), we get it from memory (see warning above). Then, we convert the CharacterOwnedItemDAO to CharacterOwnedItem, and using the info we got in the CharacterOwnedItemDAO, we put the converted structure to player's inventory or equipment, or bank...
Lastly, we discard all the database related DAO instances, and they are never used again.
For saving, the oeration is just inverse:
Contains the basic information about an item, such as text token, sqlID, inventory size,
stat generation intervals
Data from a database is loaded into these structures.
The main class we work with in gameplay is CharacterOwnedItem class.
This is used as a structure to identify an item that is owned by character.
Therefore, it has s stat structure or any info that is dynamic.
To know, where the item is (is in inventory, or in equipment?), we simply figure it out by looking in inventory instance / equopment for that user
Here we mainly operate with ItemPacket class, which allows to send the data for any item
Contains only the most inportant info about Item sockets to be sent.
Contains list of ItemPacket class instances (if item is inside a socket)
Contains stats for an Item, or for equipment, or for an ability. It is a versatile structure.
Two of these structures can be added or subtracted to allow easy stats manipulation.
If item is dropped, stats are generated for that item, and they are saved into this structure
Contains limits based upon which are the stats (StatsDAO) for the item generated.
Represents item as GameObject, that lies on the ground in a map (physically) and can be interacted with (can be picked up)
Contains CharacterOwnedItem which is (upon picking up) moved to player's inventory
There are few cases, when item must be sent to the client:
If an item is dropped on floor, it must be sent to client.
sent is following:
If an item is added to inventory or equipment, sent is following:
The process is illustrated by the following sequence diagram:
Problem can be, that user can have an item with already gereated stats,
and it would be saved in database.
However, admin would change the stat generation intervals via this webpage, which, however, does not change the stats of user's items.
For that, whenever user's items are loaded by game server, the stats loaded are clamped to match the relevant current stat generation intervals of that item.
In order to add a new item to the game fully, game server must be restarted after adding the item (because all items are loaded from the database only once upon start of server in game version 1.0.3)
In order to remove existing item from the game completelly, the game server must be shut down before the
This is because if there is Player playing game, having item A in inventory, if the item A would be deleted completely from the database, it is still in the memory of the server, and therefore, upon player logs out, the item will try to be saved to database.
That can cause undefined behavior because the item prototype is no longer in database.
In order to edit existing item, the game server also must be shut down before the editing.
Reasons are same as when removing the item.