Since earlier this month, it's gotten essentially unusable on The Silver Marches. I believe it's time to try to switch to a better implementation as soon as possible.
Our alternative seems to be newly enabled functions through NWNx4 which allow binary storage fields to be inserted into database tables, and retrieved later. So, this would use the same central SQL database which hosts all the other persistency data and log information for the ACR. This may cause some lag problems, since the data will have to be passed across the net to the central SQL server and back each time (and it's more bits and bytes than the simple string fields we trade regularly between the SQL server and each of the Live and Beta host machines). The upside is the inventories would be crosserver persistent, allowing things like Portable Holes, PC corpses that can be carried across server borders without losing their inventories, pack animals that can be lead between servers, etc.
We may even be able to implement a kind of cross-server Limbo function, whereby a DM on BG could limbo a plot NPC for a TSM DM to pull out for use on TSM and vice versa. Or, builders could make items in the right kind of build module, and "send" them directly into a DM chest on an ALFA server without need for a module update/reset/import/etc.
Neat stuff. Unfortunately need to do some thinking about implementation and experimenting with the functions. First step is designing the database table. I'm thinking for fields:
- ObjectID (integer, unique, primary key, assigned automatically)
- ContainerID (string, unique for each p-chest, allows grouping/selecting for the contents of any one container for retrieval)
- Name ( of the object, string field)
- CharacterID ( integer, foreign key, default NULL/0, optional PC or DM avatar to associate the record with)
- ServerID (integer, foreign key, optional server the object is associated with)
- ObjectType (Integer, uses convention from nwscript for Item vs. Creature)
- GPValue (integer, value of the object in GP)
- ObjectData(BLOB type, stores the actual data for the game object)
- Date (string, date the object was added to the database)
Does that sound sufficient? Gives us some handles to pull selectively from the table at least. It means we'll have one record in the DB for each item in any persistent chest/corpse/etc on every server, but I'm not sure how we'd get around that.
So, OnOpen for a p-chest (or OnModuleLoad), we'd SELECT all records from the database which had ContainerID = (the unique DB name of the pchest). This would return one record per item in the chest, which could be looped through to populate the chest with real in-game items. Then, we could update it piecemeal each time the inventory is disturbed (saving the "big hit" OnClose). So, you pull a Light Crossbow out of the chest, and a quick SQL DeleteRow fires across the net to remove that ObjectID. Put a dagger into the chest, and a (larger) query goes out Inserting a new row with the dagger's data, attaching value, the PC's ID, the database ID, etc. So, were the server to crash just then, the repopulation function would know to put a new dagger in the chest OnModuleLoad based on the data transmitted.
That's the theory at least. Will update with progress as I carve out some development time for testing/implementation.