1919#include "mux/support/alloc.h"
2020
2121// Increment whenever the schema written by this module changes.
22- constexpr int GAMEDB_SCHEMA_VERSION = 14 ;
22+ constexpr int GAMEDB_SCHEMA_VERSION = 17 ;
2323
2424// Identifies SQLite as the storage implementation in snapshot metadata.
2525constexpr int GAMEDB_SOURCE_FORMAT_SQLITE = 1 ;
@@ -56,6 +56,8 @@ static const char schema_objects_sql[] =
5656 " next INTEGER NOT NULL,"
5757 " type INTEGER NOT NULL CHECK (type IN (0, 1, 2, 3, 5)),"
5858 " lua_parent TEXT NOT NULL DEFAULT '',"
59+ " description TEXT, inside_description TEXT,"
60+ " destroyer INTEGER,"
5961 " has_ansi_flag INTEGER NOT NULL DEFAULT 0 CHECK (has_ansi_flag IN (0, 1)),"
6062 " has_ansimap_flag INTEGER NOT NULL DEFAULT 0 CHECK (has_ansimap_flag IN "
6163 "(0, 1)),"
@@ -121,11 +123,6 @@ static const char schema_objects_sql[] =
121123 ");" ;
122124
123125static const char schema_state_sql [] =
124- "CREATE TABLE object_state ("
125- " object_dbref INTEGER PRIMARY KEY REFERENCES objects(dbref),"
126- " description TEXT, inside_description TEXT, admin_comment TEXT,"
127- " enter_alias TEXT, leave_alias TEXT, destroyer INTEGER"
128- ");"
129126 "CREATE TABLE player_state ("
130127 " object_dbref INTEGER PRIMARY KEY REFERENCES objects(dbref),"
131128 " password_hash TEXT, alias TEXT, last_login TEXT, last_name_change TEXT,"
@@ -155,53 +152,52 @@ typedef struct NativeColumn NativeColumn;
155152struct NativeColumn {
156153 int field ;
157154 const char * table ;
155+ const char * key_column ;
158156 const char * column ;
159157};
160158
161159static const NativeColumn native_columns [] = {
162- {A_DESC , "object_state" , "description" },
163- {A_IDESC , "object_state" , "inside_description" },
164- {A_COMMENT , "object_state" , "admin_comment" },
165- {A_EALIAS , "object_state" , "enter_alias" },
166- {A_LALIAS , "object_state" , "leave_alias" },
167- {A_DESTROYER , "object_state" , "destroyer" },
168- {A_PASS , "player_state" , "password_hash" },
169- {A_ALIAS , "player_state" , "alias" },
170- {A_LAST , "player_state" , "last_login" },
171- {A_LASTNAME , "player_state" , "last_name_change" },
172- {A_LOGINDATA , "player_state" , "login_data" },
173- {A_LASTSITE , "player_state" , "last_site" },
174- {A_LASTPAGE , "player_state" , "last_page" },
175- {A_TIMEOUT , "player_state" , "timeout" },
176- {A_QUEUEMAX , "player_state" , "queue_limit" },
177- {A_PRIVS , "player_state" , "privileges" },
178- {A_TZ , "player_state" , "timezone" },
179- {A_MECHPREFID , "btech_object_state" , "mech_preferred_id" },
180- {A_MAPCOLOR , "btech_object_state" , "map_color" },
181- {A_MECHSKILLS , "btech_object_state" , "mech_skills" },
182- {A_XTYPE , "btech_object_state" , "object_type" },
183- {A_TACSIZE , "btech_object_state" , "tactical_size" },
184- {A_LRSHEIGHT , "btech_object_state" , "lrs_height" },
185- {A_CONTACTOPT , "btech_object_state" , "contact_options" },
186- {A_MECHNAME , "btech_object_state" , "mech_name" },
187- {A_MECHTYPE , "btech_object_state" , "mech_type" },
188- {A_MECHDESC , "btech_object_state" , "mech_description" },
189- {A_MWTEMPLATE , "btech_object_state" , "mw_template" },
190- {A_FACTION , "btech_object_state" , "faction" },
191- {A_JOB , "btech_object_state" , "job" },
192- {A_RANKNUM , "btech_object_state" , "rank_number" },
193- {A_HEALTH , "btech_object_state" , "health" },
194- {A_ATTRS , "btech_object_state" , "character_attributes" },
195- {A_BUILDLINKS , "btech_object_state" , "build_links" },
196- {A_BUILDENTRANCE , "btech_object_state" , "build_entrances" },
197- {A_BUILDCOORD , "btech_object_state" , "build_coordinates" },
198- {A_ADVS , "btech_object_state" , "advantages" },
199- {A_PILOTNUM , "btech_object_state" , "pilot_dbref" },
200- {A_MAPVIS , "btech_object_state" , "map_visibility" },
201- {A_TECHTIME , "btech_object_state" , "tech_complete_at" },
202- {A_ECONPARTS , "btech_object_state" , "economy_parts" },
203- {A_SKILLS , "btech_object_state" , "skills" },
204- {A_PCEQUIP , "btech_object_state" , "personal_combat_equipment" },
160+ {A_DESC , "objects" , "dbref" , "description" },
161+ {A_IDESC , "objects" , "dbref" , "inside_description" },
162+ {A_DESTROYER , "objects" , "dbref" , "destroyer" },
163+ {A_PASS , "player_state" , "object_dbref" , "password_hash" },
164+ {A_ALIAS , "player_state" , "object_dbref" , "alias" },
165+ {A_LAST , "player_state" , "object_dbref" , "last_login" },
166+ {A_LASTNAME , "player_state" , "object_dbref" , "last_name_change" },
167+ {A_LOGINDATA , "player_state" , "object_dbref" , "login_data" },
168+ {A_LASTSITE , "player_state" , "object_dbref" , "last_site" },
169+ {A_LASTPAGE , "player_state" , "object_dbref" , "last_page" },
170+ {A_TIMEOUT , "player_state" , "object_dbref" , "timeout" },
171+ {A_QUEUEMAX , "player_state" , "object_dbref" , "queue_limit" },
172+ {A_PRIVS , "player_state" , "object_dbref" , "privileges" },
173+ {A_TZ , "player_state" , "object_dbref" , "timezone" },
174+ {A_MECHPREFID , "btech_object_state" , "object_dbref" , "mech_preferred_id" },
175+ {A_MAPCOLOR , "btech_object_state" , "object_dbref" , "map_color" },
176+ {A_MECHSKILLS , "btech_object_state" , "object_dbref" , "mech_skills" },
177+ {A_XTYPE , "btech_object_state" , "object_dbref" , "object_type" },
178+ {A_TACSIZE , "btech_object_state" , "object_dbref" , "tactical_size" },
179+ {A_LRSHEIGHT , "btech_object_state" , "object_dbref" , "lrs_height" },
180+ {A_CONTACTOPT , "btech_object_state" , "object_dbref" , "contact_options" },
181+ {A_MECHNAME , "btech_object_state" , "object_dbref" , "mech_name" },
182+ {A_MECHTYPE , "btech_object_state" , "object_dbref" , "mech_type" },
183+ {A_MECHDESC , "btech_object_state" , "object_dbref" , "mech_description" },
184+ {A_MWTEMPLATE , "btech_object_state" , "object_dbref" , "mw_template" },
185+ {A_FACTION , "btech_object_state" , "object_dbref" , "faction" },
186+ {A_JOB , "btech_object_state" , "object_dbref" , "job" },
187+ {A_RANKNUM , "btech_object_state" , "object_dbref" , "rank_number" },
188+ {A_HEALTH , "btech_object_state" , "object_dbref" , "health" },
189+ {A_ATTRS , "btech_object_state" , "object_dbref" , "character_attributes" },
190+ {A_BUILDLINKS , "btech_object_state" , "object_dbref" , "build_links" },
191+ {A_BUILDENTRANCE , "btech_object_state" , "object_dbref" , "build_entrances" },
192+ {A_BUILDCOORD , "btech_object_state" , "object_dbref" , "build_coordinates" },
193+ {A_ADVS , "btech_object_state" , "object_dbref" , "advantages" },
194+ {A_PILOTNUM , "btech_object_state" , "object_dbref" , "pilot_dbref" },
195+ {A_MAPVIS , "btech_object_state" , "object_dbref" , "map_visibility" },
196+ {A_TECHTIME , "btech_object_state" , "object_dbref" , "tech_complete_at" },
197+ {A_ECONPARTS , "btech_object_state" , "object_dbref" , "economy_parts" },
198+ {A_SKILLS , "btech_object_state" , "object_dbref" , "skills" },
199+ {A_PCEQUIP , "btech_object_state" , "object_dbref" ,
200+ "personal_combat_equipment" },
205201};
206202
207203/* Log either the SQLite error or the current operating-system error. */
@@ -555,10 +551,9 @@ static int gamedb_load_native_state(PersistenceContext *context,
555551 sqlite3_stmt * statement = nullptr ;
556552 int step ;
557553
558- snprintf (
559- query , sizeof (query ),
560- "SELECT object_dbref, CAST(%s AS TEXT) FROM %s WHERE %s IS NOT NULL;" ,
561- column -> column , column -> table , column -> column );
554+ snprintf (query , sizeof (query ),
555+ "SELECT %s, CAST(%s AS TEXT) FROM %s WHERE %s IS NOT NULL;" ,
556+ column -> key_column , column -> column , column -> table , column -> column );
562557 if (gamedb_prepare (sqlite , & statement , query ) < 0 )
563558 return -1 ;
564559 while ((step = sqlite3_step (statement )) == SQLITE_ROW ) {
@@ -667,7 +662,7 @@ static int gamedb_store_native_state(GameDatabase *database, sqlite3 *sqlite,
667662 sqlite3_stmt * statement = nullptr ;
668663 char query [256 ];
669664
670- const char * tables [] = {"object_state" , " player_state" , "btech_object_state" };
665+ const char * tables [] = {"player_state" , "btech_object_state" };
671666 for (size_t index = 0 ; index < sizeof (tables ) / sizeof (* tables ); index ++ ) {
672667 snprintf (query , sizeof (query ), "INSERT INTO %s (object_dbref) VALUES (?);" ,
673668 tables [index ]);
@@ -687,9 +682,8 @@ static int gamedb_store_native_state(GameDatabase *database, sqlite3 *sqlite,
687682
688683 if (!value )
689684 continue ;
690- snprintf (query , sizeof (query ),
691- "UPDATE %s SET %s = ? WHERE object_dbref = ?;" , column -> table ,
692- column -> column );
685+ snprintf (query , sizeof (query ), "UPDATE %s SET %s = ? WHERE %s = ?;" ,
686+ column -> table , column -> column , column -> key_column );
693687 if (gamedb_prepare (sqlite , & statement , query ) < 0 ||
694688 sqlite3_bind_text (statement , 1 , value , -1 , SQLITE_TRANSIENT ) !=
695689 SQLITE_OK ||
0 commit comments