Raised This Month: $ Target: $400
 0% 

Code needed for String and Type conversions


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
souvikdas95
Senior Member
Join Date: Mar 2012
Old 04-02-2014 , 11:51   Code needed for String and Type conversions
Reply With Quote #1

Quote:
Originally Posted by Bugsy View Post
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 
Testid )
{
    new 
iStats] , iBHits];
    
    
//Get position in stats and stats data from csstats.dat
    
new iRankPos get_user_statsid iStats iBHits );
    
    
server_print"STATS BEFORE WRITE" );
    
    
//Read existing stats
    
ReadStats();
    
    
//Modify values to check if they change
    
iStats] = 1101;
    
iStats] = 1102;
    
iStats] = 1103;
    
iStats] = 1104;
    
iStats] = 1105;
    
iStats] = 1106;
    
iStats] = 1107;
    
iStats] = 1108;
    
    
//Write new values
    
WriteStatsiRankPos iStats iBHits );
    
    
server_print"STATS AFTER WRITE" );
    
    
//Read to see if changed after writing
    
ReadStats();
}
    
public 
ReadStats()
{
    new 
szFile64 ] , iFile;
    new 
iData10 ];
    new 
szString35 ] , iStringLen;
    new 
iStatsStats ] , iBHitsBodyHits ];
    
    
//Format the file name
    
copyszFileget_datadirszFile charsmaxszFile ) ) ] , charsmaxszFile ) , "/csstats.dat" );
    
    
//Open file for binary read
    
iFile fopenszFile "rb" );

    
//Read rank version
    
fread_rawiFile iData BLOCK_SHORT );
    
    if ( 
iData] != RANK_VERSION )
        
set_fail_state"Rank version does not match" );
    
    
//Read first name len (if 0, there are no player in stats file)
    
fread_rawiFile iData BLOCK_SHORT );
    
iStringLen iData] & 0xFFFF;

    while ( 
iStringLen )
    {        
        
//Read name
        
fread_rawiFile iData iStringLen BLOCK_CHAR );
        
ReadStringszString iStringLen charsmaxszString ) , iData );
        
server_print"Name: %s" szString );
        
        
//Read steamid len
        
fread_rawiFile iData BLOCK_SHORT );
        
iStringLen iData] & 0xFFFF;
        
        
//Read steamid
        
fread_rawiFile iData iStringLen BLOCK_CHAR );
        
ReadStringszString iStringLen charsmaxszString ) , iData );
        
server_print"SteamID: %s" szString );
        
        
//Read stats data
        
fread_rawiFile iStats STATS_SIZE BLOCK_INT );
        
server_print"%d %d %d %d %d %d %d %d %d %d %d" iStatsDamage ] ,
                                
iStatsKills ] ,
                                
iStatsDeaths ] ,
                                
iStatsTeamKills ] ,
                                
iStatsShots ] ,
                                
iStatsHits ] ,
                                
iStatsHeadshots ] ,
                                
iStatsPlants ] ,
                                
iStatsExplosions ] ,
                                
iStatsDefusions ] ,
                                
iStatsDefusalAttempts ] );
        
        
//Read body-hit data
        
fread_rawiFile iBHits BODYHITS_SIZE BLOCK_INT );
        
server_print"%d %d %d %d %d %d %d %d %d" iBHitsGeneric ] ,
                                
iBHitsHead ] ,
                                
iBHitsChest ] ,
                                
iBHitsStomach ] ,
                                
iBHitsLeftArm ] ,
                                
iBHitsRightArm ] ,
                                
iBHitsLeftLeg ] ,
                                
iBHitsRightLeg ] ,
                                
iBHits] );
        
        
//Read next players name len (if 0, end of stats)
        
fread_rawiFile iData BLOCK_SHORT );
        
iStringLen iData] & 0xFFFF;
    }
    
    
fcloseiFile );    
}

public 
WriteStatsiEntry iStatsCSX_STATS_SIZE ] , iBHitsCSX_BODYHITS_SIZE ] )
{
    new 
szFile64 ] , iFile;
    new 
iData10 ];
    new 
iStringLen;
    new 
iCurrentEntry;
    
    
copyszFileget_datadirszFile charsmaxszFile ) ) ] , charsmaxszFile ) , "/csstats.dat" );
    
    if ( !( 
iFile fopenszFile "rb+" ) ) )
        
set_fail_state"Error at file open" );
        
    
fread_rawiFile iData BLOCK_SHORT );
    
    if ( 
iData] != RANK_VERSION )
        
set_fail_state"Rank version does not match" );
    
    
fread_rawiFile iData BLOCK_SHORT );
        
    
iStringLen iData] & 0xFFFF;

    while ( 
iStringLen && ( ++iCurrentEntry <= iEntry ) )
    {
        
//Seek past the name data
        
fseekiFile iStringLen SEEK_CUR );
        
        
//Read steam-id len
        
fread_rawiFile iData BLOCK_SHORT );
        
iStringLen iData] & 0xFFFF;

        
//Seek past steam-id data
        
fseekiFile 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.
            
FixStatsOrderiStats );

            
//Write stats array
            
fwrite_rawiFile iStats CSX_STATS_SIZE BLOCK_INT )
            
//Only 8 of 11 ints are written so we seek past 3
            
fseekiFile , ( STATS_SIZE CSX_STATS_SIZE ) * BLOCK_INT SEEK_CUR );
            
            
//Write body-hit data
            
fwrite_rawiFile iBHits CSX_BODYHITS_SIZE BLOCK_INT );
            
//Only 8 of 9 ints are written so we seek past 1
            
fseekiFile , ( 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.
            
fseekiFile , ( ( STATS_SIZE BODYHITS_SIZE ) * BLOCK_INT ) , SEEK_CUR );
        }
        
        
