| souvikdas95 |
04-02-2014 11:51 |
Code needed for String and Type conversions
Quote:
Originally Posted by Bugsy
(Post 1325056)
Well I coded reading and writing to csstats.dat successfully in Pawn but all changes made by my code are lost at map-change\restart since the csstats.dat file is open and being manipulated by csx module while the server is running. Someone will need to code this into the dll.
Here it is if anyone needs it for anything.
PHP Code:
#include <amxmodx> #include <amxmisc> #include <csx>
/* -- csstats.dat file structure -- * int16 - RANK_VERSION * uint16 - Bytes in first string (if 0, no entries) o sz - Name (read N bytes, where N is previous uint16) o uint16 - Bytes of next string o sz - Steam ID (read N bytes, where N is previous uint16) o uint32 - Team kills o uint32 - Damage o uint32 - Deaths o int32 - Kills o uint32 - Shots o uint32 - Hits o uint32 - Headshots o uint32 - Defusions o uint32 - Defusal Attempts o uint32 - Plants o uint32 - Explosions o uint32[9] - Body Hits (array of ints, one for each body hit area) o uint16 - If zero, end of file. Otherwise, loop back up and read the next name for this many bytes. */
const RANK_VERSION = 11;
//Array sizes for storing data in csstats.dat const STATS_SIZE = 11; const BODYHITS_SIZE = 9;
//Array sizes CSX functions use for reading data with natives const CSX_STATS_SIZE = 8; const CSX_BODYHITS_SIZE = 8;
enum _:Stats { TeamKills, //3 Damage, //6 Deaths, //1 Kills, //0 Shots, //4 Hits, //5 Headshots, //2 Defusions, //7 DefusalAttempts, Plants, Explosions }
enum _:BodyHits { Generic, Head, Chest, Stomach, LeftArm, RightArm, LeftLeg, RightLeg, Empty }
new StatsTable[] = { Kills, Deaths, Headshots, TeamKills, Shots, Hits, Damage, Defusions };
public plugin_init() { register_clcmd( "say hi" , "Test" ); }
public Test( id ) { new iStats[ 8 ] , iBHits[ 8 ]; //Get position in stats and stats data from csstats.dat new iRankPos = get_user_stats( id , iStats , iBHits ); server_print( "STATS BEFORE WRITE" ); //Read existing stats ReadStats(); //Modify values to check if they change iStats[ 0 ] = 1101; iStats[ 1 ] = 1102; iStats[ 2 ] = 1103; iStats[ 3 ] = 1104; iStats[ 4 ] = 1105; iStats[ 5 ] = 1106; iStats[ 6 ] = 1107; iStats[ 7 ] = 1108; //Write new values WriteStats( iRankPos , iStats , iBHits ); server_print( "STATS AFTER WRITE" ); //Read to see if changed after writing ReadStats(); } public ReadStats() { new szFile[ 64 ] , iFile; new iData[ 10 ]; new szString[ 35 ] , iStringLen; new iStats[ Stats ] , iBHits[ BodyHits ]; //Format the file name copy( szFile[ get_datadir( szFile , charsmax( szFile ) ) ] , charsmax( szFile ) , "/csstats.dat" ); //Open file for binary read iFile = fopen( szFile , "rb" );
//Read rank version fread_raw( iFile , iData , 1 , BLOCK_SHORT ); if ( iData[ 0 ] != RANK_VERSION ) set_fail_state( "Rank version does not match" ); //Read first name len (if 0, there are no player in stats file) fread_raw( iFile , iData , 1 , BLOCK_SHORT ); iStringLen = iData[ 0 ] & 0xFFFF;
while ( iStringLen ) { //Read name fread_raw( iFile , iData , iStringLen , BLOCK_CHAR ); ReadString( szString , iStringLen , charsmax( szString ) , iData ); server_print( "Name: %s" , szString ); //Read steamid len fread_raw( iFile , iData , 1 , BLOCK_SHORT ); iStringLen = iData[ 0 ] & 0xFFFF; //Read steamid fread_raw( iFile , iData , iStringLen , BLOCK_CHAR ); ReadString( szString , iStringLen , charsmax( szString ) , iData ); server_print( "SteamID: %s" , szString ); //Read stats data fread_raw( iFile , iStats , STATS_SIZE , BLOCK_INT ); server_print( "%d %d %d %d %d %d %d %d %d %d %d" , iStats[ Damage ] , iStats[ Kills ] , iStats[ Deaths ] , iStats[ TeamKills ] , iStats[ Shots ] , iStats[ Hits ] , iStats[ Headshots ] , iStats[ Plants ] , iStats[ Explosions ] , iStats[ Defusions ] , iStats[ DefusalAttempts ] ); //Read body-hit data fread_raw( iFile , iBHits , BODYHITS_SIZE , BLOCK_INT ); server_print( "%d %d %d %d %d %d %d %d %d" , iBHits[ Generic ] , iBHits[ Head ] , iBHits[ Chest ] , iBHits[ Stomach ] , iBHits[ LeftArm ] , iBHits[ RightArm ] , iBHits[ LeftLeg ] , iBHits[ RightLeg ] , iBHits[ 8 ] ); //Read next players name len (if 0, end of stats) fread_raw( iFile , iData , 1 , BLOCK_SHORT ); iStringLen = iData[ 0 ] & 0xFFFF; } fclose( iFile ); }
public WriteStats( iEntry , iStats[ CSX_STATS_SIZE ] , iBHits[ CSX_BODYHITS_SIZE ] ) { new szFile[ 64 ] , iFile; new iData[ 10 ]; new iStringLen; new iCurrentEntry; copy( szFile[ get_datadir( szFile , charsmax( szFile ) ) ] , charsmax( szFile ) , "/csstats.dat" ); if ( !( iFile = fopen( szFile , "rb+" ) ) ) set_fail_state( "Error at file open" ); fread_raw( iFile , iData , 1 , BLOCK_SHORT ); if ( iData[ 0 ] != RANK_VERSION ) set_fail_state( "Rank version does not match" ); fread_raw( iFile , iData , 1 , BLOCK_SHORT ); iStringLen = iData[ 0 ] & 0xFFFF;
while ( iStringLen && ( ++iCurrentEntry <= iEntry ) ) { //Seek past the name data fseek( iFile , iStringLen , SEEK_CUR ); //Read steam-id len fread_raw( iFile , iData , 1 , BLOCK_SHORT ); iStringLen = iData[ 0 ] & 0xFFFF;
//Seek past steam-id data fseek( iFile , iStringLen , SEEK_CUR ); //If current entry is the one we want to modify if ( iCurrentEntry == iEntry ) { //The order of stats saved to csstats.dat and the order used //by csx are different, this puts them in correct order. FixStatsOrder( iStats );
//Write stats array fwrite_raw( iFile , iStats , CSX_STATS_SIZE , BLOCK_INT ) //Only 8 of 11 ints are written so we seek past 3 fseek( iFile , ( STATS_SIZE - CSX_STATS_SIZE ) * BLOCK_INT , SEEK_CUR ); //Write body-hit data fwrite_raw( iFile , iBHits , CSX_BODYHITS_SIZE , BLOCK_INT ); //Only 8 of 9 ints are written so we seek past 1 fseek( iFile , ( BODYHITS_SIZE - CSX_BODYHITS_SIZE ) * BLOCK_INT , SEEK_CUR ); } else { //This is not the entry that we want to modify so we skip past //the stats and bodyhit data. fseek( iFile , ( ( STATS_SIZE + BODYHITS_SIZE ) * BLOCK_INT ) , SEEK_CUR ); } fread_raw( iFile , iData , 1 , BLOCK_SHORT ); iStringLen = iData[ 0 ] & 0xFFFF; } fclose( iFile ); }
FixStatsOrder( iStats[ 8 ] ) { new iTmpStats[ 8 ]; iTmpStats = iStats;
for ( new i = 0 ; i < 8 ; i++ ) iStats[ i ] = iTmpStats[ StatsTable[ i ] ]; }
ReadString( szDestString[] , iLen , iMaxLen , SourceData[] ) { new iStrPos = -1; new iRawPos = 0; while ( ( ++iStrPos < iLen ) && ( iStrPos < iMaxLen ) && ( iRawPos < 10 ) ) { szDestString[ iStrPos ] = ( SourceData[ iRawPos ] >> ( ( iStrPos % 4 ) * 8 ) ) & 0xFF; if ( iStrPos && ( ( iStrPos % 4 ) == 3 ) ) iRawPos++ } szDestString[ iStrPos ] = EOS; }
Code:
STATS BEFORE WRITE
Name: bugsy
SteamID: STEAM_0:0:12345
121 2 43 0 8274 2 0 7 7 2 2
0 0 0 2 0 0 0 0 0
STATS AFTER WRITE
Name: bugsy
SteamID: STEAM_0:0:12345
1103 1101 1107 1104 1105 1106 1102 7 7 1108 2
0 0 0 2 0 0 0 0 0
|
1. I require conversion of int back to shortint
2. I require WriteString() doing opposite work to that of ReadString()
|