// Byte serialization, written by Marco. Class ExtPlayerStat extends Object implements(ExtSaveDataBase); var int ArVersion,SaveNum; var transient int BufferOffset,BufferSize; var transient array<int> EOFStack; var array<byte> Buffer; var array<string> StrMap; const CurrentSaveVer=1; final function bool LoadStatFile( PlayerController Other ) { local string S; FlushData(); S = class'ServerExtMut'.Static.GetStatFile(Other.PlayerReplicationInfo.UniqueId); if( Class'Engine'.Static.BasicLoadObject(Self,S,false,CurrentSaveVer) ) { BufferSize = Buffer.Length; return true; } BufferSize = 0; Buffer.Length = 0; return false; } final function SaveStatFile( PlayerController Other ) { local string S; S = class'ServerExtMut'.Static.GetStatFile(Other.PlayerReplicationInfo.UniqueId); Class'Engine'.Static.BasicSaveObject(Self,S,false,CurrentSaveVer); } function SaveInt( int Value, optional byte MaxVal ) { ++MaxVal; if( (BufferOffset+MaxVal)>Buffer.Length ) { Buffer.Length = (BufferOffset+MaxVal); BufferSize = Buffer.Length; } Buffer[BufferOffset++] = Value & 255; if( MaxVal>1 ) { Buffer[BufferOffset++] = (Value >> 8) & 255; if( MaxVal>2 ) { Buffer[BufferOffset++] = (Value >> 16) & 255; if( MaxVal>3 ) Buffer[BufferOffset++] = (Value >> 24) & 255; } } } function int ReadInt( optional byte MaxVal ) { local int Res; ++MaxVal; if( (BufferOffset+MaxVal)>BufferSize ) return 0; Res = Buffer[BufferOffset++]; if( MaxVal>1 ) { Res = Res | (Buffer[BufferOffset++] << 8); if( MaxVal>2 ) { Res = Res | (Buffer[BufferOffset++] << 16); if( MaxVal>3 ) Res = Res | (Buffer[BufferOffset++] << 24); } } return Res; } function SaveStr( string S ) { local int i; if( S=="" ) { SaveInt(0,1); return; } S = Left(S,255); i = StrMap.Find(S); if( i==-1 ) { i = StrMap.Length; StrMap[StrMap.Length] = S; } SaveInt((i+1),1); } function string ReadStr() { local int i; i = ReadInt(1); if( i==0 || i>StrMap.Length ) return ""; return StrMap[i-1]; } function int TellOffset() { return BufferOffset; } function SeekOffset( int Offset ) { BufferOffset = Clamp(Offset,0,BufferSize); } function int TotalSize() { return BufferSize; } function ToEnd() { BufferOffset = BufferSize; } function ToStart() { BufferOffset = 0; } function bool AtEnd() { return (BufferOffset>=BufferSize); } function SkipBytes( int Count ) { BufferOffset = Clamp(BufferOffset+Count,0,BufferSize); } function FlushData() { ArVersion = 0; SaveNum = 0; BufferOffset = 0; BufferSize = 0; Buffer.Length = 0; EOFStack.Length = 0; StrMap.Length = 0; } final function DebugData() { local string S,SS; local array<byte> B; local int i; GetData(B); `Log("DEBUG DATA: Data size: "$B.Length); for( i=0; i<B.Length; ++i ) { S $= Chr(Max(B[i],1)); SS $= "."$B[i]; } `Log("DEBUG DATA: "$S); `Log("DEBUG DATA: "$SS); } function GetData( out array<byte> Res ) { local int i,l,o,j; Res = Buffer; Res.Insert(0,1); Res[0] = ArVersion; // Add string map to start. // Write string map length. Res.Insert(1,2); l = StrMap.Length; Res[1] = l & 255; Res[2] = (l >> 8) & 255; o = 3; // write each entry. for( i=0; i<StrMap.Length; ++i ) { l = Len(StrMap[i]); Res.Insert(o,l+1); Res[o++] = l; for( j=0; j<l; ++j ) Res[o++] = Asc(Mid(StrMap[i],j,1)); } } function SetData( out array<byte> S ) { local int i,o,l,j; ArVersion = S[0]; Buffer = S; // read string map length. StrMap.Length = Buffer[1] | (Buffer[2] << 8); o = 3; // read each string map entry. for( i=0; i<StrMap.Length; ++i ) { l = Buffer[o++]; StrMap[i] = ""; for( j=0; j<l; ++j ) StrMap[i] $= Chr(Buffer[o++]); } Buffer.Remove(0,o); BufferSize = Buffer.Length; } function int GetArVer() { return ArVersion; } function SetArVer( int Ver ) { ArVersion = Ver; } function PushEOFLimit( int EndOffset ) { EOFStack.AddItem(BufferSize); BufferSize = EndOffset; } function PopEOFLimit() { if( EOFStack.Length==0 ) { `Log(Self@"WARNING: Tried to pop one EoF stack down too far!!!"); return; // Whoops, error. } BufferSize = EOFStack[EOFStack.Length-1]; EOFStack.Length = EOFStack.Length-1; } function int GetSaveVersion() { return SaveNum; } function SetSaveVersion( int Num ) { SaveNum = Num; } defaultproperties { }