void JPLua_Serialiser_IterateTableWrite( cJSON *parent, const char *name, lua_State *L ) { cJSON *table = cJSON_CreateArray(); int tableIndex = lua_gettop( L ); lua_pushnil( L ); // for each element while ( lua_next( L, -2 ) != 0 ) { cJSON *item = cJSON_CreateObject(); int keyType = lua_type( L, -2 ); int valueType = lua_type( L, -1 ); cJSON_AddIntegerToObject( item, "key_type", keyType ); if ( keyType == LUA_TSTRING ) { cJSON_AddStringToObject( item, "key", lua_tostring( L, -2 ) ); } else if ( keyType == LUA_TNUMBER ) { cJSON_AddIntegerToObject( item, "key", lua_tointeger( L, -2 ) ); } else { Com_Printf( "Can not serialise key in table %s: invalid type %s\n", name, lua_typename( L, keyType ) ); } cJSON_AddIntegerToObject( item, "value_type", valueType ); if ( valueType == LUA_TTABLE ) { if ( lua_rawequal( L, -1, tableIndex ) ) { Com_Printf( "Can not serialise key <FIXME> in table %s: self-references are fatal!\n", name ); cJSON_Delete( item ); lua_pop( L, 1 ); continue; } lua_pushvalue( L, -1 ); JPLua_Serialiser_IterateTableWrite( item, "value", L ); } else if ( valueType == LUA_TNUMBER ) { cJSON_AddNumberToObject( item, "value", lua_tonumber( L, -1 ) ); } else if ( valueType == LUA_TBOOLEAN ) { cJSON_AddIntegerToObject( item, "value", !!lua_toboolean( L, -1 ) ); } else if ( valueType == LUA_TSTRING ) { cJSON_AddStringToObject( item, "value", lua_tostring( L, -1 ) ); } else { Com_Printf( "Can not serialise value in table %s: invalid type %s\n", name, lua_typename( L, valueType ) ); cJSON_Delete( item ); lua_pop( L, 1 ); continue; } cJSON_AddItemToArray( table, item ); lua_pop( L, 1 ); } lua_pop( L, 1 ); cJSON_AddItemToObject( parent, name, table ); }
void G_WriteSessionData( void ) { int i; fileHandle_t f; const gclient_t *client = NULL; cJSON *root = cJSON_CreateObject(); cJSON_AddIntegerToObject( root, "gametype", level.gametype ); trap->Print( "G_WriteSessionData: writing %s...", metaFileName ); trap->FS_Open( metaFileName, &f, FS_WRITE ); Q_FSWriteJSON( root, f ); for ( i = 0, client = level.clients; i < level.maxclients; i++, client++ ) { if ( client->pers.connected == CON_CONNECTED ) { G_WriteClientSessionData( client ); } } trap->Print( "done\n" ); }
// Called on game shutdown void G_WriteClientSessionData( const gclient_t *client ) { const clientSession_t *sess = &client->sess; cJSON *root; fileHandle_t f; char fileName[MAX_QPATH] = {}; Com_sprintf( fileName, sizeof(fileName), "session/client%02i.json", (int)(client - level.clients) ); Com_Printf( "Writing session file %s\n", fileName ); root = cJSON_CreateObject(); cJSON_AddIntegerToObject( root, "sessionTeam", sess->sessionTeam ); cJSON_AddIntegerToObject( root, "spectatorNum", sess->spectatorNum ); cJSON_AddIntegerToObject( root, "spectatorState", sess->spectatorState ); cJSON_AddIntegerToObject( root, "spectatorClient", sess->spectatorClient ); cJSON_AddIntegerToObject( root, "wins", sess->wins ); cJSON_AddIntegerToObject( root, "losses", sess->losses ); cJSON_AddIntegerToObject( root, "setForce", sess->setForce ); cJSON_AddIntegerToObject( root, "saberLevel", sess->saberLevel ); cJSON_AddIntegerToObject( root, "selectedFP", sess->selectedFP ); cJSON_AddIntegerToObject( root, "updateUITime", sess->updateUITime ); cJSON_AddIntegerToObject( root, "duelTeam", sess->duelTeam ); cJSON_AddIntegerToObject( root, "siegeDesiredTeam", sess->siegeDesiredTeam ); cJSON_AddStringToObject( root, "saberType", *sess->saberType ? sess->saberType : "" ); cJSON_AddStringToObject( root, "saber2Type", *sess->saber2Type ? sess->saber2Type : "" ); cJSON_AddStringToObject( root, "IP", sess->IP ); cJSON_AddIntegerToObject( root, "connTime", sess->connTime ); cJSON_AddIntegerToObject( root, "noq3fill", sess->noq3fill ); cJSON_AddIntegerToObject( root, "validated", sess->validated ); cJSON_AddIntegerToObject( root, "adminRank", sess->adminRank ); cJSON_AddIntegerToObject( root, "canUseCheats", sess->canUseCheats ? 1 : 0 ); trap->FS_Open( fileName, &f, FS_WRITE ); Q_FSWriteJSON( root, f ); }
// called on game shutdown void G_WriteClientSessionData( const gclient_t *client ) { const clientSession_t *sess = &client->sess; cJSON *root; fileHandle_t f; char fileName[MAX_QPATH] = {}; Com_sprintf( fileName, sizeof(fileName), "session/client%02i.json", client - level.clients ); Com_Printf( "Writing session file %s\n", fileName ); root = cJSON_CreateObject(); cJSON_AddIntegerToObject( root, "sessionTeam", sess->sessionTeam ); cJSON_AddIntegerToObject( root, "spectatorTime", sess->spectatorTime ); cJSON_AddIntegerToObject( root, "spectatorState", sess->spectatorState ); cJSON_AddIntegerToObject( root, "spectatorClient", sess->spectatorClient ); cJSON_AddIntegerToObject( root, "wins", sess->wins ); cJSON_AddIntegerToObject( root, "losses", sess->losses ); cJSON_AddIntegerToObject( root, "setForce", sess->setForce ); cJSON_AddIntegerToObject( root, "saberLevel", sess->saberLevel ); cJSON_AddIntegerToObject( root, "selectedFP", sess->selectedFP ); cJSON_AddIntegerToObject( root, "duelTeam", sess->duelTeam ); cJSON_AddIntegerToObject( root, "siegeDesiredTeam", sess->siegeDesiredTeam ); cJSON_AddStringToObject( root, "siegeClass", *sess->siegeClass ? sess->siegeClass : "none" ); cJSON_AddStringToObject( root, "IP", sess->IP ); if ( client->pers.adminUser ) { char checksum[33] = {}; char combined[MAX_STRING_CHARS] = {}; Com_sprintf( combined, sizeof(combined), "%s%s", client->pers.adminUser->user, client->pers.adminUser->password ); Crypto::ChecksumMD5( combined, strlen( combined ), checksum ); cJSON_AddStringToObject( root, "admin", checksum ); } cJSON_AddBooleanToObject( root, "empowered", !!client->pers.adminData.empowered ); cJSON_AddBooleanToObject( root, "merc", !!client->pers.adminData.merc ); cJSON_AddBooleanToObject( root, "silenced", !!client->pers.adminData.silenced ); cJSON_AddBooleanToObject( root, "slept", !!client->pers.adminData.isSlept ); cJSON_AddIntegerToObject( root, "tempprivs", !!client->pers.tempprivs); trap->FS_Open( fileName, &f, FS_WRITE ); Q_FSWriteJSON( root, f ); }