I'm not really sure if Scripting Help is the best place for this, but here goes.
This thread will be more like a discussion than actual scripting help.
As the mod I'm working on (the one in my sig, CSRP) will have MANY sub-modules and will communicate with the database A LOT, I decided it's stupid to let each subplugin/submodule handle the database in their own way. I'm trying to create a complex class system to handle the data of the database easily, while the core plugin takes care of all the hard work. An example of some natives it should have:
PHP Code:
enum _:ClassColumnStruct
{
__szColumnName[ 16 ],
ClassColumnType: __iColumn,
__iMaxLen
}
enum Class
{
Class_Invalid = -1
}
enum ClassColumnType
{
Column_Varchar,
Column_Int
}
enum ClassReturn
{
Class_InvalidHandle = -1,
Class_DatabaseFailure,
Class_Success
}
// these are for player data
Class: CSRP_CreatePlayerClass( const szTable[ ], Array: aColumns, const szCallback[ ] )
ClassReturn: CSRP_GetPlayerClassData( id, Class: hClass, &Array: aResults )
ClassReturn: CSRP_PushPlayerClassData( id, Class: hClass, Trie: tData )
// these are for other data by key instead of player index
Class: CSRP_CreateKeyClass( const szTable[ ], Array: aColumns, const szCallback[ ] )
ClassReturn: CSRP_GetKeyClassData( const szKey[ ], Class: hClass, &Array: aResults )
ClassReturn: CSRP_PushKeyClassData( const szKey[ ], Class: hClass, Trie: tData )
// general stuff
ClassReturn: CSRP_DestroyClassHandle( &Class: hClass ) // destroys the class handle and releases everything from the memory
ClassReturn: CSRP_NukeClass( &Class: hClass ) // completely removes the class from the database and destroys the class handle
ClassReturn: CSRP_ClassForceSave( Class: hClass ) // forces the class to save itself
Example of usage:
PHP Code:
enum _: TestColumns
{
Column_PlayerName,
Column_PlayerAuthId
}
new Class: g_hClassHandle
new Array: aColumns = ArrayCreate( ClassColumnStruct )
new aColumnValues[ TestColumns ][ ClassColumnStruct ] =
{
{ "jail_lifttime", Column_Int, 11 },
{ "jail_name", Column_Varchar, 32 }
}
for( new i; i < TestColumns; i ++ )
{
ArrayPushArray( aColumns, aColumnValues[ i ] )
}
g_hClassHandle = CSRP_CreatePlayerClass( "csrp_jailtimer", aColumns, "_OnClassLoad" )
What should happen in the above: CSRP_CreatePlayerClass should create a table in the database called csrp_jailtimer with these columns:
Code:
key SMALLINT(5) UNSIGNED - since it's a player class, this will hold the unique player index
jail_lifttime INT(11)
jail_name VARCHAR(32)
The core should call _OnClassLoad once the class is properly initialized.
So far I know how to do that, no worries. However the problem happens when we talk about loading the actual data.
How would I want to do that technically? First, I thought about loading the entire table into memory. Trie for each row. Then I realized that's a terribad idea.
I'm now deciding on this: If the class is a player class (i.e. it holds data for each player), the player's data should be loaded on connect and saved and destroyed on disconnect. That seems reasonable and I think I'll stick with that, but what about non-player classes? For example a class that holds the list of all the items available for players to buy. These data need to be accessible all the time; should I just load them all on the class initialization and save/destroy them on mapchange, like I first wanted to? Or do you have a better idea?
Also, HOW would you store data from a table? The player index doesn't necessarily have to be unique. For example, if the class would be a player inventory class with the following columns:
Code:
key SMALLINT(5) UNSIGNED
item VARCHAR(32)
amount INT(11)
The data in the table can be as follows:
Code:
+-----+------------------+--------+
| key | item | amount |
+-----+------------------+--------+
| 1 | item_m4a1 | 3 |
| 1 | item_hamburger | 1 |
| 1 | item_flyingwings | 8 |
| 1 | item_flashlight | 7 |
| 15 | item_flashlight | 3 |
| 16 | item_awp | 16 |
| 4 | item_primaryammo | 8 |
+-----+------------------+--------+
Which means that a CSRP_GetPlayerClassData( 1, Some_Class_Handle, Array: aOutput ) native call will have to save something like this into the aOutput array in the parameters:
Code:
Array
{
Trie: { "item" : "item_m4a1", "amount" : 3 }
Trie: { "item" : "item_hamburger", "amount" : 1 }
Trie: { "item" : "item_flyingwings", "amount" : 8 }
Trie: { "item" : "item_flashlight", "amount" : 7 }
}
Which kinda blows. This wouldn't be a problem with PHP's array design, but I have ABSOLUTELY NO IDEA how to do this reasonably well in Pawn.
Let me know what you think about my whole design, I need to get this done ASAP.