fread_rawiFile iData BLOCK_SHORT );    
        
iStringLen iData] & 0xFFFF;
    }
    
    
fcloseiFile );    
}

FixStatsOrderiStats] )
{
    new 
iTmpStats];
    
    
iTmpStats iStats;

    for ( new 
i++ )
        
iStats] = iTmpStatsStatsTable] ]; 
}

ReadStringszDestString[] , iLen iMaxLen SourceData[] )
{
    new 
iStrPos = -1;
    new 
iRawPos 0;
    
    while ( ( ++
iStrPos iLen ) && ( iStrPos iMaxLen ) && ( iRawPos 10 ) )
    {
        
szDestStringiStrPos ] = ( SourceDataiRawPos ] >> ( ( iStrPos ) * ) ) & 0xFF;
    
        if ( 
iStrPos && ( ( iStrPos ) == ) )
            
iRawPos++
    }
    
    
szDestStringiStrPos ] = 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()

Last edited by souvikdas95; 04-02-2014 at 11:52.
souvikdas95 is offline
Shooting King
RAAASENGAN
Join Date: Mar 2012
Location: India
Old 04-04-2014 , 07:45   Re: Code needed for String and Type conversions
Reply With Quote #2

This thread should be in Module Coding section because Pawn does not have ints and shorts.
Quote:
Originally Posted by souvikdas95 View Post
1. I require conversion of int back to shortint
sizeof int > sizeof shortint
.'. MaxValue of int > MaxValue of short
.'. You cannot convert int to shortint properly. You CAN convert int to shortint if value of int is in the Range of shortint.

Quote:
Originally Posted by souvikdas95 View Post
2. I require WriteString() doing opposite work to that of ReadString()
XY Problem
__________________
As every time said, don't ever UNDERESTIMATE me.

Donate - Here
Shooting King is offline
Black Rose
Veteran Member
Join Date: Feb 2011
Location: Stockholm, Sweden
Old 04-04-2014 , 16:03   Re: Code needed for String and Type conversions
Reply With Quote #3

That ReadString() seems broken or I'm misunderstanding it.

EDIT: This is from nvault_util.inc:
Code:
stock ReadString( szDestString[] , iMaxLen , const SourceData[] , iSourceSize ) {     /*    Memory layout     szDest[ 0 ] = Source{ 3 }     szDest[ 1 ] = Source{ 2 }     szDest[ 2 ] = Source{ 1 }     szDest[ 3 ] = Source{ 0 }     szDest[ 4 ] = Source{ 7 }     szDest[ 5 ] = Source{ 6 }     szDest[ 6 ] = Source{ 5 }     szDest[ 7 ] = Source{ 4 }     szDest[ 8 ] = Source{ 11 }     */             new iDestPos = -1;     new iBytePos = 4;     new iOffset = 1;     new iSourceMax = ( iSourceSize * 4 );         while ( ( ++iDestPos < iMaxLen ) && ( iBytePos < iSourceMax ) )     {         szDestString[ iDestPos ] = SourceData{ iBytePos - iOffset++ };         if ( iDestPos && ( ( iDestPos % 4 ) == 3 ) )         {             iBytePos += 4;             iOffset = 1;         }     }         szDestString[ iDestPos ] = EOS; }

EDIT2: I made these now:
Never seen {} being used to write bytes before, only to define arrays. I had no idea you could do that.
Code:
#include <amxmodx> public plugin_init() {     register_plugin("Test Plugin 4", "", "[ --{-@ ]");         new Original[] = "Hello World";         server_print("^nOriginal:");     server_print("%s", Original);         new String1[4];     WriteString(String1, charsmax(String1), Original);         server_print("^nWriteString():");     for ( new i ; i < charsmax(String1) && String1[i] ; i++ )         server_print("%d: 0x%08x (%c%c%c%c)", i, String1[i], String1{i * 4} == 0 ? ' ' : String1{i * 4}, String1{i * 4 + 1} == 0 ? ' ' : String1{i * 4 + 1}, String1{i * 4 + 2} == 0 ? ' ' : String1{i * 4 + 2}, String1{i * 4 + 3});         new String2[12];     ReadString(String2, charsmax(String2), String1);         server_print("^nReadString():");     server_print("%s", String2); } stock ReadString(Output[], maxlen, const Input[]) {         new i, len = strlen(Input) * 4;         for ( ; i < len && i < maxlen ; i++ )         Output[i] = Input{i - i % 4 + ( 3 - i % 4 )};         Output[i] = 0; } stock WriteString(Output[], maxlen, const Input[]) {         new len, len2, i;     len = len2 = strlen(Input);     if ( len % 4 )         len2 += 4 - len % 4         for ( ; i < maxlen * 4 && i < len2 ; i++ )             Output{i - i % 4 + ( 3 - i % 4 )} = i < len ? Input[i] : 0;         Output[i / 4] = 0; }

Code:
Original:
Hello World

WriteString():
0: 0x6c6c6548 (lleH)
1: 0x6f57206f (oW o)
2: 0x00646c72 ( dlr)

ReadString():
Hello World
__________________

Last edited by Black Rose; 04-05-2014 at 08:29.
Black Rose is offline
souvikdas95
Senior Member
Join Date: Mar 2012
Old 04-05-2014 , 12:23   Re: Code needed for String and Type conversions
Reply With Quote #4

@Shooting King - True but assume that it's in range. CSX does that all the time during file save.
http://stackoverflow.com/questions/2...wise-operators
I liked the last given answer.

@Black Rose - Great! I will try and tell you if it works from my side as well

Last edited by souvikdas95; 04-05-2014 at 12:24.
souvikdas95 is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 05:57.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode